8319244: implement JVMTI handshakes support for virtual threads

Reviewed-by: pchilanomate, amenkov
This commit is contained in:
Serguei Spitsyn 2023-11-21 08:17:43 +00:00
parent 46e4028adf
commit 839dd65366
4 changed files with 164 additions and 360 deletions

View File

@ -1711,47 +1711,9 @@ JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jth
// count_ptr - pre-checked for null
jvmtiError
JvmtiEnv::GetStackTrace(jthread thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) {
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
JvmtiVTMSTransitionDisabler disabler(thread);
ThreadsListHandle tlh(current_thread);
JavaThread* java_thread = nullptr;
oop thread_obj = nullptr;
jvmtiError err = get_threadOop_and_JavaThread(tlh.list(), thread, &java_thread, &thread_obj);
if (err != JVMTI_ERROR_NONE) {
return err;
}
if (java_lang_VirtualThread::is_instance(thread_obj)) {
if (java_thread == nullptr) { // Target virtual thread is unmounted.
ResourceMark rm(current_thread);
VM_VirtualThreadGetStackTrace op(this, Handle(current_thread, thread_obj),
start_depth, max_frame_count,
frame_buffer, count_ptr);
VMThread::execute(&op);
return op.result();
}
VirtualThreadGetStackTraceClosure op(this, Handle(current_thread, thread_obj),
start_depth, max_frame_count, frame_buffer, count_ptr);
Handshake::execute(&op, java_thread);
return op.result();
}
// It is only safe to perform the direct operation on the current
// thread. All other usage needs to use a direct handshake for safety.
if (java_thread == JavaThread::current()) {
err = get_stack_trace(java_thread, start_depth, max_frame_count, frame_buffer, count_ptr);
} else {
// Get stack trace with handshake.
GetStackTraceClosure op(this, start_depth, max_frame_count, frame_buffer, count_ptr);
Handshake::execute(&op, java_thread);
err = op.result();
}
return err;
GetStackTraceClosure op(this, start_depth, max_frame_count, frame_buffer, count_ptr);
JvmtiHandshake::execute(&op, thread);
return op.result();
} /* end GetStackTrace */
@ -1829,41 +1791,9 @@ JvmtiEnv::GetThreadListStackTraces(jint thread_count, const jthread* thread_list
// count_ptr - pre-checked for null
jvmtiError
JvmtiEnv::GetFrameCount(jthread thread, jint* count_ptr) {
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
JvmtiVTMSTransitionDisabler disabler(thread);
ThreadsListHandle tlh(current_thread);
JavaThread* java_thread = nullptr;
oop thread_obj = nullptr;
jvmtiError err = get_threadOop_and_JavaThread(tlh.list(), thread, &java_thread, &thread_obj);
if (err != JVMTI_ERROR_NONE) {
return err;
}
if (java_lang_VirtualThread::is_instance(thread_obj)) {
if (java_thread == nullptr) { // Target virtual thread is unmounted.
VM_VirtualThreadGetFrameCount op(this, Handle(current_thread, thread_obj), count_ptr);
VMThread::execute(&op);
return op.result();
}
VirtualThreadGetFrameCountClosure op(this, Handle(current_thread, thread_obj), count_ptr);
Handshake::execute(&op, java_thread);
return op.result();
}
// It is only safe to perform the direct operation on the current
// thread. All other usage needs to use a direct handshake for safety.
if (java_thread == JavaThread::current()) {
err = get_frame_count(java_thread, count_ptr);
} else {
// get java stack frame count with handshake.
GetFrameCountClosure op(this, count_ptr);
Handshake::execute(&op, java_thread);
err = op.result();
}
return err;
GetFrameCountClosure op(this, count_ptr);
JvmtiHandshake::execute(&op, thread);
return op.result();
} /* end GetFrameCount */
@ -1923,41 +1853,9 @@ JvmtiEnv::PopFrame(jthread thread) {
// location_ptr - pre-checked for null
jvmtiError
JvmtiEnv::GetFrameLocation(jthread thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr) {
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
JvmtiVTMSTransitionDisabler disabler(thread);
ThreadsListHandle tlh(current_thread);
JavaThread* java_thread = nullptr;
oop thread_obj = nullptr;
jvmtiError err = get_threadOop_and_JavaThread(tlh.list(), thread, &java_thread, &thread_obj);
if (err != JVMTI_ERROR_NONE) {
return err;
}
if (java_lang_VirtualThread::is_instance(thread_obj)) {
if (java_thread == nullptr) { // Target virtual thread is unmounted.
err = get_frame_location(thread_obj, depth, method_ptr, location_ptr);
return err;
}
VirtualThreadGetFrameLocationClosure op(this, Handle(current_thread, thread_obj),
depth, method_ptr, location_ptr);
Handshake::execute(&op, java_thread);
return op.result();
}
// It is only safe to perform the direct operation on the current
// thread. All other usage needs to use a direct handshake for safety.
if (java_thread == JavaThread::current()) {
err = get_frame_location(java_thread, depth, method_ptr, location_ptr);
} else {
// JVMTI get java stack frame location via direct handshake.
GetFrameLocationClosure op(this, depth, method_ptr, location_ptr);
Handshake::execute(&op, java_thread);
err = op.result();
}
return err;
GetFrameLocationClosure op(this, depth, method_ptr, location_ptr);
JvmtiHandshake::execute(&op, thread);
return op.result();
} /* end GetFrameLocation */
@ -1984,25 +1882,9 @@ JvmtiEnv::NotifyFramePop(jthread thread, jint depth) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
if (java_lang_VirtualThread::is_instance(thread_handle())) {
VirtualThreadSetFramePopClosure op(this, thread_handle, state, depth);
MutexLocker mu(current, JvmtiThreadState_lock);
if (java_thread == nullptr || java_thread == current) {
// Target virtual thread is unmounted or current.
op.doit(java_thread, true /* self */);
} else {
Handshake::execute(&op, java_thread);
}
return op.result();
}
SetFramePopClosure op(this, state, depth);
MutexLocker mu(current, JvmtiThreadState_lock);
if (java_thread == current) {
op.doit(java_thread, true /* self */);
} else {
Handshake::execute(&op, java_thread);
}
JvmtiHandshake::execute(&op, &tlh, java_thread, thread_handle);
return op.result();
} /* end NotifyFramePop */

View File

@ -625,8 +625,9 @@ JvmtiEnvBase::get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd
bool
JvmtiEnvBase::is_vthread_alive(oop vt) {
return java_lang_VirtualThread::state(vt) != java_lang_VirtualThread::NEW &&
java_lang_VirtualThread::state(vt) != java_lang_VirtualThread::TERMINATED;
oop cont = java_lang_VirtualThread::continuation(vt);
return !jdk_internal_vm_Continuation::done(cont) &&
java_lang_VirtualThread::state(vt) != java_lang_VirtualThread::NEW;
}
// Return JavaThread if virtual thread is mounted, null otherwise.
@ -1243,9 +1244,6 @@ JvmtiEnvBase::get_frame_count(JavaThread* jt, jint *count_ptr) {
jvmtiError
JvmtiEnvBase::get_frame_count(oop vthread_oop, jint *count_ptr) {
if (!JvmtiEnvBase::is_vthread_alive(vthread_oop)) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
Thread *current_thread = Thread::current();
ResourceMark rm(current_thread);
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(vthread_oop);
@ -1300,9 +1298,6 @@ JvmtiEnvBase::get_frame_location(JavaThread *java_thread, jint depth,
jvmtiError
JvmtiEnvBase::get_frame_location(oop vthread_oop, jint depth,
jmethodID* method_ptr, jlocation* location_ptr) {
if (!JvmtiEnvBase::is_vthread_alive(vthread_oop)) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
Thread* current = Thread::current();
ResourceMark rm(current);
HandleMark hm(current);
@ -1944,6 +1939,74 @@ MultipleStackTracesCollector::allocate_and_fill_stacks(jint thread_count) {
"the last copied frame info must be the last record");
}
// AdapterClosure is to make use of JvmtiUnitedHandshakeClosure objects from
// Handshake::execute() which is unaware of the do_vthread() member functions.
class AdapterClosure : public HandshakeClosure {
JvmtiUnitedHandshakeClosure* _hs_cl;
Handle _target_h;
public:
AdapterClosure(JvmtiUnitedHandshakeClosure* hs_cl, Handle target_h)
: HandshakeClosure(hs_cl->name()), _hs_cl(hs_cl), _target_h(target_h) {}
virtual void do_thread(Thread* target) {
if (java_lang_VirtualThread::is_instance(_target_h())) {
_hs_cl->do_vthread(_target_h); // virtual thread
} else {
_hs_cl->do_thread(target); // platform thread
}
}
};
// Supports platform and virtual threads.
// JvmtiVTMSTransitionDisabler is always set by this function.
void
JvmtiHandshake::execute(JvmtiUnitedHandshakeClosure* hs_cl, jthread target) {
JavaThread* current = JavaThread::current();
HandleMark hm(current);
JvmtiVTMSTransitionDisabler disabler(target);
ThreadsListHandle tlh(current);
JavaThread* java_thread = nullptr;
oop thread_obj = nullptr;
jvmtiError err = JvmtiEnvBase::get_threadOop_and_JavaThread(tlh.list(), target, &java_thread, &thread_obj);
if (err != JVMTI_ERROR_NONE) {
hs_cl->set_result(err);
return;
}
Handle target_h(current, thread_obj);
execute(hs_cl, &tlh, java_thread, target_h);
}
// Supports platform and virtual threads.
// A virtual thread is always identified by the target_h oop handle.
// The target_jt is always nullptr for an unmounted virtual thread.
// JvmtiVTMSTransitionDisabler has to be set before call to this function.
void
JvmtiHandshake::execute(JvmtiUnitedHandshakeClosure* hs_cl, ThreadsListHandle* tlh,
JavaThread* target_jt, Handle target_h) {
bool self = target_jt == JavaThread::current();
hs_cl->set_self(self); // needed when suspend is required for non-current target thread
if (java_lang_VirtualThread::is_instance(target_h())) { // virtual thread
if (!JvmtiEnvBase::is_vthread_alive(target_h())) {
return;
}
if (target_jt == nullptr) { // unmounted virtual thread
hs_cl->do_vthread(target_h); // execute handshake closure callback on current thread directly
}
}
if (target_jt != nullptr) { // mounted virtual or platform thread
AdapterClosure acl(hs_cl, target_h);
if (self) { // target platform thread is current
acl.do_thread(target_jt); // execute handshake closure callback on current thread directly
} else {
Handshake::execute(&acl, tlh, target_jt); // delegate to Handshake implementation
}
}
}
void
VM_GetThreadListStackTraces::doit() {
@ -2335,16 +2398,15 @@ UpdateForPopTopFrameClosure::doit(Thread *target, bool self) {
}
void
SetFramePopClosure::doit(Thread *target, bool self) {
ResourceMark rm;
SetFramePopClosure::do_thread(Thread *target) {
Thread* current = Thread::current();
JavaThread* java_thread = JavaThread::cast(target);
if (java_thread->is_exiting()) {
return; /* JVMTI_ERROR_THREAD_NOT_ALIVE (default) */
return; // JVMTI_ERROR_THREAD_NOT_ALIVE (default)
}
assert(_state->get_thread_or_saved() == java_thread, "Must be");
if (!self && !java_thread->is_suspended()) {
if (!_self && !java_thread->is_suspended()) {
_result = JVMTI_ERROR_THREAD_NOT_SUSPENDED;
return;
}
@ -2352,6 +2414,8 @@ SetFramePopClosure::doit(Thread *target, bool self) {
_result = JVMTI_ERROR_NO_MORE_FRAMES;
return;
}
assert(_state->get_thread_or_saved() == java_thread, "Must be");
RegisterMap reg_map(java_thread,
RegisterMap::UpdateMap::include,
RegisterMap::ProcessFrames::skip,
@ -2360,6 +2424,16 @@ SetFramePopClosure::doit(Thread *target, bool self) {
_result = ((JvmtiEnvBase*)_env)->set_frame_pop(_state, jvf, _depth);
}
void
SetFramePopClosure::do_vthread(Handle target_h) {
if (!_self && !JvmtiVTSuspender::is_vthread_suspended(target_h())) {
_result = JVMTI_ERROR_THREAD_NOT_SUSPENDED;
return;
}
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(target_h());
_result = ((JvmtiEnvBase*)_env)->set_frame_pop(_state, jvf, _depth);
}
void
GetOwnedMonitorInfoClosure::do_thread(Thread *target) {
JavaThread *jt = JavaThread::cast(target);
@ -2381,22 +2455,11 @@ GetCurrentContendedMonitorClosure::do_thread(Thread *target) {
}
}
void
VM_VirtualThreadGetStackTrace::doit() {
if (!JvmtiEnvBase::is_vthread_alive(_vthread_h())) {
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
return;
}
ResourceMark rm;
javaVFrame* jvf = JvmtiEnvBase::get_vthread_jvf(_vthread_h());
_result = ((JvmtiEnvBase *)_env)->get_stack_trace(jvf,
_start_depth, _max_count,
_frame_buffer, _count_ptr);
}
void
GetStackTraceClosure::do_thread(Thread *target) {
Thread* current = Thread::current();
ResourceMark rm(current);
JavaThread *jt = JavaThread::cast(target);
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
_result = ((JvmtiEnvBase *)_env)->get_stack_trace(jt,
@ -2405,6 +2468,17 @@ GetStackTraceClosure::do_thread(Thread *target) {
}
}
void
GetStackTraceClosure::do_vthread(Handle target_h) {
Thread* current = Thread::current();
ResourceMark rm(current);
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(target_h());
_result = ((JvmtiEnvBase *)_env)->get_stack_trace(jvf,
_start_depth, _max_count,
_frame_buffer, _count_ptr);
}
#ifdef ASSERT
void
PrintStackTraceClosure::do_thread_impl(Thread *target) {
@ -2454,29 +2528,38 @@ PrintStackTraceClosure::do_thread(Thread *target) {
}
#endif
void
VM_VirtualThreadGetFrameCount::doit() {
_result = ((JvmtiEnvBase*)_env)->get_frame_count(_vthread_h(), _count_ptr);
}
void
GetFrameCountClosure::do_thread(Thread *target) {
JavaThread* jt = JavaThread::cast(target);
assert(target == jt, "just checking");
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
_result = ((JvmtiEnvBase*)_env)->get_frame_count(jt, _count_ptr);
}
}
void
GetFrameCountClosure::do_vthread(Handle target_h) {
_result = ((JvmtiEnvBase*)_env)->get_frame_count(target_h(), _count_ptr);
}
void
GetFrameLocationClosure::do_thread(Thread *target) {
JavaThread *jt = JavaThread::cast(target);
assert(target == jt, "just checking");
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
_result = ((JvmtiEnvBase*)_env)->get_frame_location(jt, _depth,
_method_ptr, _location_ptr);
}
}
void
GetFrameLocationClosure::do_vthread(Handle target_h) {
_result = ((JvmtiEnvBase*)_env)->get_frame_location(target_h(), _depth,
_method_ptr, _location_ptr);
}
void
VirtualThreadGetOwnedMonitorInfoClosure::do_thread(Thread *target) {
if (!JvmtiEnvBase::is_vthread_alive(_vthread_h())) {
@ -2506,36 +2589,6 @@ VirtualThreadGetThreadClosure::do_thread(Thread *target) {
*_carrier_thread_ptr = (jthread)JNIHandles::make_local(jt, carrier_thread);
}
void
VirtualThreadGetStackTraceClosure::do_thread(Thread *target) {
assert(target->is_Java_thread(), "just checking");
if (!JvmtiEnvBase::is_vthread_alive(_vthread_h())) {
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
return;
}
Thread* cur_thread = Thread::current();
ResourceMark rm(cur_thread);
HandleMark hm(cur_thread);
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(_vthread_h());
_result = ((JvmtiEnvBase *)_env)->get_stack_trace(jvf,
_start_depth, _max_count,
_frame_buffer, _count_ptr);
}
void
VirtualThreadGetFrameCountClosure::do_thread(Thread *target) {
assert(target->is_Java_thread(), "just checking");
_result = ((JvmtiEnvBase*)_env)->get_frame_count(_vthread_h(), _count_ptr);
}
void
VirtualThreadGetFrameLocationClosure::do_thread(Thread *target) {
assert(target->is_Java_thread(), "just checking");
_result = ((JvmtiEnvBase*)_env)->get_frame_location(_vthread_h(), _depth,
_method_ptr, _location_ptr);
}
void
VirtualThreadGetThreadStateClosure::do_thread(Thread *target) {
assert(target->is_Java_thread(), "just checking");
@ -2558,18 +2611,3 @@ VirtualThreadGetThreadStateClosure::do_thread(Thread *target) {
*_state_ptr = state;
_result = JVMTI_ERROR_NONE;
}
void
VirtualThreadSetFramePopClosure::doit(Thread *target, bool self) {
if (!JvmtiEnvBase::is_vthread_alive(_vthread_h())) {
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
return;
}
if (!self && !JvmtiVTSuspender::is_vthread_suspended(_vthread_h())) {
_result = JVMTI_ERROR_THREAD_NOT_SUSPENDED;
return;
}
ResourceMark rm;
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(_vthread_h());
_result = ((JvmtiEnvBase*)_env)->set_frame_pop(_state, jvf, _depth);
}

View File

@ -463,6 +463,32 @@ class JvmtiHandshakeClosure : public HandshakeClosure {
jvmtiError result() { return _result; }
};
// Used in combination with the JvmtiHandshake class.
// It is intended to support both platform and virtual threads.
class JvmtiUnitedHandshakeClosure : public HandshakeClosure {
protected:
jvmtiError _result;
bool _self;
public:
JvmtiUnitedHandshakeClosure(const char* name)
: HandshakeClosure(name),
_result(JVMTI_ERROR_THREAD_NOT_ALIVE),
_self(false) {}
void set_result(jvmtiError err) { _result = err; }
void set_self(bool val) { _self = val; }
jvmtiError result() { return _result; }
virtual void do_vthread(Handle target_h) = 0;
};
// The JvmtiHandshake supports virtual threads.
class JvmtiHandshake : public Handshake {
public:
static void execute(JvmtiUnitedHandshakeClosure* hs_cl, ThreadsListHandle* tlh,
JavaThread* target_jt, Handle target_h);
static void execute(JvmtiUnitedHandshakeClosure* hs_cl, jthread target);
};
class SetForceEarlyReturn : public JvmtiHandshakeClosure {
private:
JvmtiThreadState* _state;
@ -496,7 +522,7 @@ public:
};
// HandshakeClosure to set frame pop.
class SetFramePopClosure : public JvmtiHandshakeClosure {
class SetFramePopClosure : public JvmtiUnitedHandshakeClosure {
private:
JvmtiEnv *_env;
JvmtiThreadState* _state;
@ -504,14 +530,12 @@ private:
public:
SetFramePopClosure(JvmtiEnv *env, JvmtiThreadState* state, jint depth)
: JvmtiHandshakeClosure("SetFramePopClosure"),
: JvmtiUnitedHandshakeClosure("SetFramePopClosure"),
_env(env),
_state(state),
_depth(depth) {}
void do_thread(Thread *target) {
doit(target, false /* self */);
}
void doit(Thread *target, bool self);
void do_thread(Thread *target);
void do_vthread(Handle target_h);
};
// HandshakeClosure to get monitor information with stack depth.
@ -574,7 +598,7 @@ public:
};
// HandshakeClosure to get stack trace.
class GetStackTraceClosure : public JvmtiHandshakeClosure {
class GetStackTraceClosure : public JvmtiUnitedHandshakeClosure {
private:
JvmtiEnv *_env;
jint _start_depth;
@ -585,13 +609,14 @@ private:
public:
GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count,
jvmtiFrameInfo* frame_buffer, jint* count_ptr)
: JvmtiHandshakeClosure("GetStackTrace"),
: JvmtiUnitedHandshakeClosure("GetStackTrace"),
_env(env),
_start_depth(start_depth),
_max_count(max_count),
_frame_buffer(frame_buffer),
_count_ptr(count_ptr) {}
void do_thread(Thread *target);
void do_vthread(Handle target_h);
};
#ifdef ASSERT
@ -684,54 +709,6 @@ public:
jvmtiError result() { return _collector.result(); }
};
class VM_VirtualThreadGetStackTrace : public VM_Operation {
private:
JvmtiEnv *_env;
Handle _vthread_h;
jint _start_depth;
jint _max_count;
jvmtiFrameInfo* _frame_buffer;
jint* _count_ptr;
jvmtiError _result;
public:
VM_VirtualThreadGetStackTrace(JvmtiEnv *env, Handle vthread_h,
jint start_depth, jint max_count,
jvmtiFrameInfo* frame_buffer, jint* count_ptr)
: _env(env),
_vthread_h(vthread_h),
_start_depth(start_depth),
_max_count(max_count),
_frame_buffer(frame_buffer),
_count_ptr(count_ptr),
_result(JVMTI_ERROR_NONE)
{}
VMOp_Type type() const { return VMOp_VirtualThreadGetStackTrace; }
void doit();
jvmtiError result() { return _result; }
};
class VM_VirtualThreadGetFrameCount : public VM_Operation {
private:
JvmtiEnv *_env;
Handle _vthread_h;
jint* _count_ptr;
jvmtiError _result;
public:
VM_VirtualThreadGetFrameCount(JvmtiEnv *env, Handle vthread_h, jint* count_ptr)
: _env(env),
_vthread_h(vthread_h),
_count_ptr(count_ptr),
_result(JVMTI_ERROR_NONE)
{}
VMOp_Type type() const { return VMOp_VirtualThreadGetFrameCount; }
void doit();
jvmtiError result() { return _result; }
};
// HandshakeClosure to get single stack trace.
class GetSingleStackTraceClosure : public HandshakeClosure {
private:
@ -753,21 +730,22 @@ public:
};
// HandshakeClosure to count stack frames.
class GetFrameCountClosure : public JvmtiHandshakeClosure {
class GetFrameCountClosure : public JvmtiUnitedHandshakeClosure {
private:
JvmtiEnv *_env;
jint *_count_ptr;
public:
GetFrameCountClosure(JvmtiEnv *env, jint *count_ptr)
: JvmtiHandshakeClosure("GetFrameCount"),
: JvmtiUnitedHandshakeClosure("GetFrameCount"),
_env(env),
_count_ptr(count_ptr) {}
void do_thread(Thread *target);
void do_vthread(Handle target_h);
};
// HandshakeClosure to get frame location.
class GetFrameLocationClosure : public JvmtiHandshakeClosure {
class GetFrameLocationClosure : public JvmtiUnitedHandshakeClosure {
private:
JvmtiEnv *_env;
jint _depth;
@ -777,12 +755,13 @@ private:
public:
GetFrameLocationClosure(JvmtiEnv *env, jint depth,
jmethodID* method_ptr, jlocation* location_ptr)
: JvmtiHandshakeClosure("GetFrameLocation"),
: JvmtiUnitedHandshakeClosure("GetFrameLocation"),
_env(env),
_depth(depth),
_method_ptr(method_ptr),
_location_ptr(location_ptr) {}
void do_thread(Thread *target);
void do_vthread(Handle target_h);
};
// HandshakeClosure to get virtual thread monitor information with stack depth.
@ -825,77 +804,6 @@ public:
jvmtiError result() { return _result; }
};
// HandshakeClosure to get virtual thread stack trace at safepoint.
class VirtualThreadGetStackTraceClosure : public HandshakeClosure {
private:
JvmtiEnv *_env;
Handle _vthread_h;
jint _start_depth;
jint _max_count;
jvmtiFrameInfo *_frame_buffer;
jint *_count_ptr;
jvmtiError _result;
public:
VirtualThreadGetStackTraceClosure(JvmtiEnv *env, Handle vthread_h,
jint start_depth, jint max_count,
jvmtiFrameInfo* frame_buffer, jint* count_ptr)
: HandshakeClosure("VirtualThreadGetStackTrace"),
_env(env),
_vthread_h(vthread_h),
_start_depth(start_depth),
_max_count(max_count),
_frame_buffer(frame_buffer),
_count_ptr(count_ptr),
_result(JVMTI_ERROR_NONE) {}
void do_thread(Thread *target);
jvmtiError result() { return _result; }
};
// HandshakeClosure to count virtual thread stack frames at safepoint.
class VirtualThreadGetFrameCountClosure : public HandshakeClosure {
private:
JvmtiEnv *_env;
Handle _vthread_h;
jint *_count_ptr;
jvmtiError _result;
public:
VirtualThreadGetFrameCountClosure(JvmtiEnv *env, Handle vthread_h, jint *count_ptr)
: HandshakeClosure("VirtualThreadGetFrameCount"),
_env(env), _vthread_h(vthread_h), _count_ptr(count_ptr),
_result(JVMTI_ERROR_NONE) {}
void do_thread(Thread *target);
jvmtiError result() { return _result; }
};
// HandshakeClosure get to virtual thread frame location at safepoint.
class VirtualThreadGetFrameLocationClosure : public HandshakeClosure {
private:
JvmtiEnv *_env;
Handle _vthread_h;
jint _depth;
jmethodID* _method_ptr;
jlocation* _location_ptr;
jvmtiError _result;
public:
VirtualThreadGetFrameLocationClosure(JvmtiEnv *env, Handle vthread_h, jint depth,
jmethodID* method_ptr, jlocation* location_ptr)
: HandshakeClosure("VirtualThreadGetFrameLocation"),
_env(env),
_vthread_h(vthread_h),
_depth(depth),
_method_ptr(method_ptr),
_location_ptr(location_ptr),
_result(JVMTI_ERROR_NONE) {}
void do_thread(Thread *target);
jvmtiError result() { return _result; }
};
// HandshakeClosure to get virtual thread state at safepoint.
class VirtualThreadGetThreadStateClosure : public HandshakeClosure {
private:
@ -914,28 +822,6 @@ public:
jvmtiError result() { return _result; }
};
// HandshakeClosure to set frame pop for a virtual thread.
class VirtualThreadSetFramePopClosure : public JvmtiHandshakeClosure {
private:
JvmtiEnv *_env;
Handle _vthread_h;
JvmtiThreadState* _state;
jint _depth;
public:
VirtualThreadSetFramePopClosure(JvmtiEnv *env, Handle vthread_h, JvmtiThreadState* state, jint depth)
: JvmtiHandshakeClosure("VirtualThreadSetFramePopClosure"),
_env(env),
_vthread_h(vthread_h),
_state(state),
_depth(depth) {}
void do_thread(Thread *target) {
doit(target, false /* self */);
}
void doit(Thread *target, bool self);
};
// ResourceTracker
//

View File

@ -81,8 +81,6 @@
template(GetObjectMonitorUsage) \
template(GetAllStackTraces) \
template(GetThreadListStackTraces) \
template(VirtualThreadGetStackTrace) \
template(VirtualThreadGetFrameCount) \
template(ChangeBreakpoints) \
template(GetOrSetLocal) \
template(VirtualThreadGetOrSetLocal) \