8306028: separate ThreadStart/ThreadEnd events posting code in JVMTI VTMS transitions
8304444: Reappearance of NULL in jvmtiThreadState.cpp Reviewed-by: pchilanomate, lmesnik
This commit is contained in:
parent
35e75c131d
commit
1227a275a1
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
@ -217,6 +217,8 @@ JVM_DefineModule
|
|||||||
JVM_SetBootLoaderUnnamedModule
|
JVM_SetBootLoaderUnnamedModule
|
||||||
|
|
||||||
# Virtual thread notifications for JVMTI
|
# Virtual thread notifications for JVMTI
|
||||||
|
JVM_VirtualThreadStart
|
||||||
|
JVM_VirtualThreadEnd
|
||||||
JVM_VirtualThreadMount
|
JVM_VirtualThreadMount
|
||||||
JVM_VirtualThreadUnmount
|
JVM_VirtualThreadUnmount
|
||||||
JVM_VirtualThreadHideFrames
|
JVM_VirtualThreadHideFrames
|
||||||
|
@ -584,9 +584,11 @@ class methodHandle;
|
|||||||
do_alias( continuationDoYield_signature, void_int_signature) \
|
do_alias( continuationDoYield_signature, void_int_signature) \
|
||||||
\
|
\
|
||||||
/* java/lang/VirtualThread */ \
|
/* java/lang/VirtualThread */ \
|
||||||
do_intrinsic(_notifyJvmtiMount, java_lang_VirtualThread, notifyJvmtiMount_name, bool_bool_void_signature, F_RN) \
|
do_intrinsic(_notifyJvmtiVThreadStart, java_lang_VirtualThread, notifyJvmtiStart_name, void_method_signature, F_RN) \
|
||||||
do_intrinsic(_notifyJvmtiUnmount, java_lang_VirtualThread, notifyJvmtiUnmount_name, bool_bool_void_signature, F_RN) \
|
do_intrinsic(_notifyJvmtiVThreadEnd, java_lang_VirtualThread, notifyJvmtiEnd_name, void_method_signature, F_RN) \
|
||||||
do_intrinsic(_notifyJvmtiHideFrames, java_lang_VirtualThread, notifyJvmtiHideFrames_name, bool_void_signature, F_RN) \
|
do_intrinsic(_notifyJvmtiVThreadMount, java_lang_VirtualThread, notifyJvmtiMount_name, bool_void_signature, F_RN) \
|
||||||
|
do_intrinsic(_notifyJvmtiVThreadUnmount, java_lang_VirtualThread, notifyJvmtiUnmount_name, bool_void_signature, F_RN) \
|
||||||
|
do_intrinsic(_notifyJvmtiVThreadHideFrames, java_lang_VirtualThread, notifyJvmtiHideFrames_name, bool_void_signature, F_RN) \
|
||||||
\
|
\
|
||||||
/* support for UnsafeConstants */ \
|
/* support for UnsafeConstants */ \
|
||||||
do_class(jdk_internal_misc_UnsafeConstants, "jdk/internal/misc/UnsafeConstants") \
|
do_class(jdk_internal_misc_UnsafeConstants, "jdk/internal/misc/UnsafeConstants") \
|
||||||
|
@ -412,6 +412,8 @@
|
|||||||
template(run_finalization_name, "runFinalization") \
|
template(run_finalization_name, "runFinalization") \
|
||||||
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
|
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
|
||||||
template(loadClass_name, "loadClass") \
|
template(loadClass_name, "loadClass") \
|
||||||
|
template(notifyJvmtiStart_name, "notifyJvmtiStart") \
|
||||||
|
template(notifyJvmtiEnd_name, "notifyJvmtiEnd") \
|
||||||
template(notifyJvmtiMount_name, "notifyJvmtiMount") \
|
template(notifyJvmtiMount_name, "notifyJvmtiMount") \
|
||||||
template(notifyJvmtiUnmount_name, "notifyJvmtiUnmount") \
|
template(notifyJvmtiUnmount_name, "notifyJvmtiUnmount") \
|
||||||
template(notifyJvmtiHideFrames_name, "notifyJvmtiHideFrames") \
|
template(notifyJvmtiHideFrames_name, "notifyJvmtiHideFrames") \
|
||||||
|
@ -1144,10 +1144,16 @@ JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass);
|
|||||||
* Virtual thread support.
|
* Virtual thread support.
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
JVM_VirtualThreadMount(JNIEnv* env, jobject vthread, jboolean hide, jboolean first_mount);
|
JVM_VirtualThreadStart(JNIEnv* env, jobject vthread);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
JVM_VirtualThreadUnmount(JNIEnv* env, jobject vthread, jboolean hide, jboolean last_unmount);
|
JVM_VirtualThreadEnd(JNIEnv* env, jobject vthread);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_VirtualThreadMount(JNIEnv* env, jobject vthread, jboolean hide);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_VirtualThreadUnmount(JNIEnv* env, jobject vthread, jboolean hide);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
JVM_VirtualThreadHideFrames(JNIEnv* env, jobject vthread, jboolean hide);
|
JVM_VirtualThreadHideFrames(JNIEnv* env, jobject vthread, jboolean hide);
|
||||||
|
@ -775,9 +775,11 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) {
|
|||||||
return EnableVectorSupport;
|
return EnableVectorSupport;
|
||||||
case vmIntrinsics::_blackhole:
|
case vmIntrinsics::_blackhole:
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
case vmIntrinsics::_notifyJvmtiMount:
|
case vmIntrinsics::_notifyJvmtiVThreadStart:
|
||||||
case vmIntrinsics::_notifyJvmtiUnmount:
|
case vmIntrinsics::_notifyJvmtiVThreadEnd:
|
||||||
case vmIntrinsics::_notifyJvmtiHideFrames:
|
case vmIntrinsics::_notifyJvmtiVThreadMount:
|
||||||
|
case vmIntrinsics::_notifyJvmtiVThreadUnmount:
|
||||||
|
case vmIntrinsics::_notifyJvmtiVThreadHideFrames:
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -481,11 +481,15 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
|||||||
case vmIntrinsics::_setScopedValueCache: return inline_native_setScopedValueCache();
|
case vmIntrinsics::_setScopedValueCache: return inline_native_setScopedValueCache();
|
||||||
|
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
case vmIntrinsics::_notifyJvmtiMount: return inline_native_notify_jvmti_funcs(CAST_FROM_FN_PTR(address, OptoRuntime::notify_jvmti_mount()),
|
case vmIntrinsics::_notifyJvmtiVThreadStart: return inline_native_notify_jvmti_funcs(CAST_FROM_FN_PTR(address, OptoRuntime::notify_jvmti_vthread_start()),
|
||||||
"notifyJvmtiMount");
|
"notifyJvmtiStart", true, false);
|
||||||
case vmIntrinsics::_notifyJvmtiUnmount: return inline_native_notify_jvmti_funcs(CAST_FROM_FN_PTR(address, OptoRuntime::notify_jvmti_unmount()),
|
case vmIntrinsics::_notifyJvmtiVThreadEnd: return inline_native_notify_jvmti_funcs(CAST_FROM_FN_PTR(address, OptoRuntime::notify_jvmti_vthread_end()),
|
||||||
"notifyJvmtiUnmount");
|
"notifyJvmtiEnd", false, true);
|
||||||
case vmIntrinsics::_notifyJvmtiHideFrames: return inline_native_notify_jvmti_hide();
|
case vmIntrinsics::_notifyJvmtiVThreadMount: return inline_native_notify_jvmti_funcs(CAST_FROM_FN_PTR(address, OptoRuntime::notify_jvmti_vthread_mount()),
|
||||||
|
"notifyJvmtiMount", false, false);
|
||||||
|
case vmIntrinsics::_notifyJvmtiVThreadUnmount: return inline_native_notify_jvmti_funcs(CAST_FROM_FN_PTR(address, OptoRuntime::notify_jvmti_vthread_unmount()),
|
||||||
|
"notifyJvmtiUnmount", false, false);
|
||||||
|
case vmIntrinsics::_notifyJvmtiVThreadHideFrames: return inline_native_notify_jvmti_hide();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef JFR_HAVE_INTRINSICS
|
#ifdef JFR_HAVE_INTRINSICS
|
||||||
@ -2873,25 +2877,24 @@ bool LibraryCallKit::inline_native_time_funcs(address funcAddr, const char* func
|
|||||||
|
|
||||||
// When notifications are disabled then just update the VTMS transition bit and return.
|
// When notifications are disabled then just update the VTMS transition bit and return.
|
||||||
// Otherwise, the bit is updated in the given function call implementing JVMTI notification protocol.
|
// Otherwise, the bit is updated in the given function call implementing JVMTI notification protocol.
|
||||||
bool LibraryCallKit::inline_native_notify_jvmti_funcs(address funcAddr, const char* funcName) {
|
bool LibraryCallKit::inline_native_notify_jvmti_funcs(address funcAddr, const char* funcName, bool is_start, bool is_end) {
|
||||||
if (!DoJVMTIVirtualThreadTransitions) {
|
if (!DoJVMTIVirtualThreadTransitions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
IdealKit ideal(this);
|
IdealKit ideal(this);
|
||||||
|
|
||||||
Node* ONE = ideal.ConI(1);
|
Node* ONE = ideal.ConI(1);
|
||||||
Node* hide = _gvn.transform(argument(1)); // hide argument: true for begin and false for end of VTMS transition
|
Node* hide = is_start ? ideal.ConI(0) : (is_end ? ideal.ConI(1) : _gvn.transform(argument(1)));
|
||||||
Node* addr = makecon(TypeRawPtr::make((address)&JvmtiVTMSTransitionDisabler::_VTMS_notify_jvmti_events));
|
Node* addr = makecon(TypeRawPtr::make((address)&JvmtiVTMSTransitionDisabler::_VTMS_notify_jvmti_events));
|
||||||
Node* notify_jvmti_enabled = ideal.load(ideal.ctrl(), addr, TypeInt::BOOL, T_BOOLEAN, Compile::AliasIdxRaw);
|
Node* notify_jvmti_enabled = ideal.load(ideal.ctrl(), addr, TypeInt::BOOL, T_BOOLEAN, Compile::AliasIdxRaw);
|
||||||
|
|
||||||
ideal.if_then(notify_jvmti_enabled, BoolTest::eq, ONE); {
|
ideal.if_then(notify_jvmti_enabled, BoolTest::eq, ONE); {
|
||||||
// if notifyJvmti enabled then make a call to the given SharedRuntime function
|
// if notifyJvmti enabled then make a call to the given SharedRuntime function
|
||||||
const TypeFunc* tf = OptoRuntime::notify_jvmti_Type();
|
const TypeFunc* tf = OptoRuntime::notify_jvmti_vthread_Type();
|
||||||
Node* vt_oop = _gvn.transform(must_be_not_null(argument(0), true)); // VirtualThread this argument
|
Node* vt_oop = _gvn.transform(must_be_not_null(argument(0), true)); // VirtualThread this argument
|
||||||
Node* cond = _gvn.transform(argument(2)); // firstMount or lastUnmount argument
|
|
||||||
|
|
||||||
sync_kit(ideal);
|
sync_kit(ideal);
|
||||||
make_runtime_call(RC_NO_LEAF, tf, funcAddr, funcName, TypePtr::BOTTOM, vt_oop, hide, cond);
|
make_runtime_call(RC_NO_LEAF, tf, funcAddr, funcName, TypePtr::BOTTOM, vt_oop, hide);
|
||||||
ideal.sync_kit(this);
|
ideal.sync_kit(this);
|
||||||
} ideal.else_(); {
|
} ideal.else_(); {
|
||||||
// set hide value to the VTMS transition bit in current JavaThread and VirtualThread object
|
// set hide value to the VTMS transition bit in current JavaThread and VirtualThread object
|
||||||
|
@ -246,7 +246,7 @@ class LibraryCallKit : public GraphKit {
|
|||||||
|
|
||||||
bool inline_native_time_funcs(address method, const char* funcName);
|
bool inline_native_time_funcs(address method, const char* funcName);
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
bool inline_native_notify_jvmti_funcs(address funcAddr, const char* funcName);
|
bool inline_native_notify_jvmti_funcs(address funcAddr, const char* funcName, bool is_start, bool is_end);
|
||||||
bool inline_native_notify_jvmti_hide();
|
bool inline_native_notify_jvmti_hide();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -111,8 +111,10 @@ address OptoRuntime::_slow_arraycopy_Java = nullptr;
|
|||||||
address OptoRuntime::_register_finalizer_Java = nullptr;
|
address OptoRuntime::_register_finalizer_Java = nullptr;
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
address OptoRuntime::_notify_jvmti_object_alloc = nullptr;
|
address OptoRuntime::_notify_jvmti_object_alloc = nullptr;
|
||||||
address OptoRuntime::_notify_jvmti_mount = nullptr;
|
address OptoRuntime::_notify_jvmti_vthread_start = nullptr;
|
||||||
address OptoRuntime::_notify_jvmti_unmount = nullptr;
|
address OptoRuntime::_notify_jvmti_vthread_end = nullptr;
|
||||||
|
address OptoRuntime::_notify_jvmti_vthread_mount = nullptr;
|
||||||
|
address OptoRuntime::_notify_jvmti_vthread_unmount = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ExceptionBlob* OptoRuntime::_exception_blob;
|
ExceptionBlob* OptoRuntime::_exception_blob;
|
||||||
@ -155,8 +157,10 @@ bool OptoRuntime::generate(ciEnv* env) {
|
|||||||
gen(env, _multianewarrayN_Java , multianewarrayN_Type , multianewarrayN_C , 0 , true, false);
|
gen(env, _multianewarrayN_Java , multianewarrayN_Type , multianewarrayN_C , 0 , true, false);
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
gen(env, _notify_jvmti_object_alloc , notify_jvmti_object_alloc_Type, SharedRuntime::notify_jvmti_object_alloc, 0, true, false);
|
gen(env, _notify_jvmti_object_alloc , notify_jvmti_object_alloc_Type, SharedRuntime::notify_jvmti_object_alloc, 0, true, false);
|
||||||
gen(env, _notify_jvmti_mount , notify_jvmti_Type , SharedRuntime::notify_jvmti_mount, 0 , true, false);
|
gen(env, _notify_jvmti_vthread_start , notify_jvmti_vthread_Type , SharedRuntime::notify_jvmti_vthread_start, 0, true, false);
|
||||||
gen(env, _notify_jvmti_unmount , notify_jvmti_Type , SharedRuntime::notify_jvmti_unmount, 0 , true, false);
|
gen(env, _notify_jvmti_vthread_end , notify_jvmti_vthread_Type , SharedRuntime::notify_jvmti_vthread_end, 0, true, false);
|
||||||
|
gen(env, _notify_jvmti_vthread_mount , notify_jvmti_vthread_Type , SharedRuntime::notify_jvmti_vthread_mount, 0, true, false);
|
||||||
|
gen(env, _notify_jvmti_vthread_unmount , notify_jvmti_vthread_Type , SharedRuntime::notify_jvmti_vthread_unmount, 0, true, false);
|
||||||
#endif
|
#endif
|
||||||
gen(env, _complete_monitor_locking_Java , complete_monitor_enter_Type , SharedRuntime::complete_monitor_locking_C, 0, false, false);
|
gen(env, _complete_monitor_locking_Java , complete_monitor_enter_Type , SharedRuntime::complete_monitor_locking_C, 0, false, false);
|
||||||
gen(env, _monitor_notify_Java , monitor_notify_Type , monitor_notify_C , 0 , false, false);
|
gen(env, _monitor_notify_Java , monitor_notify_Type , monitor_notify_C , 0 , false, false);
|
||||||
@ -491,6 +495,21 @@ const TypeFunc *OptoRuntime::notify_jvmti_object_alloc_Type() {
|
|||||||
|
|
||||||
return TypeFunc::make(domain, range);
|
return TypeFunc::make(domain, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TypeFunc *OptoRuntime::notify_jvmti_vthread_Type() {
|
||||||
|
// create input type (domain)
|
||||||
|
const Type **fields = TypeTuple::fields(2);
|
||||||
|
fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // VirtualThread oop
|
||||||
|
fields[TypeFunc::Parms+1] = TypeInt::BOOL; // jboolean
|
||||||
|
const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
|
||||||
|
|
||||||
|
// no result type needed
|
||||||
|
fields = TypeTuple::fields(1);
|
||||||
|
fields[TypeFunc::Parms+0] = NULL; // void
|
||||||
|
const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
|
||||||
|
|
||||||
|
return TypeFunc::make(domain,range);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const TypeFunc *OptoRuntime::athrow_Type() {
|
const TypeFunc *OptoRuntime::athrow_Type() {
|
||||||
@ -1670,24 +1689,6 @@ const TypeFunc *OptoRuntime::class_id_load_barrier_Type() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if INCLUDE_JVMTI
|
|
||||||
const TypeFunc *OptoRuntime::notify_jvmti_Type() {
|
|
||||||
// create input type (domain)
|
|
||||||
const Type **fields = TypeTuple::fields(3);
|
|
||||||
fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // VirtualThread oop
|
|
||||||
fields[TypeFunc::Parms+1] = TypeInt::BOOL; // jboolean
|
|
||||||
fields[TypeFunc::Parms+2] = TypeInt::BOOL; // jboolean
|
|
||||||
const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+3,fields);
|
|
||||||
|
|
||||||
// no result type needed
|
|
||||||
fields = TypeTuple::fields(1);
|
|
||||||
fields[TypeFunc::Parms+0] = NULL; // void
|
|
||||||
const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
|
|
||||||
|
|
||||||
return TypeFunc::make(domain,range);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Dtrace support. entry and exit probes have the same signature
|
// Dtrace support. entry and exit probes have the same signature
|
||||||
const TypeFunc *OptoRuntime::dtrace_method_entry_exit_Type() {
|
const TypeFunc *OptoRuntime::dtrace_method_entry_exit_Type() {
|
||||||
|
@ -137,8 +137,10 @@ class OptoRuntime : public AllStatic {
|
|||||||
static address _register_finalizer_Java;
|
static address _register_finalizer_Java;
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
static address _notify_jvmti_object_alloc;
|
static address _notify_jvmti_object_alloc;
|
||||||
static address _notify_jvmti_mount;
|
static address _notify_jvmti_vthread_start;
|
||||||
static address _notify_jvmti_unmount;
|
static address _notify_jvmti_vthread_end;
|
||||||
|
static address _notify_jvmti_vthread_mount;
|
||||||
|
static address _notify_jvmti_vthread_unmount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -215,8 +217,10 @@ private:
|
|||||||
static address register_finalizer_Java() { return _register_finalizer_Java; }
|
static address register_finalizer_Java() { return _register_finalizer_Java; }
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
static address notify_jvmti_object_alloc() { return _notify_jvmti_object_alloc; }
|
static address notify_jvmti_object_alloc() { return _notify_jvmti_object_alloc; }
|
||||||
static address notify_jvmti_mount() { return _notify_jvmti_mount; }
|
static address notify_jvmti_vthread_start() { return _notify_jvmti_vthread_start; }
|
||||||
static address notify_jvmti_unmount() { return _notify_jvmti_unmount; }
|
static address notify_jvmti_vthread_end() { return _notify_jvmti_vthread_end; }
|
||||||
|
static address notify_jvmti_vthread_mount() { return _notify_jvmti_vthread_mount; }
|
||||||
|
static address notify_jvmti_vthread_unmount() { return _notify_jvmti_vthread_unmount; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ExceptionBlob* exception_blob() { return _exception_blob; }
|
static ExceptionBlob* exception_blob() { return _exception_blob; }
|
||||||
@ -306,7 +310,7 @@ private:
|
|||||||
JFR_ONLY(static const TypeFunc* class_id_load_barrier_Type();)
|
JFR_ONLY(static const TypeFunc* class_id_load_barrier_Type();)
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
static const TypeFunc* notify_jvmti_object_alloc_Type();
|
static const TypeFunc* notify_jvmti_object_alloc_Type();
|
||||||
static const TypeFunc* notify_jvmti_Type();
|
static const TypeFunc* notify_jvmti_vthread_Type();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Dtrace support
|
// Dtrace support
|
||||||
|
@ -3910,24 +3910,53 @@ JVM_LEAF(jint, JVM_FindSignal(const char *name))
|
|||||||
return os::get_signal_number(name);
|
return os::get_signal_number(name);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
// If notifications are disabled then just update the VTMS transition bit and return.
|
JVM_ENTRY(void, JVM_VirtualThreadStart(JNIEnv* env, jobject vthread))
|
||||||
// Otherwise, the bit is updated in the given jvmtiVTMSTransitionDisabler function call.
|
|
||||||
JVM_ENTRY(void, JVM_VirtualThreadMount(JNIEnv* env, jobject vthread, jboolean hide, jboolean first_mount))
|
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
if (!DoJVMTIVirtualThreadTransitions) {
|
if (!DoJVMTIVirtualThreadTransitions) {
|
||||||
assert(!JvmtiExport::can_support_virtual_threads(), "sanity check");
|
assert(!JvmtiExport::can_support_virtual_threads(), "sanity check");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
|
if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
|
||||||
thread->set_is_in_VTMS_transition(hide);
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_start(vthread);
|
||||||
oop vt = JNIHandles::resolve_external_guard(vthread);
|
} else {
|
||||||
java_lang_Thread::set_is_in_VTMS_transition(vt, hide);
|
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
|
||||||
|
JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(thread, vthread, false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
fatal("Should only be called with JVMTI enabled");
|
||||||
|
#endif
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY(void, JVM_VirtualThreadEnd(JNIEnv* env, jobject vthread))
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
|
if (!DoJVMTIVirtualThreadTransitions) {
|
||||||
|
assert(!JvmtiExport::can_support_virtual_threads(), "sanity check");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hide) {
|
if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_mount_begin(vthread, first_mount);
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_end(vthread);
|
||||||
} else {
|
} else {
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_mount_end(vthread, first_mount);
|
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
|
||||||
|
JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(thread, vthread, true);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
fatal("Should only be called with JVMTI enabled");
|
||||||
|
#endif
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
// If notifications are disabled then just update the VTMS transition bit and return.
|
||||||
|
// Otherwise, the bit is updated in the given jvmtiVTMSTransitionDisabler function call.
|
||||||
|
JVM_ENTRY(void, JVM_VirtualThreadMount(JNIEnv* env, jobject vthread, jboolean hide))
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
|
if (!DoJVMTIVirtualThreadTransitions) {
|
||||||
|
assert(!JvmtiExport::can_support_virtual_threads(), "sanity check");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
|
||||||
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_mount(vthread, hide);
|
||||||
|
} else {
|
||||||
|
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
|
||||||
|
JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(thread, vthread, hide);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
fatal("Should only be called with JVMTI enabled");
|
fatal("Should only be called with JVMTI enabled");
|
||||||
@ -3936,22 +3965,17 @@ JVM_END
|
|||||||
|
|
||||||
// If notifications are disabled then just update the VTMS transition bit and return.
|
// If notifications are disabled then just update the VTMS transition bit and return.
|
||||||
// Otherwise, the bit is updated in the given jvmtiVTMSTransitionDisabler function call below.
|
// Otherwise, the bit is updated in the given jvmtiVTMSTransitionDisabler function call below.
|
||||||
JVM_ENTRY(void, JVM_VirtualThreadUnmount(JNIEnv* env, jobject vthread, jboolean hide, jboolean last_unmount))
|
JVM_ENTRY(void, JVM_VirtualThreadUnmount(JNIEnv* env, jobject vthread, jboolean hide))
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
if (!DoJVMTIVirtualThreadTransitions) {
|
if (!DoJVMTIVirtualThreadTransitions) {
|
||||||
assert(!JvmtiExport::can_support_virtual_threads(), "sanity check");
|
assert(!JvmtiExport::can_support_virtual_threads(), "sanity check");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
|
if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
|
||||||
thread->set_is_in_VTMS_transition(hide);
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_unmount(vthread, hide);
|
||||||
oop vt = JNIHandles::resolve_external_guard(vthread);
|
|
||||||
java_lang_Thread::set_is_in_VTMS_transition(vt, hide);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (hide) {
|
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_unmount_begin(vthread, last_unmount);
|
|
||||||
} else {
|
} else {
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_unmount_end(vthread, last_unmount);
|
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
|
||||||
|
JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(thread, vthread, hide);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
fatal("Should only be called with JVMTI enabled");
|
fatal("Should only be called with JVMTI enabled");
|
||||||
|
@ -292,7 +292,7 @@ JvmtiVTMSTransitionDisabler::~JvmtiVTMSTransitionDisabler() {
|
|||||||
// disable VTMS transitions for one virtual thread
|
// disable VTMS transitions for one virtual thread
|
||||||
void
|
void
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_transition_disable_for_one() {
|
JvmtiVTMSTransitionDisabler::VTMS_transition_disable_for_one() {
|
||||||
assert(_thread != NULL, "sanity check");
|
assert(_thread != nullptr, "sanity check");
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
HandleMark hm(thread);
|
HandleMark hm(thread);
|
||||||
Handle vth = Handle(thread, JNIHandles::resolve_external_guard(_thread));
|
Handle vth = Handle(thread, JNIHandles::resolve_external_guard(_thread));
|
||||||
@ -511,8 +511,95 @@ JvmtiVTMSTransitionDisabler::finish_VTMS_transition(jthread vthread, bool is_mou
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
|
||||||
|
void JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(JavaThread* thread, jobject vthread, bool in_trans) {
|
||||||
|
oop vt = JNIHandles::resolve_external_guard(vthread);
|
||||||
|
java_lang_Thread::set_is_in_VTMS_transition(vt, in_trans);
|
||||||
|
thread->set_is_in_VTMS_transition(in_trans);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_mount_begin(jobject vthread, jboolean first_mount) {
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_start(jobject vthread) {
|
||||||
|
VTMS_mount_end(vthread);
|
||||||
|
JavaThread* thread = JavaThread::current();
|
||||||
|
|
||||||
|
assert(!thread->is_in_VTMS_transition(), "sanity check");
|
||||||
|
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
||||||
|
|
||||||
|
if (JvmtiExport::can_support_virtual_threads()) {
|
||||||
|
JvmtiEventController::thread_started(thread);
|
||||||
|
if (JvmtiExport::should_post_vthread_start()) {
|
||||||
|
JvmtiExport::post_vthread_start(vthread);
|
||||||
|
}
|
||||||
|
} else { // compatibility for vthread unaware agents: legacy thread_start
|
||||||
|
if (PostVirtualThreadCompatibleLifecycleEvents &&
|
||||||
|
JvmtiExport::should_post_thread_life()) {
|
||||||
|
// JvmtiEventController::thread_started is called here
|
||||||
|
JvmtiExport::post_thread_start(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// post VirtualThreadMount event after VirtualThreadStart
|
||||||
|
if (JvmtiExport::should_post_vthread_mount()) {
|
||||||
|
JvmtiExport::post_vthread_mount(vthread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_end(jobject vthread) {
|
||||||
|
JavaThread* thread = JavaThread::current();
|
||||||
|
|
||||||
|
assert(!thread->is_in_VTMS_transition(), "sanity check");
|
||||||
|
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
||||||
|
|
||||||
|
// post VirtualThreadUnmount event before VirtualThreadEnd
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
} else { // compatibility for vthread unaware agents: legacy thread_end
|
||||||
|
if (PostVirtualThreadCompatibleLifecycleEvents &&
|
||||||
|
JvmtiExport::should_post_thread_life()) {
|
||||||
|
JvmtiExport::post_thread_end(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (thread->jvmti_thread_state() != nullptr) {
|
||||||
|
JvmtiExport::cleanup_thread(thread);
|
||||||
|
thread->set_jvmti_thread_state(nullptr);
|
||||||
|
oop vt = JNIHandles::resolve(vthread);
|
||||||
|
java_lang_Thread::set_jvmti_thread_state(vt, nullptr);
|
||||||
|
}
|
||||||
|
VTMS_unmount_begin(vthread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_mount(jobject vthread, bool hide) {
|
||||||
|
if (hide) {
|
||||||
|
VTMS_mount_begin(vthread);
|
||||||
|
} else {
|
||||||
|
VTMS_mount_end(vthread);
|
||||||
|
if (JvmtiExport::should_post_vthread_mount()) {
|
||||||
|
JvmtiExport::post_vthread_mount(vthread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_unmount(jobject vthread, bool hide) {
|
||||||
|
if (hide) {
|
||||||
|
if (JvmtiExport::should_post_vthread_unmount()) {
|
||||||
|
JvmtiExport::post_vthread_unmount(vthread);
|
||||||
|
}
|
||||||
|
VTMS_unmount_begin(vthread);
|
||||||
|
} else {
|
||||||
|
VTMS_unmount_end(vthread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JvmtiVTMSTransitionDisabler::VTMS_mount_begin(jobject vthread) {
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
||||||
assert(!thread->is_in_VTMS_transition(), "sanity check");
|
assert(!thread->is_in_VTMS_transition(), "sanity check");
|
||||||
@ -520,7 +607,7 @@ JvmtiVTMSTransitionDisabler::VTMS_mount_begin(jobject vthread, jboolean first_mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_mount_end(jobject vthread, jboolean first_mount) {
|
JvmtiVTMSTransitionDisabler::VTMS_mount_end(jobject vthread) {
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
oop vt = JNIHandles::resolve(vthread);
|
oop vt = JNIHandles::resolve(vthread);
|
||||||
|
|
||||||
@ -536,62 +623,21 @@ JvmtiVTMSTransitionDisabler::VTMS_mount_end(jobject vthread, jboolean first_moun
|
|||||||
assert(thread->is_in_VTMS_transition(), "sanity check");
|
assert(thread->is_in_VTMS_transition(), "sanity check");
|
||||||
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
||||||
finish_VTMS_transition(vthread, /* is_mount */ true);
|
finish_VTMS_transition(vthread, /* is_mount */ true);
|
||||||
if (first_mount) {
|
|
||||||
// thread start
|
|
||||||
if (JvmtiExport::can_support_virtual_threads()) {
|
|
||||||
JvmtiEventController::thread_started(thread);
|
|
||||||
if (JvmtiExport::should_post_vthread_start()) {
|
|
||||||
JvmtiExport::post_vthread_start(vthread);
|
|
||||||
}
|
|
||||||
} else { // compatibility for vthread unaware agents: legacy thread_start
|
|
||||||
if (PostVirtualThreadCompatibleLifecycleEvents &&
|
|
||||||
JvmtiExport::should_post_thread_life()) {
|
|
||||||
// JvmtiEventController::thread_started is called here
|
|
||||||
JvmtiExport::post_thread_start(thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (JvmtiExport::should_post_vthread_mount()) {
|
|
||||||
JvmtiExport::post_vthread_mount(vthread);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_unmount_begin(jobject vthread, jboolean last_unmount) {
|
JvmtiVTMSTransitionDisabler::VTMS_unmount_begin(jobject vthread) {
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
HandleMark hm(thread);
|
|
||||||
Handle ct(thread, thread->threadObj());
|
|
||||||
|
|
||||||
if (JvmtiExport::should_post_vthread_unmount()) {
|
|
||||||
JvmtiExport::post_vthread_unmount(vthread);
|
|
||||||
}
|
|
||||||
if (last_unmount) {
|
|
||||||
if (JvmtiExport::can_support_virtual_threads()) {
|
|
||||||
if (JvmtiExport::should_post_vthread_end()) {
|
|
||||||
JvmtiExport::post_vthread_end(vthread);
|
|
||||||
}
|
|
||||||
} else { // compatibility for vthread unaware agents: legacy thread_end
|
|
||||||
if (PostVirtualThreadCompatibleLifecycleEvents &&
|
|
||||||
JvmtiExport::should_post_thread_life()) {
|
|
||||||
JvmtiExport::post_thread_end(thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
||||||
assert(!thread->is_in_VTMS_transition(), "sanity check");
|
assert(!thread->is_in_VTMS_transition(), "sanity check");
|
||||||
start_VTMS_transition(vthread, /* is_mount */ false);
|
|
||||||
|
|
||||||
if (last_unmount && thread->jvmti_thread_state() != nullptr) {
|
start_VTMS_transition(vthread, /* is_mount */ false);
|
||||||
JvmtiExport::cleanup_thread(thread);
|
thread->rebind_to_jvmti_thread_state_of(thread->threadObj());
|
||||||
thread->set_jvmti_thread_state(nullptr);
|
|
||||||
oop vt = JNIHandles::resolve(vthread);
|
|
||||||
java_lang_Thread::set_jvmti_thread_state(vt, nullptr);
|
|
||||||
}
|
|
||||||
thread->rebind_to_jvmti_thread_state_of(ct());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_unmount_end(jobject vthread, jboolean last_unmount) {
|
JvmtiVTMSTransitionDisabler::VTMS_unmount_end(jobject vthread) {
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
assert(thread->is_in_VTMS_transition(), "sanity check");
|
assert(thread->is_in_VTMS_transition(), "sanity check");
|
||||||
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
assert(!thread->is_in_tmp_VTMS_transition(), "sanity check");
|
||||||
|
@ -105,13 +105,23 @@ class JvmtiVTMSTransitionDisabler {
|
|||||||
JvmtiVTMSTransitionDisabler(jthread thread);
|
JvmtiVTMSTransitionDisabler(jthread thread);
|
||||||
~JvmtiVTMSTransitionDisabler();
|
~JvmtiVTMSTransitionDisabler();
|
||||||
|
|
||||||
|
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
|
||||||
|
static void set_is_in_VTMS_transition(JavaThread* thread, jobject vthread, bool in_trans);
|
||||||
|
|
||||||
static void start_VTMS_transition(jthread vthread, bool is_mount);
|
static void start_VTMS_transition(jthread vthread, bool is_mount);
|
||||||
static void finish_VTMS_transition(jthread vthread, bool is_mount);
|
static void finish_VTMS_transition(jthread vthread, bool is_mount);
|
||||||
|
|
||||||
static void VTMS_mount_begin(jobject vthread, jboolean first_mount);
|
static void VTMS_vthread_start(jobject vthread);
|
||||||
static void VTMS_mount_end(jobject vthread, jboolean first_mount);
|
static void VTMS_vthread_end(jobject vthread);
|
||||||
static void VTMS_unmount_begin(jobject vthread, jboolean last_unmount);
|
|
||||||
static void VTMS_unmount_end(jobject vthread, jboolean last_unmount);
|
static void VTMS_vthread_mount(jobject vthread, bool hide);
|
||||||
|
static void VTMS_vthread_unmount(jobject vthread, bool hide);
|
||||||
|
|
||||||
|
static void VTMS_mount_begin(jobject vthread);
|
||||||
|
static void VTMS_mount_end(jobject vthread);
|
||||||
|
|
||||||
|
static void VTMS_unmount_begin(jobject vthread);
|
||||||
|
static void VTMS_unmount_end(jobject vthread);
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
|
@ -636,27 +636,29 @@ JRT_ENTRY(void, SharedRuntime::notify_jvmti_object_alloc(oopDesc* o, JavaThread*
|
|||||||
current->set_vm_result(h());
|
current->set_vm_result(h());
|
||||||
JRT_END
|
JRT_END
|
||||||
|
|
||||||
JRT_ENTRY(void, SharedRuntime::notify_jvmti_mount(oopDesc* vt, jboolean hide, jboolean first_mount, JavaThread* current))
|
JRT_ENTRY(void, SharedRuntime::notify_jvmti_vthread_start(oopDesc* vt, jboolean hide, JavaThread* current))
|
||||||
|
assert(hide == JNI_FALSE, "must be VTMS transition finish");
|
||||||
jobject vthread = JNIHandles::make_local(const_cast<oopDesc*>(vt));
|
jobject vthread = JNIHandles::make_local(const_cast<oopDesc*>(vt));
|
||||||
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_start(vthread);
|
||||||
if (hide) {
|
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_mount_begin(vthread, first_mount);
|
|
||||||
} else {
|
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_mount_end(vthread, first_mount);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIHandles::destroy_local(vthread);
|
JNIHandles::destroy_local(vthread);
|
||||||
JRT_END
|
JRT_END
|
||||||
|
|
||||||
JRT_ENTRY(void, SharedRuntime::notify_jvmti_unmount(oopDesc* vt, jboolean hide, jboolean last_unmount, JavaThread* current))
|
JRT_ENTRY(void, SharedRuntime::notify_jvmti_vthread_end(oopDesc* vt, jboolean hide, JavaThread* current))
|
||||||
|
assert(hide == JNI_TRUE, "must be VTMS transition start");
|
||||||
jobject vthread = JNIHandles::make_local(const_cast<oopDesc*>(vt));
|
jobject vthread = JNIHandles::make_local(const_cast<oopDesc*>(vt));
|
||||||
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_end(vthread);
|
||||||
|
JNIHandles::destroy_local(vthread);
|
||||||
|
JRT_END
|
||||||
|
|
||||||
if (hide) {
|
JRT_ENTRY(void, SharedRuntime::notify_jvmti_vthread_mount(oopDesc* vt, jboolean hide, JavaThread* current))
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_unmount_begin(vthread, last_unmount);
|
jobject vthread = JNIHandles::make_local(const_cast<oopDesc*>(vt));
|
||||||
} else {
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_mount(vthread, hide);
|
||||||
JvmtiVTMSTransitionDisabler::VTMS_unmount_end(vthread, last_unmount);
|
JNIHandles::destroy_local(vthread);
|
||||||
}
|
JRT_END
|
||||||
|
|
||||||
|
JRT_ENTRY(void, SharedRuntime::notify_jvmti_vthread_unmount(oopDesc* vt, jboolean hide, JavaThread* current))
|
||||||
|
jobject vthread = JNIHandles::make_local(const_cast<oopDesc*>(vt));
|
||||||
|
JvmtiVTMSTransitionDisabler::VTMS_vthread_unmount(vthread, hide);
|
||||||
JNIHandles::destroy_local(vthread);
|
JNIHandles::destroy_local(vthread);
|
||||||
JRT_END
|
JRT_END
|
||||||
#endif // INCLUDE_JVMTI
|
#endif // INCLUDE_JVMTI
|
||||||
|
@ -267,8 +267,10 @@ class SharedRuntime: AllStatic {
|
|||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
static void notify_jvmti_object_alloc(oopDesc* o, JavaThread* current);
|
static void notify_jvmti_object_alloc(oopDesc* o, JavaThread* current);
|
||||||
// Functions for JVMTI notifications
|
// Functions for JVMTI notifications
|
||||||
static void notify_jvmti_mount(oopDesc* vt, jboolean hide, jboolean first_mount, JavaThread* current);
|
static void notify_jvmti_vthread_start(oopDesc* vt, jboolean hide, JavaThread* current);
|
||||||
static void notify_jvmti_unmount(oopDesc* vt, jboolean hide, jboolean last_unmount, JavaThread* current);
|
static void notify_jvmti_vthread_end(oopDesc* vt, jboolean hide, JavaThread* current);
|
||||||
|
static void notify_jvmti_vthread_mount(oopDesc* vt, jboolean hide, JavaThread* current);
|
||||||
|
static void notify_jvmti_vthread_unmount(oopDesc* vt, jboolean hide, JavaThread* current);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// RedefineClasses() tracing support for obsolete method entry
|
// RedefineClasses() tracing support for obsolete method entry
|
||||||
|
@ -205,22 +205,19 @@ final class VirtualThread extends BaseVirtualThread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set state to RUNNING
|
// set state to RUNNING
|
||||||
boolean firstRun;
|
|
||||||
int initialState = state();
|
int initialState = state();
|
||||||
if (initialState == STARTED && compareAndSetState(STARTED, RUNNING)) {
|
if (initialState == STARTED && compareAndSetState(STARTED, RUNNING)) {
|
||||||
// first run
|
// first run
|
||||||
firstRun = true;
|
|
||||||
} else if (initialState == RUNNABLE && compareAndSetState(RUNNABLE, RUNNING)) {
|
} else if (initialState == RUNNABLE && compareAndSetState(RUNNABLE, RUNNING)) {
|
||||||
// consume parking permit
|
// consume parking permit
|
||||||
setParkPermit(false);
|
setParkPermit(false);
|
||||||
firstRun = false;
|
|
||||||
} else {
|
} else {
|
||||||
// not runnable
|
// not runnable
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify JVMTI before mount
|
// notify JVMTI before mount
|
||||||
notifyJvmtiMount(/*hide*/true, firstRun);
|
notifyJvmtiMount(/*hide*/true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cont.run();
|
cont.run();
|
||||||
@ -300,7 +297,7 @@ final class VirtualThread extends BaseVirtualThread {
|
|||||||
|
|
||||||
// first mount
|
// first mount
|
||||||
mount();
|
mount();
|
||||||
notifyJvmtiMount(/*hide*/false, /*first*/true);
|
notifyJvmtiStart();
|
||||||
|
|
||||||
// emit JFR event if enabled
|
// emit JFR event if enabled
|
||||||
if (VirtualThreadStartEvent.isTurnedOn()) {
|
if (VirtualThreadStartEvent.isTurnedOn()) {
|
||||||
@ -328,7 +325,7 @@ final class VirtualThread extends BaseVirtualThread {
|
|||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
// last unmount
|
// last unmount
|
||||||
notifyJvmtiUnmount(/*hide*/true, /*last*/true);
|
notifyJvmtiEnd();
|
||||||
unmount();
|
unmount();
|
||||||
|
|
||||||
// final state
|
// final state
|
||||||
@ -438,14 +435,14 @@ final class VirtualThread extends BaseVirtualThread {
|
|||||||
@ChangesCurrentThread
|
@ChangesCurrentThread
|
||||||
private boolean yieldContinuation() {
|
private boolean yieldContinuation() {
|
||||||
// unmount
|
// unmount
|
||||||
notifyJvmtiUnmount(/*hide*/true, /*last*/false);
|
notifyJvmtiUnmount(/*hide*/true);
|
||||||
unmount();
|
unmount();
|
||||||
try {
|
try {
|
||||||
return Continuation.yield(VTHREAD_SCOPE);
|
return Continuation.yield(VTHREAD_SCOPE);
|
||||||
} finally {
|
} finally {
|
||||||
// re-mount
|
// re-mount
|
||||||
mount();
|
mount();
|
||||||
notifyJvmtiMount(/*hide*/false, /*first*/false);
|
notifyJvmtiMount(/*hide*/false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +459,7 @@ final class VirtualThread extends BaseVirtualThread {
|
|||||||
setState(PARKED);
|
setState(PARKED);
|
||||||
|
|
||||||
// notify JVMTI that unmount has completed, thread is parked
|
// notify JVMTI that unmount has completed, thread is parked
|
||||||
notifyJvmtiUnmount(/*hide*/false, /*last*/false);
|
notifyJvmtiUnmount(/*hide*/false);
|
||||||
|
|
||||||
// may have been unparked while parking
|
// may have been unparked while parking
|
||||||
if (parkPermit && compareAndSetState(PARKED, RUNNABLE)) {
|
if (parkPermit && compareAndSetState(PARKED, RUNNABLE)) {
|
||||||
@ -478,7 +475,7 @@ final class VirtualThread extends BaseVirtualThread {
|
|||||||
setState(RUNNABLE);
|
setState(RUNNABLE);
|
||||||
|
|
||||||
// notify JVMTI that unmount has completed, thread is runnable
|
// notify JVMTI that unmount has completed, thread is runnable
|
||||||
notifyJvmtiUnmount(/*hide*/false, /*last*/false);
|
notifyJvmtiUnmount(/*hide*/false);
|
||||||
|
|
||||||
// external submit if there are no tasks in the local task queue
|
// external submit if there are no tasks in the local task queue
|
||||||
if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) {
|
if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) {
|
||||||
@ -508,7 +505,7 @@ final class VirtualThread extends BaseVirtualThread {
|
|||||||
assert (state() == TERMINATED) && (carrierThread == null);
|
assert (state() == TERMINATED) && (carrierThread == null);
|
||||||
|
|
||||||
if (executed) {
|
if (executed) {
|
||||||
notifyJvmtiUnmount(/*hide*/false, /*last*/true);
|
notifyJvmtiUnmount(/*hide*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify anyone waiting for this virtual thread to terminate
|
// notify anyone waiting for this virtual thread to terminate
|
||||||
@ -1086,11 +1083,19 @@ final class VirtualThread extends BaseVirtualThread {
|
|||||||
|
|
||||||
@IntrinsicCandidate
|
@IntrinsicCandidate
|
||||||
@JvmtiMountTransition
|
@JvmtiMountTransition
|
||||||
private native void notifyJvmtiMount(boolean hide, boolean firstMount);
|
private native void notifyJvmtiStart();
|
||||||
|
|
||||||
@IntrinsicCandidate
|
@IntrinsicCandidate
|
||||||
@JvmtiMountTransition
|
@JvmtiMountTransition
|
||||||
private native void notifyJvmtiUnmount(boolean hide, boolean lastUnmount);
|
private native void notifyJvmtiEnd();
|
||||||
|
|
||||||
|
@IntrinsicCandidate
|
||||||
|
@JvmtiMountTransition
|
||||||
|
private native void notifyJvmtiMount(boolean hide);
|
||||||
|
|
||||||
|
@IntrinsicCandidate
|
||||||
|
@JvmtiMountTransition
|
||||||
|
private native void notifyJvmtiUnmount(boolean hide);
|
||||||
|
|
||||||
@IntrinsicCandidate
|
@IntrinsicCandidate
|
||||||
@JvmtiMountTransition
|
@JvmtiMountTransition
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -32,9 +32,11 @@
|
|||||||
#define VIRTUAL_THREAD "Ljava/lang/VirtualThread;"
|
#define VIRTUAL_THREAD "Ljava/lang/VirtualThread;"
|
||||||
|
|
||||||
static JNINativeMethod methods[] = {
|
static JNINativeMethod methods[] = {
|
||||||
{ "notifyJvmtiMount", "(ZZ)V", (void *)&JVM_VirtualThreadMount },
|
{ "notifyJvmtiStart", "()V", (void *)&JVM_VirtualThreadStart },
|
||||||
{ "notifyJvmtiUnmount", "(ZZ)V", (void *)&JVM_VirtualThreadUnmount },
|
{ "notifyJvmtiEnd", "()V", (void *)&JVM_VirtualThreadEnd },
|
||||||
{ "notifyJvmtiHideFrames", "(Z)V", (void *)&JVM_VirtualThreadHideFrames },
|
{ "notifyJvmtiMount", "(Z)V", (void *)&JVM_VirtualThreadMount },
|
||||||
|
{ "notifyJvmtiUnmount", "(Z)V", (void *)&JVM_VirtualThreadUnmount },
|
||||||
|
{ "notifyJvmtiHideFrames", "(Z)V", (void *)&JVM_VirtualThreadHideFrames },
|
||||||
};
|
};
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
|
Loading…
Reference in New Issue
Block a user