diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 94c4336f222..c6ddc501d1a 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -1363,32 +1363,17 @@ JvmtiEnv::GetOwnedMonitorInfo(jthread thread, jint* owned_monitor_count_ptr, job return err; } - if (java_lang_VirtualThread::is_instance(thread_oop)) { - // There is no monitor info to collect if target virtual thread is unmounted. - if (java_thread != nullptr) { - VirtualThreadGetOwnedMonitorInfoClosure op(this, - Handle(calling_thread, thread_oop), - owned_monitors_list); - Handshake::execute(&op, java_thread); - err = op.result(); - } - } else { + if (java_thread != nullptr) { + Handle thread_handle(calling_thread, thread_oop); EscapeBarrier eb(true, calling_thread, java_thread); if (!eb.deoptimize_objects(MaxJavaStackTraceDepth)) { delete owned_monitors_list; return JVMTI_ERROR_OUT_OF_MEMORY; } - - if (java_thread == calling_thread) { - // It is only safe to make a direct call on the current thread. - // All other usage needs to use a direct handshake for safety. - err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); - } else { - // get owned monitors info with handshake - GetOwnedMonitorInfoClosure op(calling_thread, this, owned_monitors_list); - Handshake::execute(&op, java_thread); - err = op.result(); - } + // get owned monitors info with handshake + GetOwnedMonitorInfoClosure op(this, calling_thread, owned_monitors_list); + JvmtiHandshake::execute(&op, &tlh, java_thread, thread_handle); + err = op.result(); } jint owned_monitor_count = owned_monitors_list->length(); @@ -1436,33 +1421,19 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(jthread thread, jint* monitor_info_count return err; } - if (java_lang_VirtualThread::is_instance(thread_oop)) { - // There is no monitor info to collect if target virtual thread is unmounted. - if (java_thread != nullptr) { - VirtualThreadGetOwnedMonitorInfoClosure op(this, - Handle(calling_thread, thread_oop), - owned_monitors_list); - Handshake::execute(&op, java_thread); - err = op.result(); - } - } else { + if (java_thread != nullptr) { + Handle thread_handle(calling_thread, thread_oop); EscapeBarrier eb(true, calling_thread, java_thread); if (!eb.deoptimize_objects(MaxJavaStackTraceDepth)) { delete owned_monitors_list; return JVMTI_ERROR_OUT_OF_MEMORY; } - - if (java_thread == calling_thread) { - // It is only safe to make a direct call on the current thread. - // All other usage needs to use a direct handshake for safety. - err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); - } else { - // get owned monitors info with handshake - GetOwnedMonitorInfoClosure op(calling_thread, this, owned_monitors_list); - Handshake::execute(&op, java_thread); - err = op.result(); - } + // get owned monitors info with handshake + GetOwnedMonitorInfoClosure op(this, calling_thread, owned_monitors_list); + JvmtiHandshake::execute(&op, &tlh, java_thread, thread_handle); + err = op.result(); } + jint owned_monitor_count = owned_monitors_list->length(); if (err == JVMTI_ERROR_NONE) { if ((err = allocate(owned_monitor_count * sizeof(jvmtiMonitorStackDepthInfo), diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 05d9a26444c..44b1acf8043 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1997,11 +1997,14 @@ JvmtiHandshake::execute(JvmtiUnitedHandshakeClosure* hs_cl, jthread target) { void JvmtiHandshake::execute(JvmtiUnitedHandshakeClosure* hs_cl, ThreadsListHandle* tlh, JavaThread* target_jt, Handle target_h) { + bool is_virtual = java_lang_VirtualThread::is_instance(target_h()); bool self = target_jt == JavaThread::current(); - hs_cl->set_self(self); // needed when suspend is required for non-current target thread + hs_cl->set_target_jt(target_jt); // can be needed in the virtual thread case + hs_cl->set_is_virtual(is_virtual); // can be needed in the virtual thread case + 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 (is_virtual) { // virtual thread if (!JvmtiEnvBase::is_vthread_alive(target_h())) { return; } @@ -2466,6 +2469,23 @@ GetOwnedMonitorInfoClosure::do_thread(Thread *target) { } } +void +GetOwnedMonitorInfoClosure::do_vthread(Handle target_h) { + assert(_target_jt != nullptr, "sanity check"); + Thread* current = Thread::current(); + ResourceMark rm(current); // vframes are resource allocated + HandleMark hm(current); + + javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(target_h()); + + if (!_target_jt->is_exiting() && _target_jt->threadObj() != nullptr) { + _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, + _target_jt, + jvf, + _owned_monitors_list); + } +} + void GetCurrentContendedMonitorClosure::do_thread(Thread *target) { JavaThread *jt = JavaThread::cast(target); @@ -2582,27 +2602,6 @@ GetFrameLocationClosure::do_vthread(Handle target_h) { _method_ptr, _location_ptr); } -void -VirtualThreadGetOwnedMonitorInfoClosure::do_thread(Thread *target) { - if (!JvmtiEnvBase::is_vthread_alive(_vthread_h())) { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - return; - } - JavaThread* java_thread = JavaThread::cast(target); - Thread* cur_thread = Thread::current(); - ResourceMark rm(cur_thread); - HandleMark hm(cur_thread); - - javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(_vthread_h()); - - if (!java_thread->is_exiting() && java_thread->threadObj() != nullptr) { - _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(java_thread, - java_thread, - jvf, - _owned_monitors_list); - } -} - void VirtualThreadGetThreadClosure::do_thread(Thread *target) { assert(target->is_Java_thread(), "just checking"); diff --git a/src/hotspot/share/prims/jvmtiEnvBase.hpp b/src/hotspot/share/prims/jvmtiEnvBase.hpp index 7d3ea272434..fedd447490a 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.hpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -471,14 +471,21 @@ class JvmtiHandshakeClosure : public HandshakeClosure { class JvmtiUnitedHandshakeClosure : public HandshakeClosure { protected: jvmtiError _result; + // the fields below are set by the JvmtiHandshake::execute + JavaThread* _target_jt; + bool _is_virtual; bool _self; public: JvmtiUnitedHandshakeClosure(const char* name) : HandshakeClosure(name), _result(JVMTI_ERROR_THREAD_NOT_ALIVE), + _target_jt(nullptr), + _is_virtual(false), _self(false) {} void set_result(jvmtiError err) { _result = err; } + void set_target_jt(JavaThread* target_jt) { _target_jt = target_jt; } + void set_is_virtual(bool val) { _is_virtual = val; } void set_self(bool val) { _self = val; } jvmtiError result() { return _result; } virtual void do_vthread(Handle target_h) = 0; @@ -542,20 +549,23 @@ public: }; // HandshakeClosure to get monitor information with stack depth. -class GetOwnedMonitorInfoClosure : public JvmtiHandshakeClosure { +class GetOwnedMonitorInfoClosure : public JvmtiUnitedHandshakeClosure { private: - JavaThread* _calling_thread; JvmtiEnv *_env; + JavaThread* _calling_thread; GrowableArray *_owned_monitors_list; public: - GetOwnedMonitorInfoClosure(JavaThread* calling_thread, JvmtiEnv* env, - GrowableArray* owned_monitor_list) - : JvmtiHandshakeClosure("GetOwnedMonitorInfo"), - _calling_thread(calling_thread), + GetOwnedMonitorInfoClosure(JvmtiEnv* env, + JavaThread* calling_thread, + GrowableArray* owned_monitors_list) + : JvmtiUnitedHandshakeClosure("GetOwnedMonitorInfo"), _env(env), - _owned_monitors_list(owned_monitor_list) {} + _calling_thread(calling_thread), + _owned_monitors_list(owned_monitors_list) {} + void do_thread(Thread *target); + void do_vthread(Handle target_h); }; // VM operation to get object monitor usage. @@ -767,28 +777,6 @@ public: void do_vthread(Handle target_h); }; -// HandshakeClosure to get virtual thread monitor information with stack depth. -class VirtualThreadGetOwnedMonitorInfoClosure : public HandshakeClosure { -private: - JvmtiEnv *_env; - Handle _vthread_h; - GrowableArray *_owned_monitors_list; - jvmtiError _result; - -public: - VirtualThreadGetOwnedMonitorInfoClosure(JvmtiEnv* env, - Handle vthread_h, - GrowableArray* owned_monitors_list) - : HandshakeClosure("VirtualThreadGetOwnedMonitorInfo"), - _env(env), - _vthread_h(vthread_h), - _owned_monitors_list(owned_monitors_list), - _result(JVMTI_ERROR_THREAD_NOT_ALIVE) {} - - void do_thread(Thread *target); - jvmtiError result() { return _result; } -}; - // HandshakeClosure to get virtual thread thread at safepoint. class VirtualThreadGetThreadClosure : public HandshakeClosure { private: diff --git a/src/hotspot/share/runtime/escapeBarrier.cpp b/src/hotspot/share/runtime/escapeBarrier.cpp index bc01d900285..410609beb95 100644 --- a/src/hotspot/share/runtime/escapeBarrier.cpp +++ b/src/hotspot/share/runtime/escapeBarrier.cpp @@ -75,7 +75,8 @@ bool EscapeBarrier::deoptimize_objects(int d1, int d2) { // These frames are about to be removed. We must not interfere with that and signal failure. return false; } - if (deoptee_thread()->has_last_Java_frame()) { + if (deoptee_thread()->has_last_Java_frame() && + deoptee_thread()->last_continuation() == nullptr) { assert(calling_thread() == Thread::current(), "should be"); KeepStackGCProcessedMark ksgcpm(deoptee_thread()); ResourceMark rm(calling_thread());