8329757: Crash with fatal error: DEBUG MESSAGE: Fast Unlock lock on stack
Reviewed-by: pchilanomate, kvn
This commit is contained in:
parent
ece7d4349a
commit
e45fea5a80
src/hotspot/share/runtime
test/hotspot/jtreg/compiler/escapeAnalysis
@ -391,6 +391,7 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArray<compiledV
|
||||
#ifndef PRODUCT
|
||||
bool first = true;
|
||||
#endif // !PRODUCT
|
||||
DEBUG_ONLY(GrowableArray<oop> lock_order{0};)
|
||||
// Start locking from outermost/oldest frame
|
||||
for (int i = (chunk->length() - 1); i >= 0; i--) {
|
||||
compiledVFrame* cvf = chunk->at(i);
|
||||
@ -400,6 +401,13 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArray<compiledV
|
||||
bool relocked = Deoptimization::relock_objects(thread, monitors, deoptee_thread, deoptee,
|
||||
exec_mode, realloc_failures);
|
||||
deoptimized_objects = deoptimized_objects || relocked;
|
||||
#ifdef ASSERT
|
||||
if (LockingMode == LM_LIGHTWEIGHT && !realloc_failures) {
|
||||
for (MonitorInfo* mi : *monitors) {
|
||||
lock_order.push(mi->owner());
|
||||
}
|
||||
}
|
||||
#endif // ASSERT
|
||||
#ifndef PRODUCT
|
||||
if (PrintDeoptimizationDetails) {
|
||||
ResourceMark rm;
|
||||
@ -431,6 +439,11 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArray<compiledV
|
||||
#endif // !PRODUCT
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
if (LockingMode == LM_LIGHTWEIGHT && !realloc_failures) {
|
||||
deoptee_thread->lock_stack().verify_consistent_lock_order(lock_order, exec_mode != Deoptimization::Unpack_none);
|
||||
}
|
||||
#endif // ASSERT
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
if (LockingMode == LM_LIGHTWEIGHT && exec_mode == Unpack_none) {
|
||||
if (LockingMode == LM_LIGHTWEIGHT) {
|
||||
// We have lost information about the correct state of the lock stack.
|
||||
// Inflate the locks instead. Enter then inflate to avoid races with
|
||||
// deflation.
|
||||
|
@ -26,8 +26,11 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/markWord.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/lockStack.inline.hpp"
|
||||
#include "runtime/objectMonitor.inline.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/stackWatermark.hpp"
|
||||
#include "runtime/stackWatermarkSet.inline.hpp"
|
||||
@ -35,6 +38,7 @@
|
||||
#include "utilities/copy.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
@ -99,6 +103,60 @@ void LockStack::verify(const char* msg) const {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ASSERT
|
||||
void LockStack::verify_consistent_lock_order(GrowableArray<oop>& lock_order, bool leaf_frame) const {
|
||||
int top_index = to_index(_top);
|
||||
int lock_index = lock_order.length();
|
||||
|
||||
if (!leaf_frame) {
|
||||
// If the lock_order is not from the leaf frame we must search
|
||||
// for the top_index which fits with the most recent fast_locked
|
||||
// objects in the lock stack.
|
||||
while (lock_index-- > 0) {
|
||||
const oop obj = lock_order.at(lock_index);
|
||||
if (contains(obj)) {
|
||||
for (int index = 0; index < top_index; index++) {
|
||||
if (_base[index] == obj) {
|
||||
// Found top index
|
||||
top_index = index + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (VM_Version::supports_recursive_lightweight_locking()) {
|
||||
// With recursive looks there may be more of the same object
|
||||
while (lock_index-- > 0 && lock_order.at(lock_index) == obj) {
|
||||
top_index++;
|
||||
}
|
||||
assert(top_index <= to_index(_top), "too many obj in lock_order");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lock_index = lock_order.length();
|
||||
}
|
||||
|
||||
while (lock_index-- > 0) {
|
||||
const oop obj = lock_order.at(lock_index);
|
||||
const markWord mark = obj->mark_acquire();
|
||||
assert(obj->is_locked(), "must be locked");
|
||||
if (top_index > 0 && obj == _base[top_index - 1]) {
|
||||
assert(mark.is_fast_locked() || mark.monitor()->is_owner_anonymous(),
|
||||
"must be fast_locked or inflated by other thread");
|
||||
top_index--;
|
||||
} else {
|
||||
assert(!mark.is_fast_locked(), "must be inflated");
|
||||
assert(mark.monitor()->owner_raw() == get_thread() ||
|
||||
(!leaf_frame && get_thread()->current_waiting_monitor() == mark.monitor()),
|
||||
"must be owned by (or waited on by) thread");
|
||||
assert(!contains(obj), "must not be on lock_stack");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void LockStack::print_on(outputStream* st) {
|
||||
for (int i = to_index(_top); (--i) >= 0;) {
|
||||
st->print("LockStack[%d]: ", i);
|
||||
|
@ -34,6 +34,8 @@
|
||||
class JavaThread;
|
||||
class OopClosure;
|
||||
class outputStream;
|
||||
template<typename>
|
||||
class GrowableArray;
|
||||
|
||||
class LockStack {
|
||||
friend class LockStackTest;
|
||||
@ -119,6 +121,9 @@ public:
|
||||
|
||||
// Printing
|
||||
void print_on(outputStream* st);
|
||||
|
||||
// Verify Lock Stack consistent with lock order
|
||||
void verify_consistent_lock_order(GrowableArray<oop>& lock_order, bool leaf_frame) const NOT_DEBUG_RETURN;
|
||||
};
|
||||
|
||||
#endif // SHARE_RUNTIME_LOCKSTACK_HPP
|
||||
|
72
test/hotspot/jtreg/compiler/escapeAnalysis/Test8329757.java
Normal file
72
test/hotspot/jtreg/compiler/escapeAnalysis/Test8329757.java
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8329757
|
||||
* @summary Deoptimization with nested eliminated and not eliminated locks
|
||||
* caused reordered lock stacks. This can be handled by the interpreter
|
||||
* but when a frame is migrated back to compiled code via OSR the C2
|
||||
* assumption about balanced monitorenter-monitorexit is broken.
|
||||
*
|
||||
* @requires vm.compMode != "Xint"
|
||||
*
|
||||
* @run main/othervm compiler.escapeAnalysis.Test8329757
|
||||
*/
|
||||
|
||||
package compiler.escapeAnalysis;
|
||||
|
||||
public class Test8329757 {
|
||||
|
||||
int a = 400;
|
||||
Double ddd;
|
||||
|
||||
void q() {
|
||||
int e;
|
||||
synchronized (new Double(1.1f)) {
|
||||
int[] f = new int[a];
|
||||
synchronized (Test8329757.class) {
|
||||
for (int d = 4; d < 127; d++) {
|
||||
e = 13;
|
||||
do switch (d * 5) {
|
||||
case 0:
|
||||
case 42:
|
||||
case 29:
|
||||
e = d;
|
||||
default:
|
||||
f[1] = e;
|
||||
} while (--e > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void n() {
|
||||
for (int j = 6; j < 274; ++j) q();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Test8329757 r = new Test8329757();
|
||||
for (int i = 0; i < 1000; i++) r.n();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user