diff --git a/src/hotspot/share/prims/jvmtiThreadState.cpp b/src/hotspot/share/prims/jvmtiThreadState.cpp index 0004feb54b4..6882c02f95a 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.cpp +++ b/src/hotspot/share/prims/jvmtiThreadState.cpp @@ -52,6 +52,7 @@ static const int UNKNOWN_STACK_DEPTH = -99; // JvmtiThreadState *JvmtiThreadState::_head = nullptr; +bool JvmtiThreadState::_seen_interp_only_mode = false; JvmtiThreadState::JvmtiThreadState(JavaThread* thread, oop thread_oop) : _thread_event_enable() { @@ -553,11 +554,14 @@ JvmtiVTMSTransitionDisabler::VTMS_vthread_start(jobject vthread) { assert(!thread->is_in_VTMS_transition(), "sanity check"); assert(!thread->is_in_tmp_VTMS_transition(), "sanity check"); - JvmtiEventController::thread_started(thread); - if (JvmtiExport::can_support_virtual_threads()) { - if (JvmtiExport::should_post_vthread_start()) { - JvmtiExport::post_vthread_start(vthread); - } + // If interp_only_mode has been enabled then we must eagerly create JvmtiThreadState + // objects for globally enabled virtual thread filtered events. Otherwise, + // it is an important optimization to create JvmtiThreadState objects lazily. + if (JvmtiThreadState::seen_interp_only_mode()) { + JvmtiEventController::thread_started(thread); + } + if (JvmtiExport::should_post_vthread_start()) { + JvmtiExport::post_vthread_start(vthread); } // post VirtualThreadMount event after VirtualThreadStart if (JvmtiExport::should_post_vthread_mount()) { @@ -576,10 +580,8 @@ JvmtiVTMSTransitionDisabler::VTMS_vthread_end(jobject vthread) { if (JvmtiExport::should_post_vthread_unmount()) { JvmtiExport::post_vthread_unmount(vthread); } - if (JvmtiExport::can_support_virtual_threads()) { - if (JvmtiExport::should_post_vthread_end()) { - JvmtiExport::post_vthread_end(vthread); - } + if (JvmtiExport::should_post_vthread_end()) { + JvmtiExport::post_vthread_end(vthread); } VTMS_unmount_begin(vthread, /* last_unmount */ true); if (thread->jvmti_thread_state() != nullptr) { @@ -629,9 +631,10 @@ JvmtiVTMSTransitionDisabler::VTMS_mount_end(jobject vthread) { thread->rebind_to_jvmti_thread_state_of(vt); - { + JvmtiThreadState* state = thread->jvmti_thread_state(); + if (state != nullptr && state->is_pending_interp_only_mode()) { MutexLocker mu(JvmtiThreadState_lock); - JvmtiThreadState* state = thread->jvmti_thread_state(); + state = thread->jvmti_thread_state(); if (state != nullptr && state->is_pending_interp_only_mode()) { JvmtiEventController::enter_interp_only_mode(); } @@ -770,6 +773,7 @@ void JvmtiThreadState::add_env(JvmtiEnvBase *env) { void JvmtiThreadState::enter_interp_only_mode() { assert(_thread != nullptr, "sanity check"); + _seen_interp_only_mode = true; _thread->increment_interp_only_mode(); invalidate_cur_stack_depth(); } diff --git a/src/hotspot/share/prims/jvmtiThreadState.hpp b/src/hotspot/share/prims/jvmtiThreadState.hpp index c15e328f363..4bba0691e40 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.hpp +++ b/src/hotspot/share/prims/jvmtiThreadState.hpp @@ -240,6 +240,8 @@ class JvmtiThreadState : public CHeapObj { inline JvmtiEnvThreadState* head_env_thread_state(); inline void set_head_env_thread_state(JvmtiEnvThreadState* ets); + static bool _seen_interp_only_mode; // interp_only_mode was requested at least once + public: ~JvmtiThreadState(); @@ -259,6 +261,11 @@ class JvmtiThreadState : public CHeapObj { static void periodic_clean_up(); + // Return true if any thread has entered interp_only_mode at any point during the JVMs execution. + static bool seen_interp_only_mode() { + return _seen_interp_only_mode; + } + void add_env(JvmtiEnvBase *env); // The pending_interp_only_mode is set when the interp_only_mode is triggered.