RFR: 8247992: [JVMCI] HotSpotNmethod.executeVarargs can try execute a zombie nmethod

Tom Rodriguez tom.rodriguez at oracle.com
Mon Jun 22 17:28:05 UTC 2020


I agree it shouldn't throw if the method was invalidated when the caller 
returns.  That's something the caller can check if they care.  Looks good.

tom

Doug Simon wrote on 6/22/20 9:25 AM:
> Thanks Erik,
> 
> Almost every one of your suggestions makes sense to me - thanks a lot! 
> I’ve incorporated them into https://dougxc.github.io/webrevs/8247992_16.02/
> 
> The only thing I’m not sure about is the check after the nmethod has 
> been executed. It means we can execute the alternative nmethod but still 
> throw an InvalidInstalledCodeException. This is problematic for an 
> alternative nmethod with a side effect (e.g. it changes a static field). 
> As such, I think the better option is to update the javadoc 
> for HotSpotNmethod.executeVargs as follows:
> 
>      /**
>       * {@inheritDoc}
>       *
>       * It's possible for the HotSpot runtime to sweep nmethods at any 
> point in time. As a result,
>       * there is no guarantee that calling this method will execute the 
> wrapped nmethod. Instead, it
>       * may end up executing the bytecode of the associated {@link 
> #getMethod() Java method}. Only if
>       * {@link #isValid()} is {@code true} after returning can the 
> caller be sure that the nmethod
>       * was executed. If {@link #isValid()} is {@code false}, then the 
> only way to determine if the
>       * nmethod was executed is to test for some side-effect specific to 
> the nmethod (e.g., update to
>       * a field) that is not performed by the bytecode of the associated 
> {@link #getMethod() Java
>       * method}.
>       */
> 
> The javadoc update is also part of 8247992_16.02.
> 
> -Doug
> 
>> On 22 Jun 2020, at 15:49, Erik Österlund <erik.osterlund at oracle.com 
>> <mailto:erik.osterlund at oracle.com>> wrote:
>>
>> Hi Doug,
>>
>> It would be nice if we could get rid of some cluttering of nested
>>
>> #if JVMCI
>>   if (blah) {
>> #endif
>> ...
>> #if JVMCI
>>   }
>> #endif
>>
>> It makes it hard to read for (to me) no obvious reason.
>>
>> Here is a patch on top of yours to remove some of that:
>> http://cr.openjdk.java.net/~eosterlund/8247992/webrev.doug..00/
>>
>> Full webrev:
>> http://cr.openjdk.java.net/~eosterlund/8247992/webrev.00/
>>
>> The reasoning in my changes is that since the SharedRuntime wrong 
>> method handler has no idea about these alternative call targets, 
>> checking if the nmethod is still entrant right before the call, will 
>> not guarantee that we actually end up calling the target nmethod 
>> anyway. It could get made not entrant just after the call, but before 
>> executing the first instruction, which when becoming not entrant jumps 
>> to the wrong method handler, which has no clue about any of this and 
>> just re-routes the call to the currently best method code of the 
>> method used in the Java call wrapper, without throwing any exception. 
>> So either we can live with that, or we can not. If we can live with 
>> that, then all exception handling can (and should) be removed from the 
>> Java call wrapper, because it is not needed. Instead, we check if the 
>> nmethod is still entrant in the JVMCI caller function, and accept that 
>> it could subsequently become not entrant at any point in time. A few 
>> more instructions for a slippery race to happen, but not worth 
>> cluttering the call wrapper with JVMCI code over the difference.
>>
>> Now I don't know how this API is used, but would it make sense to 
>> instead check *after* the nmethod has been executed, if it is still 
>> in_use()? Then we know that the nmethod has been executed to 
>> completion without getting killed off, if we do not get an exception. 
>> And if we get an exception then it got deoptimized either right before 
>> calling, or during its execution. Like this:
>>
>> http://cr.openjdk.java.net/~eosterlund/8247992/webrev.00..01/
>>
>> That would completely close the window for that race, but assumes the 
>> caller is okay with getting an exception if the nmethod gets 
>> deoptimized while running. You know this API better than I do, so 
>> that's your call if it is a good idea or not.
>>
>> Thanks,
>> /Erik
>>
>> On 2020-06-22 13:12, Doug Simon wrote:
>>> Hi, can I please get some reviews for this patch that fixes a race 
>>> described in JDK-8247992 
>>> <https://bugs.openjdk.java.net/browse/JDK-8247992>.
>>>
>>> The fix in the patch is to pass the HotSpotNmethod mirror object (in 
>>> a handle) through the problematic VM-to-Java transition and only 
>>> after the transition will the verified entry point be extracted from 
>>> the mirror. This will prevent a zombie nmethod from being executed.
>>>
>>> It’s still possible for the call to not reach the “alternative 
>>> target” due to sweeping heuristics. This is an acceptable limitation 
>>> of having an alternative call target in JavaCallWrapper. It could be 
>>> fixed by altering CPU specific i2c trampoline code but the added 
>>> complexity is not worth it for this test-only mechanism. Tests using 
>>> this API can detect whether the alternative target was actually 
>>> called if they really care about it.
>>>
>>> Thanks to Erik Osterlund for the in-depth analysis and suggested 
>>> solutions.
>>>
>>> https://dougxc.github.io/webrevs/8247992_16/index.html
>>> https://bugs.openjdk.java.net/browse/JDK-8247992
>>>
>>> Testing: hs-tier1,hs-tier2,hs-tier3-graal
>>>
>>> -Doug
>>
> 


More information about the hotspot-compiler-dev mailing list