diff --git a/runtime/j9vm/exports.cmake b/runtime/j9vm/exports.cmake index be90331a10a..d755fd7a6bf 100644 --- a/runtime/j9vm/exports.cmake +++ b/runtime/j9vm/exports.cmake @@ -433,7 +433,9 @@ if(JAVA_SPEC_VERSION LESS 21) else() jvm_add_exports(jvm JVM_IsForeignLinkerSupported + JVM_VirtualThreadEnd JVM_VirtualThreadMount + JVM_VirtualThreadStart JVM_VirtualThreadUnmount ) endif() diff --git a/runtime/j9vm/j9scar.tdf b/runtime/j9vm/j9scar.tdf index 52b6e829e34..f1d569ace2b 100644 --- a/runtime/j9vm/j9scar.tdf +++ b/runtime/j9vm/j9scar.tdf @@ -339,10 +339,10 @@ TraceEntry=Trc_SC_RegisterSignal_Entry Overhead=1 Level=1 Template="JVM_Register TraceExit=Trc_SC_RegisterSignal_Exit Overhead=1 Level=1 Template="JVM_RegisterSignal -- return old OS handler = %p" TraceException=Trc_SC_RegisterSignal_FailedToRegisterHandler Overhead=1 Level=1 Template="Failed to register handler: OS signal value = %d, new signal handler = %p, old signal handler = %p" -TraceEntry=Trc_SC_GetExtendedNPEMessage_Entry Overhead=1 Level=3 Template="JVM_GetExtendedNPEMessage - throwableObj(0x%p)" -TraceEntry=Trc_SC_GetExtendedNPEMessage_Entry2 Overhead=1 Level=1 Template="JVM_GetExtendedNPEMessage - throwableObj(0x%p)" -TraceEvent=Trc_SC_GetExtendedNPEMessage_Null_NPE_MSG Overhead=1 Level=1 Template="JVM_GetExtendedNPEMessage - returns a NULL NPE message : romClass (0x%p) && romMethod (0x%p) bytecodeOffset (%d)" -TraceExit=Trc_SC_GetExtendedNPEMessage_Exit Overhead=1 Level=3 Template="JVM_GetExtendedNPEMessage - returns msgObjectRef(0x%p)" +TraceEntry=Trc_SC_GetExtendedNPEMessage_Entry Overhead=1 Level=3 Template="JVM_GetExtendedNPEMessage - throwableObj(%p)" +TraceEntry=Trc_SC_GetExtendedNPEMessage_Entry2 Overhead=1 Level=1 Template="JVM_GetExtendedNPEMessage - throwableObj(%p)" +TraceEvent=Trc_SC_GetExtendedNPEMessage_Null_NPE_MSG Overhead=1 Level=1 Template="JVM_GetExtendedNPEMessage - returns a NULL NPE message : romClass (%p) && romMethod (%p) bytecodeOffset (%d)" +TraceExit=Trc_SC_GetExtendedNPEMessage_Exit Overhead=1 Level=3 Template="JVM_GetExtendedNPEMessage - returns msgObjectRef(%p)" TraceEntry=Trc_SC_UnloadLibrary_Entry NoEnv Overhead=1 Level=2 Template="JVM_UnloadLibrary(handle=%p)" TraceEvent=Trc_SC_LoadLibrary_BootStrap NoEnv Overhead=1 Level=3 Template="JVM_LoadLibrary(name=%s) Bootstrap library" @@ -351,21 +351,21 @@ TraceEvent=Trc_SC_LoadLibrary_OpenShared_Decorate NoEnv Overhead=1 Level=3 Templ TraceExit=Trc_SC_LoadLibrary_Exit NoEnv Overhead=1 Level=2 Template="JVM_LoadLibrary -- return 0x%zx" -TraceEntry=Trc_SC_VirtualThreadMountBegin_Entry Overhead=1 Level=3 Template="thread = 0x%p, firstMount = %d" -TraceExit=Trc_SC_VirtualThreadMountBegin_Exit Overhead=1 Level=3 Template="thread = 0x%p, firstMount = %d" +TraceEntry=Trc_SC_VirtualThreadMountBegin_Entry Overhead=1 Level=3 Template="thread = %p, firstMount = %d" +TraceExit=Trc_SC_VirtualThreadMountBegin_Exit Overhead=1 Level=3 Template="thread = %p, firstMount = %d" -TraceEntry=Trc_SC_VirtualThreadMountEnd_Entry Overhead=1 Level=3 Template="thread = 0x%p, firstMount = %d" -TraceExit=Trc_SC_VirtualThreadMountEnd_Exit Overhead=1 Level=3 Template="thread = 0x%p, firstMount = %d" +TraceEntry=Trc_SC_VirtualThreadMountEnd_Entry Overhead=1 Level=3 Template="thread = %p, firstMount = %d" +TraceExit=Trc_SC_VirtualThreadMountEnd_Exit Overhead=1 Level=3 Template="thread = %p, firstMount = %d" -TraceEntry=Trc_SC_VirtualThreadUnmountBegin_Entry Overhead=1 Level=3 Template="thread = 0x%p, lastUnmount = %d" -TraceExit=Trc_SC_VirtualThreadUnmountBegin_Exit Overhead=1 Level=3 Template="thread = 0x%p, lastUnmount = %d" +TraceEntry=Trc_SC_VirtualThreadUnmountBegin_Entry Overhead=1 Level=3 Template="thread = %p, lastUnmount = %d" +TraceExit=Trc_SC_VirtualThreadUnmountBegin_Exit Overhead=1 Level=3 Template="thread = %p, lastUnmount = %d" -TraceEntry=Trc_SC_VirtualThreadUnmountEnd_Entry Overhead=1 Level=3 Template="thread = 0x%p, lastUnmount = %d" -TraceExit=Trc_SC_VirtualThreadUnmountEnd_Exit Overhead=1 Level=3 Template="thread = 0x%p, lastUnmount = %d" +TraceEntry=Trc_SC_VirtualThreadUnmountEnd_Entry Overhead=1 Level=3 Template="thread = %p, lastUnmount = %d" +TraceExit=Trc_SC_VirtualThreadUnmountEnd_Exit Overhead=1 Level=3 Template="thread = %p, lastUnmount = %d" -TraceEvent=Trc_SC_VirtualThread_Info Overhead=1 Level=3 Test Template="virtualThreadObj = 0x%p, virtualThreadState = 0x%p, virtualThreadInspectorCount = %lld, carrierThreadObj = 0x%p, continuationObj = 0x%p, J9VMContinuation = 0x%p" +TraceEvent=Trc_SC_VirtualThread_Info Overhead=1 Level=3 Test Template="virtualThreadObj = %p, virtualThreadState = %p, virtualThreadInspectorCount = %lld, carrierThreadObj = %p, continuationObj = %p, J9VMContinuation = %p" -TraceEvent=Trc_SC_VirtualThread_RootNodeSet Overhead=1 Level=1 Test Template="Virtual threadlist root node set, global ref = 0x%p" +TraceEvent=Trc_SC_VirtualThread_RootNodeSet Overhead=1 Level=1 Test Template="Virtual threadlist root node set, global ref = %p" TraceEntry=Trc_SC_ValidateJNILibrary_Entry NoEnv Overhead=1 Level=1 Template="JVM_ValidateJNILibrary(name=%s, handle=%p, isStatic=%d)" TraceExit=Trc_SC_ValidateJNILibrary_Exit NoEnv Overhead=1 Level=1 Template="JVM_ValidateJNILibrary -- return %p" @@ -375,3 +375,15 @@ TraceExit=Trc_SC_UnloadLibrary_Exit NoEnv Overhead=1 Level=2 Template="JVM_Unloa // z/OS only TraceEntry=Trc_SC_Invoke31BitJNI_OnXLoad_Entry NoEnv Overhead=1 Level=3 Template="JVM_Invoke31BitJNI_OnXLoad(vm=%p, handle=%p, isOnLoad=%d, reserved=%p)" TraceExit=Trc_SC_Invoke31BitJNI_OnXLoad_Exit NoEnv Overhead=1 Level=3 Template="JVM_Invoke31BitJNI_OnXLoad -- return %d" + +TraceEntry=Trc_SC_VirtualThreadMount_Entry Overhead=1 Level=3 Template="thread = %p, hide = %d" +TraceExit=Trc_SC_VirtualThreadMount_Exit Overhead=1 Level=3 Template="thread = %p, hide = %d" + +TraceEntry=Trc_SC_VirtualThreadUnmount_Entry Overhead=1 Level=3 Template="thread = %p, hide = %d" +TraceExit=Trc_SC_VirtualThreadUnmount_Exit Overhead=1 Level=3 Template="thread = %p, hide = %d" + +TraceEntry=Trc_SC_VirtualThreadStart_Entry Overhead=1 Level=3 Template="thread = %p" +TraceExit=Trc_SC_VirtualThreadStart_Exit Overhead=1 Level=3 Template="thread = %p" + +TraceEntry=Trc_SC_VirtualThreadEnd_Entry Overhead=1 Level=3 Template="thread = %p" +TraceExit=Trc_SC_VirtualThreadEnd_Exit Overhead=1 Level=3 Template="thread = %p" diff --git a/runtime/j9vm/j9vmnatives.xml b/runtime/j9vm/j9vmnatives.xml index 47a36f0ac0c..2a08cd5adcf 100644 --- a/runtime/j9vm/j9vmnatives.xml +++ b/runtime/j9vm/j9vmnatives.xml @@ -440,7 +440,9 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex + + diff --git a/runtime/j9vm/javanextvmi.cpp b/runtime/j9vm/javanextvmi.cpp index 5683e1034ee..14a21282821 100644 --- a/runtime/j9vm/javanextvmi.cpp +++ b/runtime/j9vm/javanextvmi.cpp @@ -30,6 +30,7 @@ #if JAVA_SPEC_VERSION >= 19 #include "VMHelpers.hpp" +#include "ContinuationHelpers.hpp" #endif /* JAVA_SPEC_VERSION >= 19 */ extern "C" { @@ -272,20 +273,31 @@ exitVThreadTransitionCritical(J9VMThread *currentThread, j9object_t vthread) J9OBJECT_I64_STORE(currentThread, vthread, currentThread->javaVM->virtualThreadInspectorCountOffset, 0); } -JNIEXPORT void JNICALL -JVM_VirtualThreadMountBegin(JNIEnv *env, jobject thread, jboolean firstMount) +static void +unsetParentVthread(J9VMThread *currentThread, jobject thread) +{ + enterVThreadTransitionCritical(currentThread, thread); + /* Re-fetch reference as enterVThreadTransitionCritical may release VMAccess. */ + j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread); + j9object_t continuationObj = J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObj); + /* Add reverse link from Continuation object to VirtualThread object, this let JVMTI code. */ + J9VMJDKINTERNALVMCONTINUATION_SET_VTHREAD(currentThread, continuationObj, NULL); + exitVThreadTransitionCritical(currentThread, threadObj); +} + +/* Caller must have VMAccess. */ +static void +virtualThreadMountBegin(JNIEnv *env, jobject thread) { J9VMThread *currentThread = (J9VMThread *)env; - J9JavaVM *vm = currentThread->javaVM; - J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; - Trc_SC_VirtualThreadMountBegin_Entry(currentThread, thread, firstMount); + VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_TRUE); - vmFuncs->internalEnterVMFromJNI(currentThread); j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread); Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObj)); if (TrcEnabled_Trc_SC_VirtualThread_Info) { + J9JavaVM *vm = currentThread->javaVM; j9object_t continuationObj = J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObj); J9VMContinuation *continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, continuationObj); Trc_SC_VirtualThread_Info( @@ -299,26 +311,17 @@ JVM_VirtualThreadMountBegin(JNIEnv *env, jobject thread, jboolean firstMount) } enterVThreadTransitionCritical(currentThread, thread); - - vmFuncs->internalExitVMToJNI(currentThread); - - Trc_SC_VirtualThreadMountBegin_Exit(currentThread, thread, firstMount); } -JNIEXPORT void JNICALL -JVM_VirtualThreadMountEnd(JNIEnv *env, jobject thread, jboolean firstMount) +/* Caller must have VMAccess. */ +static void +virtualThreadMountEnd(JNIEnv *env, jobject thread) { J9VMThread *currentThread = (J9VMThread *)env; J9JavaVM *vm = currentThread->javaVM; - J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; - j9object_t rootVirtualThread = NULL; - j9object_t threadObj = NULL; - BOOLEAN runJ9Hooks = FALSE; - - Trc_SC_VirtualThreadMountEnd_Entry(currentThread, thread, firstMount); + j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread); - vmFuncs->internalEnterVMFromJNI(currentThread); - threadObj = J9_JNI_UNWRAP_REFERENCE(thread); + VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_FALSE); Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObj)); @@ -340,32 +343,22 @@ JVM_VirtualThreadMountEnd(JNIEnv *env, jobject thread, jboolean firstMount) */ if (0 != J9OBJECT_U32_LOAD(currentThread, threadObj, vm->isSuspendedInternalOffset)) { Assert_SC_true(threadObj == currentThread->threadObject); - vmFuncs->setHaltFlag(currentThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND); + vm->internalVMFunctions->setHaltFlag(currentThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND); } /* Allow thread to be inspected again. */ exitVThreadTransitionCritical(currentThread, threadObj); - if (firstMount) { - TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_STARTED(vm->hookInterface, currentThread); - } TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_MOUNT(vm->hookInterface, currentThread); - - vmFuncs->internalExitVMToJNI(currentThread); - - Trc_SC_VirtualThreadMountEnd_Exit(currentThread, thread, firstMount); } -JNIEXPORT void JNICALL -JVM_VirtualThreadUnmountBegin(JNIEnv *env, jobject thread, jboolean lastUnmount) +/* Caller must have VMAccess. */ +static void +virtualThreadUnmountBegin(JNIEnv *env, jobject thread) { J9VMThread *currentThread = (J9VMThread *)env; J9JavaVM *vm = currentThread->javaVM; - J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; - - Trc_SC_VirtualThreadUnmountBegin_Entry(currentThread, thread, lastUnmount); - vmFuncs->internalEnterVMFromJNI(currentThread); j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread); Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObj)); @@ -383,39 +376,28 @@ JVM_VirtualThreadUnmountBegin(JNIEnv *env, jobject thread, jboolean lastUnmount) } TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_UNMOUNT(vm->hookInterface, currentThread); - if (lastUnmount) { - TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_END(vm->hookInterface, currentThread); - } enterVThreadTransitionCritical(currentThread, thread); - if (lastUnmount) { - /* Re-fetch reference as enterVThreadTransitionCritical may release VMAccess. */ - threadObj = J9_JNI_UNWRAP_REFERENCE(thread); - j9object_t continuationObj = J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObj); - /* Add reverse link from Continuation object to VirtualThread object, this let JVMTI code */ - J9VMJDKINTERNALVMCONTINUATION_SET_VTHREAD(currentThread, continuationObj, NULL); - } - vmFuncs->internalExitVMToJNI(currentThread); - - Trc_SC_VirtualThreadUnmountBegin_Exit(currentThread, thread, lastUnmount); + VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_TRUE); } -JNIEXPORT void JNICALL -JVM_VirtualThreadUnmountEnd(JNIEnv *env, jobject thread, jboolean lastUnmount) +/* Caller must have VMAccess. */ +static void +virtualThreadUnmountEnd(JNIEnv *env, jobject thread) { J9VMThread *currentThread = (J9VMThread *)env; J9JavaVM *vm = currentThread->javaVM; J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; - Trc_SC_VirtualThreadUnmountEnd_Entry(currentThread, thread, lastUnmount); + VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_FALSE); - vmFuncs->internalEnterVMFromJNI(currentThread); j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread); + j9object_t continuationObj = J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObj); + ContinuationState continuationState = *VM_ContinuationHelpers::getContinuationStateAddress(currentThread, continuationObj); Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObj)); if (TrcEnabled_Trc_SC_VirtualThread_Info) { - j9object_t continuationObj = J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObj); Trc_SC_VirtualThread_Info( currentThread, threadObj, @@ -426,7 +408,7 @@ JVM_VirtualThreadUnmountEnd(JNIEnv *env, jobject thread, jboolean lastUnmount) J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, continuationObj)); } - if (lastUnmount) { + if (VM_ContinuationHelpers::isFinished(continuationState)) { vmFuncs->freeTLS(currentThread, threadObj); } @@ -441,12 +423,89 @@ JVM_VirtualThreadUnmountEnd(JNIEnv *env, jobject thread, jboolean lastUnmount) /* Allow thread to be inspected again. */ exitVThreadTransitionCritical(currentThread, threadObj); +} +#endif /* JAVA_SPEC_VERSION >= 19 */ + +#if (19 <= JAVA_SPEC_VERSION) && (JAVA_SPEC_VERSION < 21) +JNIEXPORT void JNICALL +JVM_VirtualThreadMountBegin(JNIEnv *env, jobject thread, jboolean firstMount) +{ + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; + + Trc_SC_VirtualThreadMountBegin_Entry(currentThread, thread, firstMount); + + vmFuncs->internalEnterVMFromJNI(currentThread); + + virtualThreadMountBegin(env, thread); + + vmFuncs->internalExitVMToJNI(currentThread); + + Trc_SC_VirtualThreadMountBegin_Exit(currentThread, thread, firstMount); +} + +JNIEXPORT void JNICALL +JVM_VirtualThreadMountEnd(JNIEnv *env, jobject thread, jboolean firstMount) +{ + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; + + Trc_SC_VirtualThreadMountEnd_Entry(currentThread, thread, firstMount); + + vmFuncs->internalEnterVMFromJNI(currentThread); + + virtualThreadMountEnd(env, thread); + if (firstMount) { + TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_STARTED(vm->hookInterface, currentThread); + } + + vmFuncs->internalExitVMToJNI(currentThread); + + Trc_SC_VirtualThreadMountEnd_Exit(currentThread, thread, firstMount); +} + +JNIEXPORT void JNICALL +JVM_VirtualThreadUnmountBegin(JNIEnv *env, jobject thread, jboolean lastUnmount) +{ + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; + + Trc_SC_VirtualThreadUnmountBegin_Entry(currentThread, thread, lastUnmount); + + vmFuncs->internalEnterVMFromJNI(currentThread); + + if (lastUnmount) { + TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_END(vm->hookInterface, currentThread); + unsetParentVthread((J9VMThread *)env, thread); + } + virtualThreadUnmountBegin(env, thread); + + vmFuncs->internalExitVMToJNI(currentThread); + + Trc_SC_VirtualThreadUnmountBegin_Exit(currentThread, thread,lastUnmount); +} + +JNIEXPORT void JNICALL +JVM_VirtualThreadUnmountEnd(JNIEnv *env, jobject thread, jboolean lastUnmount) +{ + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; + + Trc_SC_VirtualThreadUnmountEnd_Entry(currentThread, thread, lastUnmount); + + vmFuncs->internalEnterVMFromJNI(currentThread); + + virtualThreadUnmountEnd(env, thread); vmFuncs->internalExitVMToJNI(currentThread); Trc_SC_VirtualThreadUnmountEnd_Exit(currentThread, thread, lastUnmount); } -#endif /* JAVA_SPEC_VERSION >= 19 */ +#endif /* (19 <= JAVA_SPEC_VERSION) && (JAVA_SPEC_VERSION < 21) */ #if JAVA_SPEC_VERSION >= 20 JNIEXPORT jint JNICALL @@ -474,37 +533,60 @@ JNIEXPORT void JNICALL JVM_VirtualThreadHideFrames(JNIEnv *env, jobject vthread, jboolean hide) { J9VMThread *currentThread = (J9VMThread *)env; - Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, currentThread->threadObject)); + Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, currentThread->threadObject)); if (hide) { Assert_SC_true(J9_ARE_NO_BITS_SET(currentThread->privateFlags, J9_PRIVATE_FLAGS_VIRTUAL_THREAD_HIDDEN_FRAMES)); - currentThread->privateFlags |= J9_PRIVATE_FLAGS_VIRTUAL_THREAD_HIDDEN_FRAMES; } else { Assert_SC_true(J9_ARE_ALL_BITS_SET(currentThread->privateFlags, J9_PRIVATE_FLAGS_VIRTUAL_THREAD_HIDDEN_FRAMES)); - currentThread->privateFlags &= ~(UDATA)J9_PRIVATE_FLAGS_VIRTUAL_THREAD_HIDDEN_FRAMES; } + VM_VMHelpers::virtualThreadHideFrames(currentThread, hide); } #endif /* JAVA_SPEC_VERSION >= 20 */ #if JAVA_SPEC_VERSION >= 21 JNIEXPORT void JNICALL -JVM_VirtualThreadMount(JNIEnv* env, jobject vthread, jboolean hide, jboolean firstMount) +JVM_VirtualThreadMount(JNIEnv *env, jobject vthread, jboolean hide) { + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; + + Trc_SC_VirtualThreadMount_Entry(currentThread, vthread, hide); + + vmFuncs->internalEnterVMFromJNI(currentThread); + if (hide) { - JVM_VirtualThreadMountBegin(env, vthread, firstMount); + virtualThreadMountBegin(env, vthread); } else { - JVM_VirtualThreadMountEnd(env, vthread, firstMount); + virtualThreadMountEnd(env, vthread); } + + vmFuncs->internalExitVMToJNI(currentThread); + + Trc_SC_VirtualThreadMount_Exit(currentThread, vthread, hide); } JNIEXPORT void JNICALL -JVM_VirtualThreadUnmount(JNIEnv* env, jobject vthread, jboolean hide, jboolean lastUnmount) +JVM_VirtualThreadUnmount(JNIEnv *env, jobject vthread, jboolean hide) { + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; + + Trc_SC_VirtualThreadUnmount_Entry(currentThread, vthread, hide); + + vmFuncs->internalEnterVMFromJNI(currentThread); + if (hide) { - JVM_VirtualThreadUnmountBegin(env, vthread, lastUnmount); + virtualThreadUnmountBegin(env, vthread); } else { - JVM_VirtualThreadUnmountEnd(env, vthread, lastUnmount); + virtualThreadUnmountEnd(env, vthread); } + + vmFuncs->internalExitVMToJNI(currentThread); + + Trc_SC_VirtualThreadUnmount_Exit(currentThread, vthread, hide); } JNIEXPORT jboolean JNICALL @@ -512,6 +594,45 @@ JVM_IsForeignLinkerSupported() { return JNI_TRUE; } + +JNIEXPORT void JNICALL +JVM_VirtualThreadStart(JNIEnv *env, jobject vthread) +{ + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; + + Trc_SC_VirtualThreadStart_Entry(currentThread, vthread); + + vmFuncs->internalEnterVMFromJNI(currentThread); + + virtualThreadMountEnd(env, vthread); + TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_STARTED(vm->hookInterface, currentThread); + + vmFuncs->internalExitVMToJNI(currentThread); + + Trc_SC_VirtualThreadStart_Exit(currentThread, vthread); +} + +JNIEXPORT void JNICALL +JVM_VirtualThreadEnd(JNIEnv *env, jobject vthread) +{ + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; + + Trc_SC_VirtualThreadEnd_Entry(currentThread, vthread); + + vmFuncs->internalEnterVMFromJNI(currentThread); + + TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_END(vm->hookInterface, currentThread); + unsetParentVthread((J9VMThread *)env, vthread); + virtualThreadUnmountBegin(env, vthread); + + vmFuncs->internalExitVMToJNI(currentThread); + + Trc_SC_VirtualThreadEnd_Exit(currentThread, vthread); +} #endif /* JAVA_SPEC_VERSION >= 21 */ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES) diff --git a/runtime/oti/VMHelpers.hpp b/runtime/oti/VMHelpers.hpp index 4a7cf8c3c8f..2132a46d09f 100644 --- a/runtime/oti/VMHelpers.hpp +++ b/runtime/oti/VMHelpers.hpp @@ -2062,6 +2062,17 @@ class VM_VMHelpers return oldState; } +#if JAVA_SPEC_VERSION >= 20 + static VMINLINE void + virtualThreadHideFrames(J9VMThread *currentThread, jboolean hide) + { + if (hide) { + currentThread->privateFlags |= J9_PRIVATE_FLAGS_VIRTUAL_THREAD_HIDDEN_FRAMES; + } else { + currentThread->privateFlags &= ~(UDATA)J9_PRIVATE_FLAGS_VIRTUAL_THREAD_HIDDEN_FRAMES; + } + } +#endif /* JAVA_SPEC_VERSION >= 20 */ }; #endif /* VMHELPERS_HPP_ */ diff --git a/runtime/redirector/forwarders.m4 b/runtime/redirector/forwarders.m4 index a473665fc87..73264aeba49 100644 --- a/runtime/redirector/forwarders.m4 +++ b/runtime/redirector/forwarders.m4 @@ -412,8 +412,12 @@ _IF([JAVA_SPEC_VERSION >= 20], _IF([JAVA_SPEC_VERSION >= 21], [_X(JVM_IsForeignLinkerSupported, JNICALL, false, jboolean, void)]) _IF([JAVA_SPEC_VERSION >= 21], - [_X(JVM_VirtualThreadMount, JNICALL, false, void, JNIEnv *env, jobject vthread, jboolean hide, jboolean firstMount)]) + [_X(JVM_VirtualThreadEnd, JNICALL, false, void, JNIEnv *env, jobject vthread)]) _IF([JAVA_SPEC_VERSION >= 21], - [_X(JVM_VirtualThreadUnmount, JNICALL, false, void, JNIEnv *env, jobject vthread, jboolean hide, jboolean lastUnmount)]) + [_X(JVM_VirtualThreadMount, JNICALL, false, void, JNIEnv *env, jobject vthread, jboolean hide)]) +_IF([JAVA_SPEC_VERSION >= 21], + [_X(JVM_VirtualThreadStart, JNICALL, false, void, JNIEnv *env, jobject vthread)]) +_IF([JAVA_SPEC_VERSION >= 21], + [_X(JVM_VirtualThreadUnmount, JNICALL, false, void, JNIEnv *env, jobject vthread, jboolean hide)]) _IF([defined(J9VM_OPT_VALHALLA_VALUE_TYPES)], [_X(JVM_IsValhallaEnabled, JNICALL, false, jboolean, void)])