8319244: implement JVMTI handshakes support for virtual threads
Reviewed-by: pchilanomate, amenkov
This commit is contained in:
parent
46e4028adf
commit
839dd65366
@ -1711,47 +1711,9 @@ JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jth
|
|||||||
// count_ptr - pre-checked for null
|
// count_ptr - pre-checked for null
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnv::GetStackTrace(jthread thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) {
|
JvmtiEnv::GetStackTrace(jthread thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) {
|
||||||
JavaThread* current_thread = JavaThread::current();
|
GetStackTraceClosure op(this, start_depth, max_frame_count, frame_buffer, count_ptr);
|
||||||
HandleMark hm(current_thread);
|
JvmtiHandshake::execute(&op, thread);
|
||||||
|
return op.result();
|
||||||
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;
|
|
||||||
} /* end GetStackTrace */
|
} /* end GetStackTrace */
|
||||||
|
|
||||||
|
|
||||||
@ -1829,41 +1791,9 @@ JvmtiEnv::GetThreadListStackTraces(jint thread_count, const jthread* thread_list
|
|||||||
// count_ptr - pre-checked for null
|
// count_ptr - pre-checked for null
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnv::GetFrameCount(jthread thread, jint* count_ptr) {
|
JvmtiEnv::GetFrameCount(jthread thread, jint* count_ptr) {
|
||||||
JavaThread* current_thread = JavaThread::current();
|
GetFrameCountClosure op(this, count_ptr);
|
||||||
HandleMark hm(current_thread);
|
JvmtiHandshake::execute(&op, thread);
|
||||||
|
return op.result();
|
||||||
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;
|
|
||||||
} /* end GetFrameCount */
|
} /* end GetFrameCount */
|
||||||
|
|
||||||
|
|
||||||
@ -1923,41 +1853,9 @@ JvmtiEnv::PopFrame(jthread thread) {
|
|||||||
// location_ptr - pre-checked for null
|
// location_ptr - pre-checked for null
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnv::GetFrameLocation(jthread thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr) {
|
JvmtiEnv::GetFrameLocation(jthread thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr) {
|
||||||
JavaThread* current_thread = JavaThread::current();
|
GetFrameLocationClosure op(this, depth, method_ptr, location_ptr);
|
||||||
HandleMark hm(current_thread);
|
JvmtiHandshake::execute(&op, thread);
|
||||||
|
return op.result();
|
||||||
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;
|
|
||||||
} /* end GetFrameLocation */
|
} /* end GetFrameLocation */
|
||||||
|
|
||||||
|
|
||||||
@ -1984,25 +1882,9 @@ JvmtiEnv::NotifyFramePop(jthread thread, jint depth) {
|
|||||||
return JVMTI_ERROR_THREAD_NOT_ALIVE;
|
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);
|
SetFramePopClosure op(this, state, depth);
|
||||||
MutexLocker mu(current, JvmtiThreadState_lock);
|
MutexLocker mu(current, JvmtiThreadState_lock);
|
||||||
if (java_thread == current) {
|
JvmtiHandshake::execute(&op, &tlh, java_thread, thread_handle);
|
||||||
op.doit(java_thread, true /* self */);
|
|
||||||
} else {
|
|
||||||
Handshake::execute(&op, java_thread);
|
|
||||||
}
|
|
||||||
return op.result();
|
return op.result();
|
||||||
} /* end NotifyFramePop */
|
} /* end NotifyFramePop */
|
||||||
|
|
||||||
|
@ -625,8 +625,9 @@ JvmtiEnvBase::get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
JvmtiEnvBase::is_vthread_alive(oop vt) {
|
JvmtiEnvBase::is_vthread_alive(oop vt) {
|
||||||
return java_lang_VirtualThread::state(vt) != java_lang_VirtualThread::NEW &&
|
oop cont = java_lang_VirtualThread::continuation(vt);
|
||||||
java_lang_VirtualThread::state(vt) != java_lang_VirtualThread::TERMINATED;
|
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.
|
// Return JavaThread if virtual thread is mounted, null otherwise.
|
||||||
@ -1243,9 +1244,6 @@ JvmtiEnvBase::get_frame_count(JavaThread* jt, jint *count_ptr) {
|
|||||||
|
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnvBase::get_frame_count(oop vthread_oop, jint *count_ptr) {
|
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();
|
Thread *current_thread = Thread::current();
|
||||||
ResourceMark rm(current_thread);
|
ResourceMark rm(current_thread);
|
||||||
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(vthread_oop);
|
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(vthread_oop);
|
||||||
@ -1300,9 +1298,6 @@ JvmtiEnvBase::get_frame_location(JavaThread *java_thread, jint depth,
|
|||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnvBase::get_frame_location(oop vthread_oop, jint depth,
|
JvmtiEnvBase::get_frame_location(oop vthread_oop, jint depth,
|
||||||
jmethodID* method_ptr, jlocation* location_ptr) {
|
jmethodID* method_ptr, jlocation* location_ptr) {
|
||||||
if (!JvmtiEnvBase::is_vthread_alive(vthread_oop)) {
|
|
||||||
return JVMTI_ERROR_THREAD_NOT_ALIVE;
|
|
||||||
}
|
|
||||||
Thread* current = Thread::current();
|
Thread* current = Thread::current();
|
||||||
ResourceMark rm(current);
|
ResourceMark rm(current);
|
||||||
HandleMark hm(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");
|
"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
|
void
|
||||||
VM_GetThreadListStackTraces::doit() {
|
VM_GetThreadListStackTraces::doit() {
|
||||||
@ -2335,16 +2398,15 @@ UpdateForPopTopFrameClosure::doit(Thread *target, bool self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetFramePopClosure::doit(Thread *target, bool self) {
|
SetFramePopClosure::do_thread(Thread *target) {
|
||||||
ResourceMark rm;
|
Thread* current = Thread::current();
|
||||||
JavaThread* java_thread = JavaThread::cast(target);
|
JavaThread* java_thread = JavaThread::cast(target);
|
||||||
|
|
||||||
if (java_thread->is_exiting()) {
|
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;
|
_result = JVMTI_ERROR_THREAD_NOT_SUSPENDED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2352,6 +2414,8 @@ SetFramePopClosure::doit(Thread *target, bool self) {
|
|||||||
_result = JVMTI_ERROR_NO_MORE_FRAMES;
|
_result = JVMTI_ERROR_NO_MORE_FRAMES;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
assert(_state->get_thread_or_saved() == java_thread, "Must be");
|
||||||
|
|
||||||
RegisterMap reg_map(java_thread,
|
RegisterMap reg_map(java_thread,
|
||||||
RegisterMap::UpdateMap::include,
|
RegisterMap::UpdateMap::include,
|
||||||
RegisterMap::ProcessFrames::skip,
|
RegisterMap::ProcessFrames::skip,
|
||||||
@ -2360,6 +2424,16 @@ SetFramePopClosure::doit(Thread *target, bool self) {
|
|||||||
_result = ((JvmtiEnvBase*)_env)->set_frame_pop(_state, jvf, _depth);
|
_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
|
void
|
||||||
GetOwnedMonitorInfoClosure::do_thread(Thread *target) {
|
GetOwnedMonitorInfoClosure::do_thread(Thread *target) {
|
||||||
JavaThread *jt = JavaThread::cast(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
|
void
|
||||||
GetStackTraceClosure::do_thread(Thread *target) {
|
GetStackTraceClosure::do_thread(Thread *target) {
|
||||||
|
Thread* current = Thread::current();
|
||||||
|
ResourceMark rm(current);
|
||||||
|
|
||||||
JavaThread *jt = JavaThread::cast(target);
|
JavaThread *jt = JavaThread::cast(target);
|
||||||
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
|
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
|
||||||
_result = ((JvmtiEnvBase *)_env)->get_stack_trace(jt,
|
_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
|
#ifdef ASSERT
|
||||||
void
|
void
|
||||||
PrintStackTraceClosure::do_thread_impl(Thread *target) {
|
PrintStackTraceClosure::do_thread_impl(Thread *target) {
|
||||||
@ -2454,29 +2528,38 @@ PrintStackTraceClosure::do_thread(Thread *target) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
|
||||||
VM_VirtualThreadGetFrameCount::doit() {
|
|
||||||
_result = ((JvmtiEnvBase*)_env)->get_frame_count(_vthread_h(), _count_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GetFrameCountClosure::do_thread(Thread *target) {
|
GetFrameCountClosure::do_thread(Thread *target) {
|
||||||
JavaThread* jt = JavaThread::cast(target);
|
JavaThread* jt = JavaThread::cast(target);
|
||||||
assert(target == jt, "just checking");
|
assert(target == jt, "just checking");
|
||||||
|
|
||||||
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
|
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
|
||||||
_result = ((JvmtiEnvBase*)_env)->get_frame_count(jt, _count_ptr);
|
_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
|
void
|
||||||
GetFrameLocationClosure::do_thread(Thread *target) {
|
GetFrameLocationClosure::do_thread(Thread *target) {
|
||||||
JavaThread *jt = JavaThread::cast(target);
|
JavaThread *jt = JavaThread::cast(target);
|
||||||
|
assert(target == jt, "just checking");
|
||||||
|
|
||||||
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
|
if (!jt->is_exiting() && jt->threadObj() != nullptr) {
|
||||||
_result = ((JvmtiEnvBase*)_env)->get_frame_location(jt, _depth,
|
_result = ((JvmtiEnvBase*)_env)->get_frame_location(jt, _depth,
|
||||||
_method_ptr, _location_ptr);
|
_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
|
void
|
||||||
VirtualThreadGetOwnedMonitorInfoClosure::do_thread(Thread *target) {
|
VirtualThreadGetOwnedMonitorInfoClosure::do_thread(Thread *target) {
|
||||||
if (!JvmtiEnvBase::is_vthread_alive(_vthread_h())) {
|
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);
|
*_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
|
void
|
||||||
VirtualThreadGetThreadStateClosure::do_thread(Thread *target) {
|
VirtualThreadGetThreadStateClosure::do_thread(Thread *target) {
|
||||||
assert(target->is_Java_thread(), "just checking");
|
assert(target->is_Java_thread(), "just checking");
|
||||||
@ -2558,18 +2611,3 @@ VirtualThreadGetThreadStateClosure::do_thread(Thread *target) {
|
|||||||
*_state_ptr = state;
|
*_state_ptr = state;
|
||||||
_result = JVMTI_ERROR_NONE;
|
_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);
|
|
||||||
}
|
|
||||||
|
@ -463,6 +463,32 @@ class JvmtiHandshakeClosure : public HandshakeClosure {
|
|||||||
jvmtiError result() { return _result; }
|
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 {
|
class SetForceEarlyReturn : public JvmtiHandshakeClosure {
|
||||||
private:
|
private:
|
||||||
JvmtiThreadState* _state;
|
JvmtiThreadState* _state;
|
||||||
@ -496,7 +522,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// HandshakeClosure to set frame pop.
|
// HandshakeClosure to set frame pop.
|
||||||
class SetFramePopClosure : public JvmtiHandshakeClosure {
|
class SetFramePopClosure : public JvmtiUnitedHandshakeClosure {
|
||||||
private:
|
private:
|
||||||
JvmtiEnv *_env;
|
JvmtiEnv *_env;
|
||||||
JvmtiThreadState* _state;
|
JvmtiThreadState* _state;
|
||||||
@ -504,14 +530,12 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
SetFramePopClosure(JvmtiEnv *env, JvmtiThreadState* state, jint depth)
|
SetFramePopClosure(JvmtiEnv *env, JvmtiThreadState* state, jint depth)
|
||||||
: JvmtiHandshakeClosure("SetFramePopClosure"),
|
: JvmtiUnitedHandshakeClosure("SetFramePopClosure"),
|
||||||
_env(env),
|
_env(env),
|
||||||
_state(state),
|
_state(state),
|
||||||
_depth(depth) {}
|
_depth(depth) {}
|
||||||
void do_thread(Thread *target) {
|
void do_thread(Thread *target);
|
||||||
doit(target, false /* self */);
|
void do_vthread(Handle target_h);
|
||||||
}
|
|
||||||
void doit(Thread *target, bool self);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// HandshakeClosure to get monitor information with stack depth.
|
// HandshakeClosure to get monitor information with stack depth.
|
||||||
@ -574,7 +598,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// HandshakeClosure to get stack trace.
|
// HandshakeClosure to get stack trace.
|
||||||
class GetStackTraceClosure : public JvmtiHandshakeClosure {
|
class GetStackTraceClosure : public JvmtiUnitedHandshakeClosure {
|
||||||
private:
|
private:
|
||||||
JvmtiEnv *_env;
|
JvmtiEnv *_env;
|
||||||
jint _start_depth;
|
jint _start_depth;
|
||||||
@ -585,13 +609,14 @@ private:
|
|||||||
public:
|
public:
|
||||||
GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count,
|
GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count,
|
||||||
jvmtiFrameInfo* frame_buffer, jint* count_ptr)
|
jvmtiFrameInfo* frame_buffer, jint* count_ptr)
|
||||||
: JvmtiHandshakeClosure("GetStackTrace"),
|
: JvmtiUnitedHandshakeClosure("GetStackTrace"),
|
||||||
_env(env),
|
_env(env),
|
||||||
_start_depth(start_depth),
|
_start_depth(start_depth),
|
||||||
_max_count(max_count),
|
_max_count(max_count),
|
||||||
_frame_buffer(frame_buffer),
|
_frame_buffer(frame_buffer),
|
||||||
_count_ptr(count_ptr) {}
|
_count_ptr(count_ptr) {}
|
||||||
void do_thread(Thread *target);
|
void do_thread(Thread *target);
|
||||||
|
void do_vthread(Handle target_h);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
@ -684,54 +709,6 @@ public:
|
|||||||
jvmtiError result() { return _collector.result(); }
|
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.
|
// HandshakeClosure to get single stack trace.
|
||||||
class GetSingleStackTraceClosure : public HandshakeClosure {
|
class GetSingleStackTraceClosure : public HandshakeClosure {
|
||||||
private:
|
private:
|
||||||
@ -753,21 +730,22 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// HandshakeClosure to count stack frames.
|
// HandshakeClosure to count stack frames.
|
||||||
class GetFrameCountClosure : public JvmtiHandshakeClosure {
|
class GetFrameCountClosure : public JvmtiUnitedHandshakeClosure {
|
||||||
private:
|
private:
|
||||||
JvmtiEnv *_env;
|
JvmtiEnv *_env;
|
||||||
jint *_count_ptr;
|
jint *_count_ptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GetFrameCountClosure(JvmtiEnv *env, jint *count_ptr)
|
GetFrameCountClosure(JvmtiEnv *env, jint *count_ptr)
|
||||||
: JvmtiHandshakeClosure("GetFrameCount"),
|
: JvmtiUnitedHandshakeClosure("GetFrameCount"),
|
||||||
_env(env),
|
_env(env),
|
||||||
_count_ptr(count_ptr) {}
|
_count_ptr(count_ptr) {}
|
||||||
void do_thread(Thread *target);
|
void do_thread(Thread *target);
|
||||||
|
void do_vthread(Handle target_h);
|
||||||
};
|
};
|
||||||
|
|
||||||
// HandshakeClosure to get frame location.
|
// HandshakeClosure to get frame location.
|
||||||
class GetFrameLocationClosure : public JvmtiHandshakeClosure {
|
class GetFrameLocationClosure : public JvmtiUnitedHandshakeClosure {
|
||||||
private:
|
private:
|
||||||
JvmtiEnv *_env;
|
JvmtiEnv *_env;
|
||||||
jint _depth;
|
jint _depth;
|
||||||
@ -777,12 +755,13 @@ private:
|
|||||||
public:
|
public:
|
||||||
GetFrameLocationClosure(JvmtiEnv *env, jint depth,
|
GetFrameLocationClosure(JvmtiEnv *env, jint depth,
|
||||||
jmethodID* method_ptr, jlocation* location_ptr)
|
jmethodID* method_ptr, jlocation* location_ptr)
|
||||||
: JvmtiHandshakeClosure("GetFrameLocation"),
|
: JvmtiUnitedHandshakeClosure("GetFrameLocation"),
|
||||||
_env(env),
|
_env(env),
|
||||||
_depth(depth),
|
_depth(depth),
|
||||||
_method_ptr(method_ptr),
|
_method_ptr(method_ptr),
|
||||||
_location_ptr(location_ptr) {}
|
_location_ptr(location_ptr) {}
|
||||||
void do_thread(Thread *target);
|
void do_thread(Thread *target);
|
||||||
|
void do_vthread(Handle target_h);
|
||||||
};
|
};
|
||||||
|
|
||||||
// HandshakeClosure to get virtual thread monitor information with stack depth.
|
// HandshakeClosure to get virtual thread monitor information with stack depth.
|
||||||
@ -825,77 +804,6 @@ public:
|
|||||||
jvmtiError result() { return _result; }
|
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.
|
// HandshakeClosure to get virtual thread state at safepoint.
|
||||||
class VirtualThreadGetThreadStateClosure : public HandshakeClosure {
|
class VirtualThreadGetThreadStateClosure : public HandshakeClosure {
|
||||||
private:
|
private:
|
||||||
@ -914,28 +822,6 @@ public:
|
|||||||
jvmtiError result() { return _result; }
|
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
|
// ResourceTracker
|
||||||
//
|
//
|
||||||
|
@ -81,8 +81,6 @@
|
|||||||
template(GetObjectMonitorUsage) \
|
template(GetObjectMonitorUsage) \
|
||||||
template(GetAllStackTraces) \
|
template(GetAllStackTraces) \
|
||||||
template(GetThreadListStackTraces) \
|
template(GetThreadListStackTraces) \
|
||||||
template(VirtualThreadGetStackTrace) \
|
|
||||||
template(VirtualThreadGetFrameCount) \
|
|
||||||
template(ChangeBreakpoints) \
|
template(ChangeBreakpoints) \
|
||||||
template(GetOrSetLocal) \
|
template(GetOrSetLocal) \
|
||||||
template(VirtualThreadGetOrSetLocal) \
|
template(VirtualThreadGetOrSetLocal) \
|
||||||
|
Loading…
Reference in New Issue
Block a user