Skip to content

Commit e45fea5

Browse files
committed
8329757: Crash with fatal error: DEBUG MESSAGE: Fast Unlock lock on stack
Reviewed-by: pchilanomate, kvn
1 parent ece7d43 commit e45fea5

File tree

4 files changed

+149
-1
lines changed

4 files changed

+149
-1
lines changed

src/hotspot/share/runtime/deoptimization.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArray<compiledV
391391
#ifndef PRODUCT
392392
bool first = true;
393393
#endif // !PRODUCT
394+
DEBUG_ONLY(GrowableArray<oop> lock_order{0};)
394395
// Start locking from outermost/oldest frame
395396
for (int i = (chunk->length() - 1); i >= 0; i--) {
396397
compiledVFrame* cvf = chunk->at(i);
@@ -400,6 +401,13 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArray<compiledV
400401
bool relocked = Deoptimization::relock_objects(thread, monitors, deoptee_thread, deoptee,
401402
exec_mode, realloc_failures);
402403
deoptimized_objects = deoptimized_objects || relocked;
404+
#ifdef ASSERT
405+
if (LockingMode == LM_LIGHTWEIGHT && !realloc_failures) {
406+
for (MonitorInfo* mi : *monitors) {
407+
lock_order.push(mi->owner());
408+
}
409+
}
410+
#endif // ASSERT
403411
#ifndef PRODUCT
404412
if (PrintDeoptimizationDetails) {
405413
ResourceMark rm;
@@ -431,6 +439,11 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArray<compiledV
431439
#endif // !PRODUCT
432440
}
433441
}
442+
#ifdef ASSERT
443+
if (LockingMode == LM_LIGHTWEIGHT && !realloc_failures) {
444+
deoptee_thread->lock_stack().verify_consistent_lock_order(lock_order, exec_mode != Deoptimization::Unpack_none);
445+
}
446+
#endif // ASSERT
434447
}
435448

436449
// Deoptimize objects, that is reallocate and relock them, just before they escape through JVMTI.
@@ -1642,7 +1655,7 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArray<MonitorInf
16421655
}
16431656
}
16441657
}
1645-
if (LockingMode == LM_LIGHTWEIGHT && exec_mode == Unpack_none) {
1658+
if (LockingMode == LM_LIGHTWEIGHT) {
16461659
// We have lost information about the correct state of the lock stack.
16471660
// Inflate the locks instead. Enter then inflate to avoid races with
16481661
// deflation.

src/hotspot/share/runtime/lockStack.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,19 @@
2626

2727
#include "precompiled.hpp"
2828
#include "memory/allocation.hpp"
29+
#include "oops/markWord.hpp"
30+
#include "oops/oop.inline.hpp"
2931
#include "runtime/globals.hpp"
3032
#include "runtime/lockStack.inline.hpp"
33+
#include "runtime/objectMonitor.inline.hpp"
3134
#include "runtime/safepoint.hpp"
3235
#include "runtime/stackWatermark.hpp"
3336
#include "runtime/stackWatermarkSet.inline.hpp"
3437
#include "runtime/thread.hpp"
3538
#include "utilities/copy.hpp"
3639
#include "utilities/debug.hpp"
3740
#include "utilities/globalDefinitions.hpp"
41+
#include "utilities/growableArray.hpp"
3842
#include "utilities/ostream.hpp"
3943

4044
#include <type_traits>
@@ -99,6 +103,60 @@ void LockStack::verify(const char* msg) const {
99103
}
100104
#endif
101105

106+
#ifdef ASSERT
107+
void LockStack::verify_consistent_lock_order(GrowableArray<oop>& lock_order, bool leaf_frame) const {
108+
int top_index = to_index(_top);
109+
int lock_index = lock_order.length();
110+
111+
if (!leaf_frame) {
112+
// If the lock_order is not from the leaf frame we must search
113+
// for the top_index which fits with the most recent fast_locked
114+
// objects in the lock stack.
115+
while (lock_index-- > 0) {
116+
const oop obj = lock_order.at(lock_index);
117+
if (contains(obj)) {
118+
for (int index = 0; index < top_index; index++) {
119+
if (_base[index] == obj) {
120+
// Found top index
121+
top_index = index + 1;
122+
break;
123+
}
124+
}
125+
126+
if (VM_Version::supports_recursive_lightweight_locking()) {
127+
// With recursive looks there may be more of the same object
128+
while (lock_index-- > 0 && lock_order.at(lock_index) == obj) {
129+
top_index++;
130+
}
131+
assert(top_index <= to_index(_top), "too many obj in lock_order");
132+
}
133+
134+
break;
135+
}
136+
}
137+
138+
lock_index = lock_order.length();
139+
}
140+
141+
while (lock_index-- > 0) {
142+
const oop obj = lock_order.at(lock_index);
143+
const markWord mark = obj->mark_acquire();
144+
assert(obj->is_locked(), "must be locked");
145+
if (top_index > 0 && obj == _base[top_index - 1]) {
146+
assert(mark.is_fast_locked() || mark.monitor()->is_owner_anonymous(),
147+
"must be fast_locked or inflated by other thread");
148+
top_index--;
149+
} else {
150+
assert(!mark.is_fast_locked(), "must be inflated");
151+
assert(mark.monitor()->owner_raw() == get_thread() ||
152+
(!leaf_frame && get_thread()->current_waiting_monitor() == mark.monitor()),
153+
"must be owned by (or waited on by) thread");
154+
assert(!contains(obj), "must not be on lock_stack");
155+
}
156+
}
157+
}
158+
#endif
159+
102160
void LockStack::print_on(outputStream* st) {
103161
for (int i = to_index(_top); (--i) >= 0;) {
104162
st->print("LockStack[%d]: ", i);

src/hotspot/share/runtime/lockStack.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
class JavaThread;
3535
class OopClosure;
3636
class outputStream;
37+
template<typename>
38+
class GrowableArray;
3739

3840
class LockStack {
3941
friend class LockStackTest;
@@ -119,6 +121,9 @@ class LockStack {
119121

120122
// Printing
121123
void print_on(outputStream* st);
124+
125+
// Verify Lock Stack consistent with lock order
126+
void verify_consistent_lock_order(GrowableArray<oop>& lock_order, bool leaf_frame) const NOT_DEBUG_RETURN;
122127
};
123128

124129
#endif // SHARE_RUNTIME_LOCKSTACK_HPP
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8329757
27+
* @summary Deoptimization with nested eliminated and not eliminated locks
28+
* caused reordered lock stacks. This can be handled by the interpreter
29+
* but when a frame is migrated back to compiled code via OSR the C2
30+
* assumption about balanced monitorenter-monitorexit is broken.
31+
*
32+
* @requires vm.compMode != "Xint"
33+
*
34+
* @run main/othervm compiler.escapeAnalysis.Test8329757
35+
*/
36+
37+
package compiler.escapeAnalysis;
38+
39+
public class Test8329757 {
40+
41+
int a = 400;
42+
Double ddd;
43+
44+
void q() {
45+
int e;
46+
synchronized (new Double(1.1f)) {
47+
int[] f = new int[a];
48+
synchronized (Test8329757.class) {
49+
for (int d = 4; d < 127; d++) {
50+
e = 13;
51+
do switch (d * 5) {
52+
case 0:
53+
case 42:
54+
case 29:
55+
e = d;
56+
default:
57+
f[1] = e;
58+
} while (--e > 0);
59+
}
60+
}
61+
}
62+
}
63+
64+
void n() {
65+
for (int j = 6; j < 274; ++j) q();
66+
}
67+
68+
public static void main(String[] args) {
69+
Test8329757 r = new Test8329757();
70+
for (int i = 0; i < 1000; i++) r.n();
71+
}
72+
}

0 commit comments

Comments
 (0)