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

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Mon Feb 16 18:12:45 UTC 2015


Dean,

Yes, either an additional pass over code cache to update all stale 
Method* or a level of indirection (MemberName) is needed to keep class 
redefinition working.

Having MemberName instance instead of Method* for java.lang.invoke use 
case looks fine to me. But if it is useful for other use cases, working 
with VM metadata is more flexible IMO.

Best regards,
Vladimir Ivanov

On 2/15/15 10:08 AM, Dean Long wrote:
> OK, let's consider your original idea.  If you attach a pre-resolved
> target method (Method*) to the nmethod,
> don't you have a problem if the class gets redefined?  You may need to
> attach the MemberName instead,
> so that MemberNameTable::adjust_method_entries updates the Method *.  I
> assume that when the class
> gets redefined, there is some mechanism to force the call site to get
> re-resolved?
>
> dl
>
>
>
> On 2/13/2015 1:46 PM, Vladimir Ivanov wrote:
>>>> Do you suggest to create prelinked call site and skip fixup logic?
>>>
>>> That was my naive suggestion.
>>>
>>>> Considering VM sometimes resets call sites (e.g. class redefinition
>>>> happens), it becomes complicated. The call site should either stay
>>>> "resolvable" or special patching logic should be introduced.
>>>
>>> What happens currently, when we are calling linkToStatic with a constant
>>> MemberName, and the class gets redefined?
>>> Do we patch/reset the inline MemberName constant?
>>
>> No, we don't touch the inlined constant, but vmtarget field is updated
>> instead (see MemberNameTable::adjust_method_entries).
>>
>> Best regards,
>> Vladimir Ivanov
>>
>>>
>>> dl
>>>
>>>> Best regards,
>>>> Vladimir Ivanov
>>>>
>>>> On 2/13/15 9:17 AM, Dean Long wrote:
>>>>> OK, I think I understand what you are suggesting.  My idea is a little
>>>>> different.  When you see
>>>>> "invokestatic  MH.linkToStatic" in the bytecodes, and the
>>>>> MemberName is
>>>>> constant, how about
>>>>> if you extract the Method * from the MemberName, then generate a
>>>>> CallStaticJava?  So you
>>>>> are basically inlining linkToStatic as a special case, regardless
>>>>> of the
>>>>> inlining depth.
>>>>>
>>>>> dl
>>>>>
>>>>> On 2/12/2015 1:09 AM, Vladimir Ivanov wrote:
>>>>>> 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