RFR[13]: 8227260: Can't deal with SharedRuntime::handle_wrong_method triggering more than once for interpreter calls
Vladimir Ivanov
vladimir.x.ivanov at oracle.com
Wed Jul 17 13:06:39 UTC 2019
Thanks, Erik.
Also, since I touch platform-specific code, I'd like Martin and Dmitrij
(implementors of support for s390, ppc, and aarch64) to take a look at
the patch as well.
Best regards,
Vladimir Ivanov
On 17/07/2019 15:25, Erik Österlund wrote:
> Hi Vladimir,
>
> Looks good. Thanks for fixing.
>
> /Erik
>
> On 2019-07-17 12:26, Vladimir Ivanov wrote:
>> Revised fix:
>> http://cr.openjdk.java.net/~vlivanov/8227260/webrev.00/
>>
>> It turned out the problem is not specific to i2c2i: fast class
>> initialization barriers on nmethod entry trigger the assert as well.
>>
>> JNI upcalls (CallStatic<type>Method) don't have class initialization
>> checks, so it's possible to initiate a JNI upcall from a
>> non-initializing thread and JVM should let it complete.
>>
>> It leads to a busy loop (asserts in debug) between nmethod entry
>> barrier & SharedRuntime::handle_wrong_method until holder class is
>> initialized (possibly infinite if it blocks class initialization).
>>
>> Proposed fix is to keep using c2i, but jump over class initialization
>> barrier right to the argument shuffling logic on verified entry when
>> coming from SharedRuntime::handle_wrong_method.
>>
>> Improved regression test reliably reproduces the problem.
>>
>> Testing: regression test, hs-precheckin-comp, tier1-6
>>
>> Best regards,
>> Vladimir Ivanov
>>
>> 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