Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.

Commit 4d75aef

Browse files
committed
8238585: JvmtiEventControllerPrivate::enter_interp_only_mode() should not make compiled methods on stack not_entrant
Reviewed-by: mdoerr, kvn, sspitsyn
1 parent 8384f7f commit 4d75aef

File tree

5 files changed

+43
-63
lines changed

5 files changed

+43
-63
lines changed

src/hotspot/share/prims/jvmtiEnvBase.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,6 @@ class VM_SetFramePop : public VM_Operation {
367367
_depth = depth;
368368
_result = JVMTI_ERROR_NONE;
369369
}
370-
// Nested operation must be allowed for the VM_EnterInterpOnlyMode that is
371-
// called from the JvmtiEventControllerPrivate::recompute_thread_enabled.
372-
bool allow_nested_vm_operations() const { return true; }
373370
VMOp_Type type() const { return VMOp_SetFramePop; }
374371
jvmtiError result() { return _result; }
375372
void doit();

src/hotspot/share/prims/jvmtiEventController.cpp

Lines changed: 33 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2020, 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
@@ -33,7 +33,7 @@
3333
#include "prims/jvmtiImpl.hpp"
3434
#include "prims/jvmtiThreadState.inline.hpp"
3535
#include "runtime/deoptimization.hpp"
36-
#include "runtime/frame.hpp"
36+
#include "runtime/frame.inline.hpp"
3737
#include "runtime/thread.inline.hpp"
3838
#include "runtime/threadSMR.hpp"
3939
#include "runtime/vframe.hpp"
@@ -190,60 +190,38 @@ JvmtiEnvEventEnable::~JvmtiEnvEventEnable() {
190190

191191
///////////////////////////////////////////////////////////////
192192
//
193-
// VM_EnterInterpOnlyMode
193+
// EnterInterpOnlyModeClosure
194194
//
195195

196-
class VM_EnterInterpOnlyMode : public VM_Operation {
197-
private:
198-
JvmtiThreadState *_state;
196+
class EnterInterpOnlyModeClosure : public HandshakeClosure {
199197

200198
public:
201-
VM_EnterInterpOnlyMode(JvmtiThreadState *state);
202-
203-
bool allow_nested_vm_operations() const { return true; }
204-
VMOp_Type type() const { return VMOp_EnterInterpOnlyMode; }
205-
void doit();
206-
207-
// to do: this same function is in jvmtiImpl - should be in one place
208-
bool can_be_deoptimized(vframe* vf) {
209-
return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized());
210-
}
211-
};
212-
213-
VM_EnterInterpOnlyMode::VM_EnterInterpOnlyMode(JvmtiThreadState *state)
214-
: _state(state)
215-
{
216-
}
217-
218-
219-
void VM_EnterInterpOnlyMode::doit() {
220-
// Set up the current stack depth for later tracking
221-
_state->invalidate_cur_stack_depth();
222-
223-
_state->enter_interp_only_mode();
224-
225-
JavaThread *thread = _state->get_thread();
226-
if (thread->has_last_Java_frame()) {
227-
// If running in fullspeed mode, single stepping is implemented
228-
// as follows: first, the interpreter does not dispatch to
229-
// compiled code for threads that have single stepping enabled;
230-
// second, we deoptimize all methods on the thread's stack when
231-
// interpreted-only mode is enabled the first time for a given
232-
// thread (nothing to do if no Java frames yet).
233-
int num_marked = 0;
234-
ResourceMark resMark;
235-
RegisterMap rm(thread, false);
236-
for (vframe* vf = thread->last_java_vframe(&rm); vf; vf = vf->sender()) {
237-
if (can_be_deoptimized(vf)) {
238-
((compiledVFrame*) vf)->code()->mark_for_deoptimization();
239-
++num_marked;
199+
EnterInterpOnlyModeClosure() : HandshakeClosure("EnterInterpOnlyMode") { }
200+
void do_thread(Thread* th) {
201+
JavaThread* jt = (JavaThread*) th;
202+
JvmtiThreadState* state = jt->jvmti_thread_state();
203+
204+
// Set up the current stack depth for later tracking
205+
state->invalidate_cur_stack_depth();
206+
207+
state->enter_interp_only_mode();
208+
209+
if (jt->has_last_Java_frame()) {
210+
// If running in fullspeed mode, single stepping is implemented
211+
// as follows: first, the interpreter does not dispatch to
212+
// compiled code for threads that have single stepping enabled;
213+
// second, we deoptimize all compiled java frames on the thread's stack when
214+
// interpreted-only mode is enabled the first time for a given
215+
// thread (nothing to do if no Java frames yet).
216+
ResourceMark resMark;
217+
for (StackFrameStream fst(jt, false); !fst.is_done(); fst.next()) {
218+
if (fst.current()->can_be_deoptimized()) {
219+
Deoptimization::deoptimize(jt, *fst.current());
220+
}
240221
}
241222
}
242-
if (num_marked > 0) {
243-
Deoptimization::deoptimize_all_marked();
244-
}
245223
}
246-
}
224+
};
247225

248226

249227
///////////////////////////////////////////////////////////////
@@ -352,9 +330,12 @@ void VM_ChangeSingleStep::doit() {
352330
void JvmtiEventControllerPrivate::enter_interp_only_mode(JvmtiThreadState *state) {
353331
EC_TRACE(("[%s] # Entering interpreter only mode",
354332
JvmtiTrace::safe_get_thread_name(state->get_thread())));
355-
356-
VM_EnterInterpOnlyMode op(state);
357-
VMThread::execute(&op);
333+
EnterInterpOnlyModeClosure hs;
334+
if (SafepointSynchronize::is_at_safepoint()) {
335+
hs.do_thread(state->get_thread());
336+
} else {
337+
Handshake::execute_direct(&hs, state->get_thread());
338+
}
358339
}
359340

360341

src/hotspot/share/prims/jvmtiThreadState.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2020, 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
@@ -236,9 +236,10 @@ int JvmtiThreadState::count_frames() {
236236

237237

238238
void JvmtiThreadState::invalidate_cur_stack_depth() {
239-
guarantee(SafepointSynchronize::is_at_safepoint() ||
240-
(JavaThread *)Thread::current() == get_thread(),
241-
"must be current thread or at safepoint");
239+
assert(SafepointSynchronize::is_at_safepoint() ||
240+
(JavaThread *)Thread::current() == get_thread() ||
241+
Thread::current() == get_thread()->active_handshaker(),
242+
"bad synchronization with owner thread");
242243

243244
_cur_stack_depth = UNKNOWN_STACK_DEPTH;
244245
}

src/hotspot/share/runtime/thread.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,9 +2032,11 @@ class JavaThread: public Thread {
20322032

20332033
// Used by the interpreter in fullspeed mode for frame pop, method
20342034
// entry, method exit and single stepping support. This field is
2035-
// only set to non-zero by the VM_EnterInterpOnlyMode VM operation.
2036-
// It can be set to zero asynchronously (i.e., without a VM operation
2037-
// or a lock) so we have to be very careful.
2035+
// only set to non-zero at a safepoint or using a direct handshake
2036+
// (see EnterInterpOnlyModeClosure).
2037+
// It can be set to zero asynchronously to this threads execution (i.e., without
2038+
// safepoint/handshake or a lock) so we have to be very careful.
2039+
// Accesses by other threads are synchronized using JvmtiThreadState_lock though.
20382040
int _interp_only_mode;
20392041

20402042
public:

src/hotspot/share/runtime/vmOperations.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@
9090
template(ChangeBreakpoints) \
9191
template(GetOrSetLocal) \
9292
template(GetCurrentLocation) \
93-
template(EnterInterpOnlyMode) \
9493
template(ChangeSingleStep) \
9594
template(HeapWalkOperation) \
9695
template(HeapIterateOperation) \

0 commit comments

Comments
 (0)