-
Bug
-
Resolution: Fixed
-
P3
-
21, 22, repo-lilliput-17, repo-lilliput-21
-
b24
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8319926 | 21.0.2 | Roman Kennke | P3 | Resolved | Fixed | b09 |
One of the problematic tests is the following:
```
class EARelockingArgEscapeLWLockedInCalleeFrame_2Target extends EATestCaseBaseTarget {
...
public void dontinline_testMethod() {
XYVal l1 = new XYVal(1, 1); // ArgEscape
XYVal l2 = new XYVal(4, 2); // NoEscape, scalar replaced
synchronized (l1) { // eliminated
synchronized (l2) { // eliminated
l1.dontinline_sync_method(this); // l1 escapes
}
}
iResult = l2.x + l2.y;
}
```
The test runs the above method enough time to for it to get C2 compiled. Then it attaches a debugger and adds a breakpoint deeper inside dontlinine_sync_method.
What we see in gdb is that `l1` is an existing object that has been pushed onto the deoptee thread's locking stack because of the dontinline_sync_method call. We then try to "replay" `synchronized (l1)` and `synchronized (l2)` in Deoptimization::relock_objects. This gives us the incorrect lock order [l1, l1, l2] while the actual code has the [l1, l2, l1] lock order. This then messes up the lock stack in the unlock path when we perform our recursive lock handling.
The lightweight code in openjdk/jdk works because the recursive lock gets inflated and removed from the lock stack. However, I can get the upstream lightweight locking to assert by removing the recursive locking in the test case:
```
class EARelockingArgEscapeLWLockedInCalleeFrame_2Target extends EATestCaseBaseTarget {
...
public void dontinline_testMethod() {
XYVal l1 = new XYVal(1, 1);
XYVal l2 = new XYVal(4, 2);
XYVal l3 = new XYVal(5, 3);
synchronized (l1) {
synchronized (l2) {
l3.dontinline_sync_method(this);
}
}
iResult = l2.x + l2.y;
}
```
This asserts with the following:
```
# Internal Error (/home/stefank/git/jdk/open/src/hotspot/share/runtime/lockStack.inline.hpp:86), pid=265437, tid=265440
# assert(contains(o)) failed: entry must be present: 0x00000000ffa00130
...
V [libjvm.so+0x1743709] LockStack::remove(oop)+0x3e9 (lockStack.inline.hpp:86)
V [libjvm.so+0x173f78d] ObjectSynchronizer::exit(oop, BasicLock*, JavaThread*)+0x2fd (synchronizer.cpp:590)
V [libjvm.so+0xe7667c] InterpreterRuntime::monitorexit(BasicObjectLock*)+0x18c (interpreterRuntime.cpp:779)
j EARelockingArgEscapeLWLockedInCalleeFrame_2Target.dontinline_testMethod()V+47
j EATestCaseBaseTarget.run()V+64
- backported by
-
JDK-8319926 Deoptimization results in incorrect lightweight locking stack
- Resolved
- relates to
-
JDK-8227745 Enable Escape Analysis for Better Performance in the Presence of JVMTI Agents
- Resolved
-
JDK-8291555 Implement alternative fast-locking scheme
- Resolved
-
JDK-8315880 Change LockingMode default from LM_LEGACY to LM_LIGHTWEIGHT
- Closed
-
JDK-8320196 assert(cur != anon_owner_ptr()) failed: no anon owner here with Graal
- Resolved
-
JDK-8324881 ObjectSynchronizer::inflate(Thread* current...) is invoked for non-current thread
- Resolved
- links to
-
Commit openjdk/jdk21u/0f7bbe1f
-
Commit openjdk/jdk/ea1ffa34
-
Commit openjdk/lilliput-jdk17u/17daee89
-
Review openjdk/jdk21u/400
-
Review openjdk/jdk/16568
-
Review openjdk/lilliput-jdk17u/77