8292657: Calling GetLocalXXX from virtual thread with thread parameter set to NULL returns carrier locals

Reviewed-by: cjplummer, alanb
This commit is contained in:
Serguei Spitsyn 2022-08-30 18:28:05 +00:00
parent 550e5d7822
commit f5ebbf3225
6 changed files with 37 additions and 15 deletions

View File

@ -2246,7 +2246,7 @@ JvmtiEnv::GetLocalObject(jthread thread, jint depth, jint slot, jobject* value_p
JvmtiVTMSTransitionDisabler disabler;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
current_thread, depth, slot);
@ -2286,7 +2286,7 @@ JvmtiEnv::GetLocalInstance(jthread thread, jint depth, jobject* value_ptr){
JvmtiVTMSTransitionDisabler disabler;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetReceiver op(this, Handle(current_thread, thread_obj),
current_thread, depth);
@ -2327,7 +2327,7 @@ JvmtiEnv::GetLocalInt(jthread thread, jint depth, jint slot, jint* value_ptr) {
JvmtiVTMSTransitionDisabler disabler;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_INT);
@ -2368,7 +2368,7 @@ JvmtiEnv::GetLocalLong(jthread thread, jint depth, jint slot, jlong* value_ptr)
JvmtiVTMSTransitionDisabler disabler;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_LONG);
@ -2409,7 +2409,7 @@ JvmtiEnv::GetLocalFloat(jthread thread, jint depth, jint slot, jfloat* value_ptr
JvmtiVTMSTransitionDisabler disabler;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_FLOAT);
@ -2450,7 +2450,7 @@ JvmtiEnv::GetLocalDouble(jthread thread, jint depth, jint slot, jdouble* value_p
JvmtiVTMSTransitionDisabler disabler;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_DOUBLE);
@ -2492,7 +2492,7 @@ JvmtiEnv::SetLocalObject(jthread thread, jint depth, jint slot, jobject value) {
val.l = value;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_OBJECT, val);
@ -2528,7 +2528,7 @@ JvmtiEnv::SetLocalInt(jthread thread, jint depth, jint slot, jint value) {
val.i = value;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_INT, val);
@ -2564,7 +2564,7 @@ JvmtiEnv::SetLocalLong(jthread thread, jint depth, jint slot, jlong value) {
val.j = value;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_LONG, val);
@ -2600,7 +2600,7 @@ JvmtiEnv::SetLocalFloat(jthread thread, jint depth, jint slot, jfloat value) {
val.f = value;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_FLOAT, val);
@ -2636,7 +2636,7 @@ JvmtiEnv::SetLocalDouble(jthread thread, jint depth, jint slot, jdouble value) {
val.d = value;
jvmtiError err = JVMTI_ERROR_NONE;
oop thread_obj = JNIHandles::resolve_external_guard(thread);
oop thread_obj = current_thread_obj_or_resolve_external_guard(thread);
if (java_lang_VirtualThread::is_instance(thread_obj)) {
VM_VirtualThreadGetOrSetLocal op(this, Handle(current_thread, thread_obj),
depth, slot, T_DOUBLE, val);

View File

@ -1310,6 +1310,17 @@ JvmtiEnvBase::is_cthread_with_continuation(JavaThread* jt) {
return cont_entry != NULL && is_cthread_with_mounted_vthread(jt);
}
// If (thread == NULL) then return current thread object.
// Otherwise return JNIHandles::resolve_external_guard(thread).
oop
JvmtiEnvBase::current_thread_obj_or_resolve_external_guard(jthread thread) {
oop thread_obj = JNIHandles::resolve_external_guard(thread);
if (thread == NULL) {
thread_obj = get_vthread_or_thread_oop(JavaThread::current());
}
return thread_obj;
}
jvmtiError
JvmtiEnvBase::get_threadOop_and_JavaThread(ThreadsList* t_list, jthread thread,
JavaThread** jt_pp, oop* thread_oop_p) {

View File

@ -167,6 +167,10 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
return byte_offset_of(JvmtiEnvBase, _jvmti_external);
};
// If (thread == NULL) then return current thread object.
// Otherwise return JNIHandles::resolve_external_guard(thread).
static oop current_thread_obj_or_resolve_external_guard(jthread thread);
static jvmtiError get_JavaThread(ThreadsList* tlist, jthread thread, JavaThread** jt_pp) {
jvmtiError err = JVMTI_ERROR_NONE;
if (thread == NULL) {

View File

@ -136,6 +136,10 @@ static jvmtiError JNICALL GetCarrierThread(const jvmtiEnv* env, ...) {
ThreadsListHandle tlh(current_thread);
JavaThread* java_thread;
oop vthread_oop = NULL;
if (vthread == NULL) {
vthread = (jthread)JNIHandles::make_local(current_thread, JvmtiEnvBase::get_vthread_or_thread_oop(current_thread));
}
jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), vthread, &java_thread, &vthread_oop);
if (err != JVMTI_ERROR_NONE) {
// We got an error code so we don't have a JavaThread *, but

View File

@ -350,7 +350,7 @@ Breakpoint(jvmtiEnv *jvmti, JNIEnv* jni, jthread vthread,
const char* virt = jni->IsVirtualThread(vthread) ? "virtual" : "carrier";
const jint depth = 0; // the depth is always 0 in case of breakpoint
LOG("Breakpoint: %s on %s thread: %s - Started\n", mname, virt, tname);
LOG("\nBreakpoint: %s on %s thread: %s - Started\n", mname, virt, tname);
// disable BREAKPOINT events
jvmtiError err = jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_BREAKPOINT, vthread);
@ -360,7 +360,12 @@ Breakpoint(jvmtiEnv *jvmti, JNIEnv* jni, jthread vthread,
{
int frame_count = get_frame_count(jvmti, jni, vthread);
test_GetSetLocal(jvmti, jni, vthread, depth, frame_count, true /* at_event */);
// vthread passed to callback has to refer to current thread,
// so we can also test with NULL in place of vthread.
test_GetSetLocal(jvmti, jni, NULL, depth, frame_count, true /* at_event */);
}
deallocate(jvmti, jni, (void*)mname);
deallocate(jvmti, jni, (void*)tname);

View File

@ -156,9 +156,7 @@ test_GetCarrierThread(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jthread vthr
// #1: Test JVMTI GetCarrierThread extension function with NULL vthread
err = GetCarrierThread(jvmti, jni, NULL, &vthread_thread);
if (err != JVMTI_ERROR_INVALID_THREAD) {
fatal(jni, "event handler: JVMTI GetCarrierThread with NULL vthread failed to return JVMTI_ERROR_INVALID_THREAD");
}
check_jvmti_status(jni, err, "event handler: error in JVMTI GetCarrierThread");
// #2: Test JVMTI GetCarrierThread extension function with a bad vthread
err = GetCarrierThread(jvmti, jni, thread, &vthread_thread);