How to get rid of MethodHandle::linkTo* call when target method is known but not inlined?

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Thu Feb 12 09:09:31 UTC 2015


Dean,

No, the problem is not with detecting compile-time constants, but how to 
pass that info to runtime in some situations.

The code for some particular DirectMethodHandle is the following:
   static int invokeStatic_005_I(java.lang.Object);
          0: aload_0
          1: invokestatic  #16                 // Method 
java/lang/invoke/DirectMethodHandle.internalMemberName:(Ljava/lang/Object;)Ljava/lang/Object;
          4: astore_1
          5: aload_1
          6: checkcast     #18                 // class 
java/lang/invoke/MemberName
          9: invokestatic  #24                 // Method 
java/lang/invoke/MethodHandle.linkToStatic:(Ljava/lang/invoke/MemberName;)I
         12: ireturn

If DMH is constant, it's easy to extract MemberName from it, and 
compiler can inline the method this MemberName points to (see 
CallGenerator::for_method_handle_inline):

The problematic case is when the method MemberName points to isn't 
inlined (for example, recursion depth is over the limit):
java.lang.invoke.LambdaForm$DMH005/359023572::invokeStatic_005_I (13 
bytes)   force inline by annotation
   @ 1   java.lang.invoke.DirectMethodHandle::internalMemberName (8 
bytes)   force inline by annotation
   @ 9   jsr292.RecursiveCall::f1 (4 bytes) recursive inlining is too deep

Right now, compiler stops at ::linkTo* call, and not at ::f1, though 
MemberName is constant and embedded into the code:

  0x000000010feeabfe: movabs $0x79561d2a0,%rdx ; {oop(a 
'java/lang/invoke/MemberName' = {method} {0x00000001180a3528} 'rec' 
'(I)V' in 'jsr292/RecursiveCall')}
   0x000000010feeac08: nop
   0x000000010feeac09: nop
   0x000000010feeac0a: nop
   0x000000010feeac0b: callq 0x000000010fe49900 ; OopMap{off=48}

It is either both ::linkTo* & target method are inlined or none of them.

What I want to get is a direct call to ::f1 instead. The problem is 
fixup logic (SharedRuntime::find_callee_info()) doesn't know anything 
about ::f1. What it sees in bytecode is ::linkTo* which is completely 
opaque.

The idea is to attach Method* (or MemberName?) to the nmethod and 
associate it with the call site. SharedRuntime::find_callee_info() can 
use it when it resolves the call site.

Best regards,
Vladimir Ivanov

On 2/12/15 4:09 AM, Dean Long wrote:
> I'm not an expert, but it appears that we generate code for linkTo*
> intrinsics using the assembler, so the compiler,
> which is good at detecting compile-time constants, isn't allowed to do
> what it's good at.  What if we implement
> all linkTo* intrinsics (or linkToStatic at least) using IR instead?
>
> dl
>
> On 2/11/2015 3:37 PM, Vladimir Ivanov wrote:
>> Hi,
>>
>> I'm looking at JDK-8072008 [1]. The idea is to get rid of linkTo* call
>> when MemberName is a compile-time constant, but target method isn't
>> inlined. Direct call to target method is issued instead. It should
>> help recursive calls, for example.
>>
>> The problem is that compiled call sites start in unlinked state and
>> runtime lacks information to patch them with a correct method (what it
>> sees during fixup is just a linkTo* call).
>>
>> The only way I see how to get call site linking working is to attach
>> pre-resolved target method (Method*) to the nmethod and make fixup
>> logic aware of it, so it can skip bytecode inspection step (in
>> SharedRuntime::find_callee_info()).
>>
>> Do you see any problems with such approach?
>> Any other ideas how to fix original problem?
>>
>> Thanks!
>>
>> Best regards,
>> Vladimir Ivanov
>>
>> [1] https://bugs.openjdk.java.net/browse/JDK-8072008
>


More information about the hotspot-compiler-dev mailing list