JDK-8223613 : Patching of C1 compiled code relies on undefined behavior
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8u212,9,10,11,12,13
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2019-05-09
  • Updated: 2024-09-26
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.
Other
tbdUnresolved
Related Reports
Relates :  
Relates :  
Relates :  
Description
"The act of one processor writing data into the currently executing code segment of a second processor with the intent of having the second processor execute that data as code is called cross-modifying code." [1] 

There are several places in Hotspot where we perform cross-modification of code in an *unsychronized* fashion (listed by John in JDK-8081782): 
(1) Updating of Inline Caches 
(2) Patching verified entry when converting nmethod to non-entrant 
(3) Patching C1 compiled code 

For above cases it's okay if some other threads still see unpatched values. For example, when hitting an uncommon trap: While the nmethod might still be executed by other threads, we atomically patch the entry point such that it points to `SharedRuntime::get_handle_wrong_method_stub()` (see `nmethod::make_not_entrant_or_zombie()`). It's fine for other threads to miss that update and continue execution, they will eventually hit the uncommon trap as well. However, this assumes that although the update might be missed by other threads, it's still safe, i.e., a thread either sees the old value or the new value. 

Now several (also recent) Intel processors are affected by an issue named "Unsynchronized Cross-Modifying Code Operations Can Cause Unexpected Instruction Execution Results" that can lead to "unexpected or unpredictable execution behavior" [2]. This means that (1) - (3) can lead to undefined behavior and this is what happens in the case reported by this bug: we crash due to unsychronized nmethod entry patching (2). 

Cases (1) and (2) will be addressed by the "New Invoke Bindings" JEP (JDK-8221828). The problem with case (3) should be addressed by this bug.

The suggested workaround by Intel is to "use the XMC synchronization algorithm as detailed in the Intel Architecture Software Developer's Manual Volume 3: System Programming Guide, Section: Handling Self- and Cross-Modifying Code." (see 8.1.3 in [1]) which is basically a stop-the-world (i.e. only patch at safepoints) approach.

So the obvious solution would be to only patch at safepoints or implement patching similar to what is done on AARCH64 (see `DEOPTIMIZE_WHEN_PATCHING`, JDK-8219993) but that will have a potentially huge performance impact.

[1] https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf 
[2] Some examples of affected processors: 
- Intel Xeon Phi x200 family, see "KNL9" 
 https://www.intel.co.uk/content/dam/www/public/us/en/documents/specification-updates/xeon-phi-processor-specification-update.pdf 
- N-series Intel Pentium and Intel Celeron, see "CHP15" 
 https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/pentium-celeron-n-series-spec-update.pdf 
- Intel Core 2 duo E7000/E8000, see "AW75" 
 http://download.intel.com/design/processor/specupdt/318733.pdf 
- Intel Core 2 Extreme X6800/E4000/E6000, see "AI33" 
 http://download.intel.com/design/processor/specupdt/313279.pdf
Comments
Actually, DEOPTIMIZE_WHEN_PATCHING has very little impact because C1 patching is fairly rare. In a tiered compilation system, recompilations caused by profile counter overflows are ten times as frequent as those caused by C1 patching traps. For that reason, you could turn off C1 patching and most people would never notice.
08-02-2021

ILW = Undefined behavior of C1 compiled code (potential crash, incorrect result, ...), never observed, disable TieredCompilation/C1 = HLM = P3
09-05-2019