RFR[13]: 8227260: Can't deal with SharedRuntime::handle_wrong_method triggering more than once for interpreter calls

Erik Österlund erik.osterlund at oracle.com
Wed Jul 17 12:25:56 UTC 2019


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