Skip to content

Commit

Permalink
8319244: implement JVMTI handshakes support for virtual threads
Browse files Browse the repository at this point in the history
Reviewed-by: pchilanomate, amenkov
  • Loading branch information
Serguei Spitsyn committed Nov 21, 2023
1 parent 46e4028 commit 839dd65
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 360 deletions.
138 changes: 10 additions & 128 deletions src/hotspot/share/prims/jvmtiEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 */


Expand Down Expand Up @@ -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 */


Expand Down Expand Up @@ -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 */


Expand All @@ -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 */

Expand Down

1 comment on commit 839dd65

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.