choxsword
choxsword

Reputation: 3359

why does optimized virtual calls point to same address in hotspot jit assembly?

here is an article introducing the jit optimization strategy of virtual calls.

But what surpised me is that all optimized virtual calls use same address, like callq 0x000000011418ea00 in the article.

So I'm curious about what it actually does in that address, and how it knows which function to call, since all optimized virtual calls are directed to the same address.

Upvotes: 3

Views: 229

Answers (1)

yugr
yugr

Reputation: 21955

My understanding is that there is another optimization happening under the hood, identical code folding.

Code for CustObj::methodCall and CustObj2::methodCall are very similar and differ only by printed string. JVM compiler is thus able to generate identical code for them:

$ javac tmp.java
$ javap -c -constants 'TestVirtualCall2$CustObj.class'
Compiled from "tmp.java"
class TestVirtualCall2$CustObj {
  public void methodCall();
    Code:
       0: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
       3: lconst_0
       4: lcmp
       5: ifne          16
       8: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      11: ldc           #4                  // String CustObj is very good!
      13: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      16: return
}
$ javap -c -constants 'TestVirtualCall2$CustObj2.class'
Compiled from "tmp.java"
class TestVirtualCall2$CustObj2 extends TestVirtualCall2$CustObj {
  public final void methodCall();
    Code:
       0: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
       3: lconst_0
       4: lcmp
       5: ifne          16
       8: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      11: ldc           #4                  // String CustObj2 is very good!
      13: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      16: return
}

Note that even string loading command ldc #4 happens to be the same because compiler put strings into same locations in respective classes constant pools.

So JIT will definitely generate just one instance of x86 code for both virtual methods.

P.S.

I think this optimization is more of a random side-effect and wasn't the author's intent. It may make sense to ask him to do more changes for code in CustObj2 class in next revision of his article.

Upvotes: 1

Related Questions