Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8330258

C2: Continuous uncommon traps from null virtual call receivers

XMLWordPrintable

      We have seen a production case where one the of the virtual call receivers got folded into a constant null, and then C2 started doing uncommon traps to get to the exception path.

      Simplest way to reproduce follows:

      ```
      @BenchmarkMode(Mode.AverageTime)
      @OutputTimeUnit(TimeUnit.NANOSECONDS)
      @Fork(1)
      @Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
      @Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
      @State(Scope.Thread)
      public class NullReceiver {

          static final Object CONSTANT_OBJ = null;

          @Benchmark
          public String test() {
              try {
                  return CONSTANT_OBJ.toString();
              } catch (NullPointerException e) {
                  return "Boo";
              }
          }
      }
      ```

      It produces the attached flamegraph: null-receiver-uncommon-trap.

      `-XX:+TraceDeoptimization` on current mainline produces a stream of "deopt" events with reason=null_check action=none:

      ```
      UNCOMMON TRAP method=org.openjdk.NullReceiver.test()Ljava/lang/String; bci=3 pc=0x00000001148506e8, relative_pc=0x0000000000000068, debug_id=0 compiler=c2 compile_id=727 (@0x00000001148506e8) thread=26115 reason=null_check action=none unloaded_class_index=-1 debug_id=0
      DEOPT PACKING thread=0x00000001259ada10 vframeArray=0x000000015800c410
         Compiled frame (sp=0x0000000171959f40 unextended sp=0x0000000171959f40, fp=0x0000000171959ff0, real_fp=0x0000000171959f60, pc=0x00000001148506e8)
           nmethod6032 727 ! 4 org.openjdk.NullReceiver::test (11 bytes)
         Virtual frames (innermost/newest first):
            VFrame 0 (0x00000001258bec20) - org.openjdk.NullReceiver.test()Ljava/lang/String; - invokevirtual @ bci=3
      ```

      I think it is from here:
       https://github.com/openjdk/jdk/blob/3f1d9c441ea98910d9483e133bccfac784db393d/src/hotspot/share/opto/callGenerator.cpp#L238-L240

      Arguably, calling virtual methods on known-null receiver is an antipattern, which we can avoid by checking for receiver null-ness explicitly. But it can also be the result of optimizations, which lets compiler know about receiver null-const-ness. It might be good if we can avoid doing this uncommon-trap dance and "just" throw the exception directly, as long as it is easy to do.

            Unassigned Unassigned
            shade Aleksey Shipilev
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: