Skip to content

Commit 7da2477

Browse files
Serguei Spitsynpchilano
andcommitted
6960970: Debugger very slow during stepping
Co-authored-by: Patricio Chilano Mateo <pchilanomate@openjdk.org> Reviewed-by: lmesnik, pchilanomate
1 parent 689800b commit 7da2477

28 files changed

Lines changed: 466 additions & 110 deletions

src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,7 @@ void InterpreterMacroAssembler::notify_method_exit(
11741174
// Whenever JVMTI is interp_only_mode, method entry/exit events are sent to
11751175
// track stack depth. If it is possible to enter interp_only_mode we add
11761176
// the code to check if the event should be sent.
1177-
if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) {
1177+
if (mode == NotifyJVMTI && (JvmtiExport::can_post_interpreter_events() || JvmtiExport::can_post_frame_pop())) {
11781178
Label L;
11791179
// Note: frame::interpreter_frame_result has a dependency on how the
11801180
// method result is saved across the call to post_method_exit. If this
@@ -1183,8 +1183,15 @@ void InterpreterMacroAssembler::notify_method_exit(
11831183

11841184
// template interpreter will leave the result on the top of the stack.
11851185
push(state);
1186-
ldrw(r3, Address(rthread, JavaThread::interp_only_mode_offset()));
1187-
cbz(r3, L);
1186+
1187+
ldr(rscratch1, Address(rthread, JavaThread::jvmti_thread_state_offset()));
1188+
cbz(rscratch1, L); // if (thread->jvmti_thread_state() == nullptr) exit;
1189+
1190+
ldrw(rscratch1, Address(rscratch1, JvmtiThreadState::frame_pop_cnt_offset()));
1191+
ldrw(rscratch2, Address(rthread, JavaThread::interp_only_mode_offset()));
1192+
orrw(rscratch1, rscratch1, rscratch2);
1193+
cbzw(rscratch1, L);
1194+
11881195
call_VM(noreg,
11891196
CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit));
11901197
bind(L);

src/hotspot/cpu/arm/interp_masm_arm.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1576,14 +1576,21 @@ void InterpreterMacroAssembler::notify_method_exit(
15761576
// Whenever JVMTI is interp_only_mode, method entry/exit events are sent to
15771577
// track stack depth. If it is possible to enter interp_only_mode we add
15781578
// the code to check if the event should be sent.
1579-
if (mode == NotifyJVMTI && can_post_interpreter_events()) {
1579+
if (mode == NotifyJVMTI && (can_post_interpreter_events() || JvmtiExport::can_post_frame_pop())) {
15801580
Label L;
1581+
const Register thread_state = R2_tmp;
1582+
15811583
// Note: frame::interpreter_frame_result has a dependency on how the
15821584
// method result is saved across the call to post_method_exit. If this
15831585
// is changed then the interpreter_frame_result implementation will
15841586
// need to be updated too.
15851587

1588+
ldr(thread_state, Address(Rthread, JavaThread::jvmti_thread_state_offset()));
1589+
cbz(thread_state, L); // if (thread->jvmti_thread_state() == nullptr) exit;
1590+
1591+
ldr_s32(thread_state, Address(thread_state, JvmtiThreadState::frame_pop_cnt_offset()));
15861592
ldr_s32(Rtemp, Address(Rthread, JavaThread::interp_only_mode_offset()));
1593+
orr(Rtemp, Rtemp, thread_state);
15871594
cbz(Rtemp, L);
15881595

15891596
if (native) {

src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2345,18 +2345,12 @@ void InterpreterMacroAssembler::notify_method_exit(bool is_native_method, TosSta
23452345
// entry/exit events are sent for that thread to track stack
23462346
// depth. If it is possible to enter interp_only_mode we add
23472347
// the code to check if the event should be sent.
2348-
if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) {
2349-
Label jvmti_post_done;
2350-
2351-
lwz(R0, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread);
2352-
cmpwi(CR0, R0, 0);
2353-
beq(CR0, jvmti_post_done);
2348+
if (mode == NotifyJVMTI && (JvmtiExport::can_post_interpreter_events() || JvmtiExport::can_post_frame_pop())) {
23542349
if (!is_native_method) { push(state); } // Expose tos to GC.
23552350
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit), check_exceptions);
23562351
if (!is_native_method) { pop(state); }
23572352

23582353
align(32, 12);
2359-
bind(jvmti_post_done);
23602354
}
23612355

23622356
// Dtrace support not implemented.

src/hotspot/cpu/riscv/interp_masm_riscv.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,20 +1220,16 @@ void InterpreterMacroAssembler::notify_method_exit(
12201220
// Whenever JVMTI is interp_only_mode, method entry/exit events are sent to
12211221
// track stack depth. If it is possible to enter interp_only_mode we add
12221222
// the code to check if the event should be sent.
1223-
if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) {
1224-
Label L;
1223+
if (mode == NotifyJVMTI && (JvmtiExport::can_post_interpreter_events() || JvmtiExport::can_post_frame_pop())) {
12251224
// Note: frame::interpreter_frame_result has a dependency on how the
12261225
// method result is saved across the call to post_method_exit. If this
12271226
// is changed then the interpreter_frame_result implementation will
12281227
// need to be updated too.
12291228

12301229
// template interpreter will leave the result on the top of the stack.
12311230
push(state);
1232-
lwu(x13, Address(xthread, JavaThread::interp_only_mode_offset()));
1233-
beqz(x13, L);
12341231
call_VM(noreg,
12351232
CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit));
1236-
bind(L);
12371233
pop(state);
12381234
}
12391235

src/hotspot/cpu/s390/interp_masm_s390.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,14 +2002,10 @@ void InterpreterMacroAssembler::notify_method_exit(bool native_method,
20022002
// entry/exit events are sent for that thread to track stack
20032003
// depth. If it is possible to enter interp_only_mode we add
20042004
// the code to check if the event should be sent.
2005-
if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) {
2006-
Label jvmti_post_done;
2007-
MacroAssembler::load_and_test_int(Z_R0, Address(Z_thread, JavaThread::interp_only_mode_offset()));
2008-
z_bre(jvmti_post_done);
2005+
if (mode == NotifyJVMTI && (JvmtiExport::can_post_interpreter_events() || JvmtiExport::can_post_frame_pop())) {
20092006
if (!native_method) push(state); // see frame::interpreter_frame_result()
20102007
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit));
20112008
if (!native_method) pop(state);
2012-
bind(jvmti_post_done);
20132009
}
20142010
}
20152011

src/hotspot/cpu/x86/interp_masm_x86.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,7 +1603,7 @@ void InterpreterMacroAssembler::notify_method_exit(
16031603
// the code to check if the event should be sent.
16041604
Register rthread = r15_thread;
16051605
Register rarg = c_rarg1;
1606-
if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) {
1606+
if (mode == NotifyJVMTI && (JvmtiExport::can_post_interpreter_events() || JvmtiExport::can_post_frame_pop())) {
16071607
Label L;
16081608
// Note: frame::interpreter_frame_result has a dependency on how the
16091609
// method result is saved across the call to post_method_exit. If this
@@ -1612,9 +1612,18 @@ void InterpreterMacroAssembler::notify_method_exit(
16121612

16131613
// template interpreter will leave the result on the top of the stack.
16141614
push(state);
1615-
movl(rdx, Address(rthread, JavaThread::interp_only_mode_offset()));
1616-
testl(rdx, rdx);
1615+
1616+
movptr(rdx, Address(rthread, JavaThread::jvmti_thread_state_offset()));
1617+
testptr(rdx, rdx);
1618+
jcc(Assembler::zero, L); // if (thread->jvmti_thread_state() == nullptr) exit;
1619+
1620+
movl(rdx, Address(rdx, JvmtiThreadState::frame_pop_cnt_offset()));
1621+
movl(rcx, Address(rthread, JavaThread::interp_only_mode_offset()));
1622+
1623+
orl(rdx, rcx);
1624+
testl(rdx,rdx);
16171625
jcc(Assembler::zero, L);
1626+
16181627
call_VM(noreg,
16191628
CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit));
16201629
bind(L);

src/hotspot/share/interpreter/interpreterRuntime.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,10 @@ JRT_ENTRY(nmethod*,
10571057

10581058
LastFrameAccessor last_frame(current);
10591059
assert(last_frame.is_interpreted_frame(), "must come from interpreter");
1060+
1061+
if (JvmtiExport::can_post_frame_pop() && JvmtiExport::has_frame_pop_for_top_frame(current)) {
1062+
return nullptr; // no OSR if there is a FramePop event request for top frame
1063+
}
10601064
methodHandle method(current, last_frame.method());
10611065
const int branch_bci = branch_bcp != nullptr ? method->bci_from(branch_bcp) : InvocationEntryBci;
10621066
const int bci = branch_bcp != nullptr ? method->bci_from(last_frame.bcp()) : InvocationEntryBci;

src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -3145,10 +3145,14 @@ void BytecodeInterpreter::run(interpreterState istate) {
31453145
// Whenever JVMTI puts a thread in interp_only_mode, method
31463146
// entry/exit events are sent for that thread to track stack depth.
31473147

3148-
if (JVMTI_ENABLED && !suppress_exit_event && THREAD->is_interp_only_mode()) {
3149-
// Prevent any HandleMarkCleaner from freeing our live handles
3150-
HandleMark __hm(THREAD);
3151-
CALL_VM_NOCHECK(InterpreterRuntime::post_method_exit(THREAD));
3148+
if (JVMTI_ENABLED && !suppress_exit_event) {
3149+
JvmtiThreadState* state = THREAD->jvmti_thread_state();
3150+
int frame_pop_cnt = state == nullptr ? 0 : state->frame_pop_cnt();
3151+
if (THREAD->is_interp_only_mode() || frame_pop_cnt) {
3152+
// Prevent any HandleMarkCleaner from freeing our live handles
3153+
HandleMark __hm(THREAD);
3154+
CALL_VM_NOCHECK(InterpreterRuntime::post_method_exit(THREAD));
3155+
}
31523156
}
31533157

31543158
//

src/hotspot/share/oops/stackChunkOop.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -154,6 +154,7 @@ class stackChunkOopDesc : public instanceOopDesc {
154154
inline void set_has_bitmap(bool value);
155155

156156
inline bool has_thaw_slowpath_condition() const;
157+
inline void force_slow_path();
157158

158159
inline bool requires_barriers();
159160

src/hotspot/share/oops/stackChunkOop.inline.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -192,6 +192,15 @@ inline void stackChunkOopDesc::set_has_bitmap(bool value) { set_flag(FL
192192

193193
inline bool stackChunkOopDesc::has_thaw_slowpath_condition() const { return flags() != 0; }
194194

195+
inline void stackChunkOopDesc::force_slow_path() {
196+
#if INCLUDE_ZGC || INCLUDE_SHENANDOAHGC
197+
if (UseZGC || UseShenandoahGC) {
198+
relativize_derived_pointers_concurrently();
199+
}
200+
#endif
201+
set_flag(FLAG_HAS_INTERPRETED_FRAMES, true);
202+
}
203+
195204
inline bool stackChunkOopDesc::requires_barriers() {
196205
return Universe::heap()->requires_barriers(this);
197206
}

0 commit comments

Comments
 (0)