How to get rid of MethodHandle::linkTo* call when target method is known but not inlined?
Dean Long
dean.long at oracle.com
Sun Feb 15 07:08:04 UTC 2015
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