On Jul 9, 2014, at 8:04 PM, John Rose <john.r.r...@oracle.com> wrote:

> On Jul 9, 2014, at 3:14 AM, Paul Sandoz <paul.san...@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.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to