JDK-8247992 : [JVMCI] HotSpotNmethod.executeVarargs can try execute a zombie nmethod
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 11,15
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2020-06-22
  • Updated: 2024-10-17
  • Resolved: 2020-06-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 15 JDK 16
11.0.9-oracleFixed 15 b29Fixed 16Fixed
Related Reports
Relates :  
Description
For white box testing purposes, JVMCi includes API for reflectively calling a compiled nmethod:

jdk.vm.ci.hotspot.HotSpotNmethod.executeVarargs(Object...) [4]

There is currently a race in the implementation of this method whereby between calling this method and executing the instruction at the nmethod's verified entry point (VEP) the code cache sweeper can have unloaded the nmethod.

This API calls an nmethod from a Java call wrapper, but with a special "alternative call target" [1], which is the VEP loaded from the nmethod mirror. The core of the issue is that the VEP is loaded from the nmethod mirror [2] before the transition from VM to Java[3]. This means that before loading the VEP from the nmethod mirror, and getting to the safepoint poll in the transition, the thread could be preempted. It could then happen that the nmethod becomes not entrant, and a sweeper cycle could issue a thread-local nmethod marking handshake. The nmethod has yet to build its frame so is not marked as on-stack. Therefore, before the i2c adapter gets to call this alternative target (the now stale VEP from the nmethod mirror), the nmethod could become zombie. Then the i2c adapter proceeds to call the zombie nmethod. From that point on, insanity follows.

This race has existed since the initial JVMCI implementation. It has not shown up in practice since nmethod sweeping has not been a highly concurrent activity. However, this is changing as of JDK 15 and we are seeing intermittent failures in upstream Graal unit testing.

[1] https://github.com/openjdk/jdk/blob/2d5137e403e16b694800b2ffe18c3640396b757e/src/hotspot/share/runtime/javaCalls.hpp#L91
[2] https://github.com/openjdk/jdk/blob/2d5137e403e16b694800b2ffe18c3640396b757e/src/hotspot/share/runtime/javaCalls.cpp#L431
[3] https://github.com/openjdk/jdk/blob/2d5137e403e16b694800b2ffe18c3640396b757e/src/hotspot/share/runtime/javaCalls.cpp#L70
[4] https://github.com/openjdk/jdk/blob/5ad889b5e0a99863a089ceee215b3f7a7158b78c/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java#L150
Comments
Changeset: 64696852 Author: Doug Simon <dnsimon@openjdk.org> Date: 2020-06-23 09:57:30 +0000 URL: https://git.openjdk.java.net/panama-foreign/commit/64696852
02-07-2020

Changeset: 64696852 Author: Doug Simon <dnsimon@openjdk.org> Date: 2020-06-23 09:57:30 +0000 URL: https://git.openjdk.java.net/amber/commit/64696852
02-07-2020

Changeset: 64696852 Author: Doug Simon <dnsimon@openjdk.org> Date: 2020-06-23 09:57:30 +0000 URL: https://git.openjdk.java.net/mobile/commit/64696852
02-07-2020

This patch restores the expected behavior that empty methods might not be called/compiled anymore (see JDK-8248265).
26-06-2020

URL: https://hg.openjdk.java.net/jdk/jdk15/rev/94025f9e6a0d User: dnsimon Date: 2020-06-23 07:57:53 +0000
23-06-2020