How to get rid of MethodHandle::linkTo* call when target method is known but not inlined?
Dean Long
dean.long at oracle.com
Mon Feb 16 18:53:08 UTC 2015
On 2/16/2015 10:12 AM, Vladimir Ivanov wrote:
> 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.
>
Another option could be to attach a constant pool to the nmethod, then
add Method *'s to that constant pool.
The reason for using a constant pool is because that's what the resolve
logic is already using.
dl
> 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