[9] RFR (M): 8037209: Improvements and cleanups to bytecode assembly for lambda forms
Paul Sandoz
paul.sandoz at oracle.com
Thu Jul 10 16:10:11 UTC 2014
On Jul 9, 2014, at 8:04 PM, John Rose <john.r.rose at oracle.com> wrote:
> On Jul 9, 2014, at 3:14 AM, Paul Sandoz <paul.sandoz at oracle.com> wrote:
>
>>
>> I quickly verified the fold up does as you expect. Also, if i do the following the null check goes away:
>>
>> ...
>>
>> void testLoop() {
>> for (int i = 0; i < 1000000; i++) {
>> testLoopOne(a);
>> testLoopOne(snull);
>> }
>> }
>
> Good observation. So rather than missing a null-case fold-up (good it's not!), the optimizer is speculating not-nullness (based on profile) and adding a test. (Either the test is being used for a downstream optimization, or else the test is not being detected as useless and removed—which would be bad!.)
>
I guess it's the pesky null check in the class cast causing issues:
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}
>> I am probably obsessing too much over some micro/nano-benchmarks,
>
> (Hi, I'm John and I'm a micro-obsess-aholic.)
>
:-)
>> but i am wondering if this could cause some unwanted de-opt/recompilation effects when all is good with no null values then suddenly a null triggers de-optimization.
>
> Besides jumping after the micro-benchmark and chewing on the optimizer until the code shrinks, there are two other things we can do:
>
> 1. Mentally file the issue and watch real benchmarks for evidence of the problem. (This works pretty well, provided enough time and focus, and provided enough people have some consciousness of the optimizer's workings.)
>
> 2. Create a self-test and check it into the test base. It could be either a unit test of assertion. In this case, I don't see an easy way to do it, but creating clever permanent tests almost always pays off much better than cleverly pounding on the micro-benchmark of the moment.
>
How about the a variant of following?
public class NullCheckDroppingsTest {
volatile String svalue = "A";
volatile String snull = null;
String ssink;
public static void main(String[] args) {
NullCheckDroppingsTest t = new NullCheckDroppingsTest();
t.testLoop();
}
void testLoop() {
// Ensure testLoopOne is compiled and does not
// see a null value
for (int i = 0; i < 1000000; i++) {
testLoopOne(svalue);
// Uncomment the following and the call outside
// the loop should not result in any deoptimization
// testLoopOne(snull);
}
// Sleep just to create delay in the compilation log
try {
Thread.currentThread().sleep(1000);
} catch (Exception e) {}
// This should cause a de-optimisation
// if testLoopOne is compiled with a null-check
testLoopOne(snull);
}
void testLoopOne(String s) {
try {
ssink = String.class.cast(s);
} catch (Throwable t) {
throw new Error(t);
}
}
}
$ java -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation NullCheckDroppingsTest
64 1 java.lang.String::hashCode (55 bytes)
69 2 java.lang.String::indexOf (70 bytes)
81 3 ! NullCheckDroppingsTest::testLoopOne (27 bytes)
81 5 n java.lang.Class::isInstance (native)
81 4 java.lang.Class::cast (27 bytes)
82 6 % ! NullCheckDroppingsTest::testLoop @ 2 (45 bytes)
85 6 % ! NullCheckDroppingsTest::testLoop @ -2 (45 bytes) made not entrant
1086 3 ! NullCheckDroppingsTest::testLoopOne (27 bytes) made not entrant
The log can be searched to see of a deopt ("made not entrant") occurred or not.
Paul.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 841 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20140710/a315a4b4/signature.asc>
More information about the mlvm-dev
mailing list