JDK-8217990 : C2 UseOptoBiasInlining: load of markword optimized to 0 if running with -XX:-EliminateLocks
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8,9,10,11,12,13
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2019-01-29
  • Updated: 2019-12-18
  • Resolved: 2019-02-08
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 13
11.0.5Fixed 13 b08Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
The jtreg test TestUseOptoBiasInliningWithoutEliminateLocks.java contained in the attached jdk.changeset triggers

  assert(dmw->is_neutral()) failed: invariant

in ObjectSynchronizer::inflate().

Analysis:

- Test is run with -XX:-EliminateLocks

- The load node 223 (see attachment 1_ideal_after_macro_before_opt.log) for loading the markword is replaced with the constant 0

  * The address of the load has instance id 25 from escape analysis, but there is no alias index.
  * The load gets Bot memory from MemMerge 56 which is the initial memory node 7
  * LoadNode::Value() treats the markword as every other field and evaluates to constant zero

- The optimizer finds the test of the markword for a bias pattern to be constant false

- The biased locking enter is found to be dead code and removed (see 2_ideal_after_macro_after_opt.log and B3 in 3_opto_assembly.log).

- At runtime: fast lock succeeds and stores the anonymously biased mark word as displaced header into the stack frame

- Frame is deoptimized w/o inflating the lock as normally

- Something goes wrong in the interpreted monitor exit which leads to inflation

- Assertion fires in ObjectSynchronizer::inflate(), because the displaced header has a bias pattern

Note: when running the test with -XX:-DoEscapeAnalysis, the markword load has as well the initial
memory as memory input (see 4_ideal_after_macro_after_opt_DoEscapeAnalysis_disabled.log). It is not
replaced with constant 0, because the address is _not_ is_known_instance_field(). I presume this is
the reason, why the markword loads get pinned?

Fix Attempt (attachment jdk.changeset):

LoadNode::Value(): only replace loads with constant 0 if the offset is greater than 0.

Experimental: GraphKit::set_output_for_allocation(): create alias index for markword references.
With this the markword load has a memory dependency on the object initialization (see
5_fix_attempt_ideal_after_macro_after_opt.log) if escape analysis is disabled. With escape analysis
enabled this is not enough if the object has an instance id. In this case the load should be pinned
(not included in the fix).
Comments
Tried to backport this to 8u: http://cr.openjdk.java.net/~shade/8217990/webrev.8u.01/ The biggest headache here is the new test. It is rather fragile itself: requires a few particular things to happen in precise way for test to detect the failure. Notably, there is no Whitebox API method that would deoptimize all compiler frames: WB.deoptimizeFrames. It was added by JDK-8028595, and that patch can be backported with some pain. However, even after backporting minimal viable piece of JDK-8028595, the original test still passes without the product fix in 8u.
04-07-2019

Fix Request (11u) This fixes C2 miscompilation when accessing the mark word (and it is important for future Shenandoah backports). The patch applies cleanly to 11u. New testcase fails without product fix, and passes with it. Additionally, patched build passes tier1 and tier2 tests.
19-06-2019

Shenandoah uses mark word to store forwarding data, and reads it in C2 barriers, linking those issues up.
19-06-2019

[~kvn], I already verified that JDK-8213825 is unrelated when triaging this bug.
31-01-2019

[~rrich] Please, look on recently fixed bug for mark word load in lock - JDK-8213825.
30-01-2019

Okay, thanks Richard!
30-01-2019

Thanks for taking a look at this, Tobias. My intention was to fix the memory dependencies, which look incorrect to me and get rid of the region pinning of the markword loads for the lock and unlock operations. Unfortunately I won't be able to put more work in it anytime soon. As a small and conservative fix one could prevent replacing a markword load with constant 0 in LoadNode::Value(). I'd leave it up to you to do this or to assign the bug to another compiler engineer. Thanks, Richard.
30-01-2019

Richard, thanks for reporting this issue! Do you plan to work on a complete fix or should we assign to another engineer? ILW = Markword load is incorrectly optimized to constant 0 (leading to assert), easy to reproduce with regression test (-XX:-EliminateLocks), -XX:+EliminateLocks or disable compilation of method = HMM = P2
30-01-2019