8273456: Do not hold ttyLock around stack walking

Reviewed-by: dholmes, eosterlund
This commit is contained in:
Coleen Phillimore 2021-09-10 14:54:47 +00:00
parent 695b434b44
commit 461a467f91
5 changed files with 81 additions and 72 deletions

View file

@ -2383,22 +2383,19 @@ WB_ENTRY(void, WB_CheckThreadObjOfTerminatingThread(JNIEnv* env, jobject wb, job
WB_END
WB_ENTRY(void, WB_VerifyFrames(JNIEnv* env, jobject wb, jboolean log, jboolean update_map))
intx tty_token = -1;
if (log) {
tty_token = ttyLocker::hold_tty();
tty->print_cr("[WhiteBox::VerifyFrames] Walking Frames");
}
ResourceMark rm; // for verify
stringStream st;
for (StackFrameStream fst(JavaThread::current(), update_map, true); !fst.is_done(); fst.next()) {
frame* current_frame = fst.current();
if (log) {
current_frame->print_value();
current_frame->print_value_on(&st, NULL);
}
current_frame->verify(fst.register_map());
}
if (log) {
tty->print_cr("[WhiteBox::VerifyFrames] Walking Frames");
tty->print_raw(st.as_string());
tty->print_cr("[WhiteBox::VerifyFrames] Done");
ttyLocker::release_tty(tty_token);
}
WB_END

View file

@ -143,14 +143,16 @@ int Deoptimization::UnrollBlock::size_of_frames() const {
void Deoptimization::UnrollBlock::print() {
ttyLocker ttyl;
tty->print_cr("UnrollBlock");
tty->print_cr(" size_of_deoptimized_frame = %d", _size_of_deoptimized_frame);
tty->print( " frame_sizes: ");
ResourceMark rm;
stringStream st;
st.print_cr("UnrollBlock");
st.print_cr(" size_of_deoptimized_frame = %d", _size_of_deoptimized_frame);
st.print( " frame_sizes: ");
for (int index = 0; index < number_of_frames(); index++) {
tty->print(INTX_FORMAT " ", frame_sizes()[index]);
st.print(INTX_FORMAT " ", frame_sizes()[index]);
}
tty->cr();
st.cr();
tty->print_raw(st.as_string());
}
@ -179,6 +181,38 @@ JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info(
JRT_END
#if COMPILER2_OR_JVMCI
#ifndef PRODUCT
// print information about reallocated objects
static void print_objects(JavaThread* deoptee_thread,
GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
ResourceMark rm;
stringStream st; // change to logStream with logging
st.print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, p2i(deoptee_thread));
fieldDescriptor fd;
for (int i = 0; i < objects->length(); i++) {
ObjectValue* sv = (ObjectValue*) objects->at(i);
Klass* k = java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()());
Handle obj = sv->value();
st.print(" object <" INTPTR_FORMAT "> of type ", p2i(sv->value()()));
k->print_value_on(&st);
assert(obj.not_null() || realloc_failures, "reallocation was missed");
if (obj.is_null()) {
st.print(" allocation failed");
} else {
st.print(" allocated (%d bytes)", obj->size() * HeapWordSize);
}
st.cr();
if (Verbose && !obj.is_null()) {
k->oop_print_on(obj(), &st);
}
}
tty->print_raw(st.as_string());
}
#endif
static bool rematerialize_objects(JavaThread* thread, int exec_mode, CompiledMethod* compiled_method,
frame& deoptee, RegisterMap& map, GrowableArray<compiledVFrame*>* chunk,
bool& deoptimized_objects) {
@ -210,7 +244,6 @@ static bool rematerialize_objects(JavaThread* thread, int exec_mode, CompiledMet
return_value = Handle(thread, result);
assert(Universe::heap()->is_in_or_null(result), "must be heap pointer");
if (TraceDeoptimization) {
ttyLocker ttyl;
tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, p2i(result), p2i(thread));
}
}
@ -231,9 +264,7 @@ static bool rematerialize_objects(JavaThread* thread, int exec_mode, CompiledMet
Deoptimization::reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal);
#ifndef PRODUCT
if (TraceDeoptimization) {
ttyLocker ttyl;
tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, p2i(deoptee_thread));
Deoptimization::print_objects(objects, realloc_failures);
print_objects(deoptee_thread, objects, realloc_failures);
}
#endif
}
@ -263,29 +294,31 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArray<compiledV
deoptimized_objects = deoptimized_objects || relocked;
#ifndef PRODUCT
if (PrintDeoptimizationDetails) {
ttyLocker ttyl;
ResourceMark rm;
stringStream st;
for (int j = 0; j < monitors->length(); j++) {
MonitorInfo* mi = monitors->at(j);
if (mi->eliminated()) {
if (first) {
first = false;
tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, p2i(thread));
st.print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, p2i(thread));
}
if (exec_mode == Deoptimization::Unpack_none) {
ObjectMonitor* monitor = deoptee_thread->current_waiting_monitor();
if (monitor != NULL && monitor->object() == mi->owner()) {
tty->print_cr(" object <" INTPTR_FORMAT "> DEFERRED relocking after wait", p2i(mi->owner()));
st.print_cr(" object <" INTPTR_FORMAT "> DEFERRED relocking after wait", p2i(mi->owner()));
continue;
}
}
if (mi->owner_is_scalar_replaced()) {
Klass* k = java_lang_Class::as_Klass(mi->owner_klass());
tty->print_cr(" failed reallocation for klass %s", k->external_name());
st.print_cr(" failed reallocation for klass %s", k->external_name());
} else {
tty->print_cr(" object <" INTPTR_FORMAT "> locked", p2i(mi->owner()));
st.print_cr(" object <" INTPTR_FORMAT "> locked", p2i(mi->owner()));
}
}
}
tty->print_raw(st.as_string());
}
#endif // !PRODUCT
}
@ -604,7 +637,6 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
if (array->frames() > 1) {
if (VerifyStack && TraceDeoptimization) {
ttyLocker ttyl;
tty->print_cr("Deoptimizing method containing inlining");
}
}
@ -698,7 +730,6 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
#ifndef PRODUCT
if (TraceDeoptimization) {
ttyLocker ttyl;
tty->print_cr("DEOPT UNPACKING thread " INTPTR_FORMAT " vframeArray " INTPTR_FORMAT " mode %d",
p2i(thread), p2i(array), exec_mode);
}
@ -820,8 +851,6 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
(iframe->interpreter_frame_expression_stack_size() == mask.expression_stack_size() + cur_invoke_parameter_size))
)) {
{
ttyLocker ttyl;
// Print out some information that will help us debug the problem
tty->print_cr("Wrong number of expression stack elements during deoptimization");
tty->print_cr(" Error occurred while verifying frame %d (0..%d, 0 is topmost)", i, cur_array->frames() - 1);
@ -842,7 +871,7 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
tty->print_cr(" %s (bci %d)", el->method()->name_and_sig_as_C_string(), el->bci());
}
cur_array->print_on_2(tty);
} // release tty lock before calling guarantee
}
guarantee(false, "wrong number of expression stack elements during deopt");
}
VerifyOopClosure verify;
@ -1461,34 +1490,6 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArray<MonitorInf
}
return relocked_objects;
}
#ifndef PRODUCT
// print information about reallocated objects
void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
fieldDescriptor fd;
for (int i = 0; i < objects->length(); i++) {
ObjectValue* sv = (ObjectValue*) objects->at(i);
Klass* k = java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()());
Handle obj = sv->value();
tty->print(" object <" INTPTR_FORMAT "> of type ", p2i(sv->value()()));
k->print_value();
assert(obj.not_null() || realloc_failures, "reallocation was missed");
if (obj.is_null()) {
tty->print(" allocation failed");
} else {
tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize);
}
tty->cr();
if (Verbose && !obj.is_null()) {
k->oop_print_on(obj(), tty);
}
}
}
#endif
#endif // COMPILER2_OR_JVMCI
vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
@ -1496,14 +1497,15 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re
#ifndef PRODUCT
if (PrintDeoptimizationDetails) {
ttyLocker ttyl;
tty->print("DEOPT PACKING thread " INTPTR_FORMAT " ", p2i(thread));
fr.print_on(tty);
tty->print_cr(" Virtual frames (innermost first):");
ResourceMark rm;
stringStream st;
st.print("DEOPT PACKING thread " INTPTR_FORMAT " ", p2i(thread));
fr.print_on(&st);
st.print_cr(" Virtual frames (innermost first):");
for (int index = 0; index < chunk->length(); index++) {
compiledVFrame* vf = chunk->at(index);
tty->print(" %2d - ", index);
vf->print_value();
st.print(" %2d - ", index);
vf->print_value_on(&st);
int bci = chunk->at(index)->raw_bci();
const char* code_name;
if (bci == SynchronizationEntryBCI) {
@ -1512,13 +1514,14 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re
Bytecodes::Code code = vf->method()->code_at(bci);
code_name = Bytecodes::name(code);
}
tty->print(" - %s", code_name);
tty->print_cr(" @ bci %d ", bci);
st.print(" - %s", code_name);
st.print_cr(" @ bci %d ", bci);
if (Verbose) {
vf->print();
tty->cr();
vf->print_on(&st);
st.cr();
}
}
tty->print_raw(st.as_string());
}
#endif
@ -1541,7 +1544,6 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re
#ifndef PRODUCT
if (PrintDeoptimizationDetails) {
ttyLocker ttyl;
tty->print_cr(" Created vframeArray " INTPTR_FORMAT, p2i(array));
}
#endif // PRODUCT
@ -1849,7 +1851,6 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr
bool is_receiver_constraint_failure = COMPILER2_PRESENT(VerifyReceiverTypes &&) (reason == Deoptimization::Reason_receiver_constraint);
if (TraceDeoptimization || is_receiver_constraint_failure) {
ttyLocker ttyl;
tty->print_cr(" bci=%d pc=" INTPTR_FORMAT ", relative_pc=" INTPTR_FORMAT ", method=%s" JVMCI_ONLY(", debug_id=%d"), trap_scope->bci(), p2i(fr.pc()), fr.pc() - nm->code_begin(), trap_scope->method()->name_and_sig_as_C_string()
#if INCLUDE_JVMCI
, debug_id

View file

@ -182,7 +182,6 @@ class Deoptimization : AllStatic {
static bool relock_objects(JavaThread* thread, GrowableArray<MonitorInfo*>* monitors,
JavaThread* deoptee_thread, frame& fr, int exec_mode, bool realloc_failures);
static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array);
NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures);)
#endif // COMPILER2_OR_JVMCI
public:

View file

@ -45,10 +45,10 @@ class Mutex : public CHeapObj<mtSynchronizer> {
// Special low level locks are given names and ranges avoid overlap.
enum lock_types {
event,
service = event + 3,
tty = event + 3,
service = tty + 3,
stackwatermark = service + 3,
tty = stackwatermark + 3,
special = tty + 3,
special = stackwatermark + 3,
oopstorage = special + 3,
leaf = oopstorage + 2,
safepoint = leaf + 10,

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, 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
@ -33,6 +33,18 @@
* compiler.uncommontrap.TestDeoptOOM
*/
/*
* @test
* @bug 8273456
* @summary Test that ttyLock isn't held when taking StackWatermark_lock
* @requires !vm.graal.enabled & vm.gc.Z
* @run main/othervm -XX:-BackgroundCompilation -Xmx128M -XX:+IgnoreUnrecognizedVMOptions -XX:+VerifyStack
* -XX:CompileCommand=exclude,compiler.uncommontrap.TestDeoptOOM::main
* -XX:CompileCommand=exclude,compiler.uncommontrap.TestDeoptOOM::m9_1
* -XX:+UseZGC -XX:+LogCompilation -XX:+PrintDeoptimizationDetails -XX:+TraceDeoptimization -XX:+Verbose
* compiler.uncommontrap.TestDeoptOOM
*/
package compiler.uncommontrap;
public class TestDeoptOOM {