RFR[13]: 8227260: Can't deal with SharedRuntime::handle_wrong_method triggering more than once for interpreter calls
coleen.phillimore at oracle.com
coleen.phillimore at oracle.com
Mon Jul 8 19:34:27 UTC 2019
One comment
On 7/5/19 7:14 AM, Vladimir Ivanov wrote:
> Thanks for diagnosing the issue, Erik!
>
> Can you elaborate, please, on relation to clinit barrier in c2i?
>
> I don't see how it is possible to hit clinit barrier during i2c2i
> transition. Template interpreter has clinit barrier as part of
> invokestatic handler [1], so by the time c2i is reached, proper checks
> should be already performed and all the conditions to pass the barrier
> should be met.
>
> If SR::handle_wrong_method is called from clinit barrier in c2i during
> i2c2i, it signals about a bug in the new clinit logic: somehow clinit
> barrier is bypassed in interpreter.
>
> Are you sure it is not related to upcalls from native code
> (caller_frame.is_entry_frame() [1])?
>
> Also, SR::handle_wrong_method() calls coming from clinit barriers
> shouldn't hit the fast path w/ callee_target(), because it bypasses
> the actual initialization check happening during call site re-resolution.
>
> Best regards,
> Vladimir Ivanov
>
> PS: regarding clearing JavaThread::_callee_target in
> JavaThread::oops_do(), I'd prefer to keep it and limit the exposure of
> a stale Method*. But it's just a matter of preference and I don't have
> a strong opinion here.
The callee_method in JavaThread::oops_do() won't keep the Method*
alive. I'm not sure what keeps it alive in the callee_method field.
Can there be a GC now with some Method* that you need there?
In that case, you should put the
callee_method->method_holder()->java_mirror() in a new field in
JavaThread::_callee_mirror or something, and have JavaThread::oops_do
walk that. Also, redefinition might have to keep the callee_method
alive in the metadata walk, but you can file a separate bug for that if
I'm not too confused.
Coleen
>
> [1]
> src/hotspot/share/runtime/sharedRuntime.cpp:
>
> JRT_BLOCK_ENTRY(address,
> SharedRuntime::handle_wrong_method(JavaThread* thread))
> ...
> if (caller_frame.is_interpreted_frame() ||
> caller_frame.is_entry_frame()) {
>
>
> On 04/07/2019 18:02, Erik Österlund wrote:
>> Hi,
>>
>> The i2c adapter sets a thread-local "callee_target" Method*, which is
>> caught (and cleared) by SharedRuntime::handle_wrong_method if the i2c
>> call is "bad" (e.g. not_entrant). This error handler forwards
>> execution to the callee c2i entry. If the
>> SharedRuntime::handle_wrong_method method is called again due to the
>> i2c2i call being still bad, then we will crash the VM in the
>> following guarantee in SharedRuntime::handle_wrong_method:
>>
>> Method* callee = thread->callee_target();
>> guarantee(callee != NULL && callee->is_method(), "bad handshake");
>>
>> Unfortunately, the c2i entry can indeed fail again if it, e.g., hits
>> the new class initialization entry barrier of the c2i adapter.
>> The solution is to simply not clear the thread-local "callee_target"
>> after handling the first failure, as we can't really know there won't
>> be another one. There is no reason to clear this value as nobody else
>> reads it than the SharedRuntime::handle_wrong_method handler (and we
>> really do want it to be able to read the value as many times as it
>> takes until the call goes through). I found some confused clearing of
>> this callee_target in JavaThread::oops_do(), with a comment saying
>> this is a methodOop that we need to clear to make GC happy or
>> something. Seems like old traces of perm gen. So I deleted that too.
>>
>> I caught this in ZGC where the timing window for hitting this issue
>> seems to be wider due to concurrent code cache unloading. But it is
>> equally problematic for all GCs.
>>
>> Bug:
>> https://bugs.openjdk.java.net/browse/JDK-8227260
>>
>> Webrev:
>> http://cr.openjdk.java.net/~eosterlund/8227260/webrev.00/
>>
>> Thanks,
>> /Erik
More information about the hotspot-dev
mailing list