Skip to content

Commit

Permalink
Merge pull request #18495 from babsingh/0.43_backports
Browse files Browse the repository at this point in the history
[0.43] Virtual Thread Support
  • Loading branch information
tajila committed Nov 20, 2023
2 parents f263056 + ecdbc7b commit 12fb70a
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 37 deletions.
39 changes: 29 additions & 10 deletions runtime/j9vm/javanextvmi.cpp
Expand Up @@ -310,8 +310,6 @@ virtualThreadMountBegin(JNIEnv *env, jobject thread)
{
J9VMThread *currentThread = (J9VMThread *)env;

VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_TRUE);

j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread);
Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObj));

Expand Down Expand Up @@ -351,6 +349,8 @@ virtualThreadMountBegin(JNIEnv *env, jobject thread)
enterVThreadTransitionCritical(currentThread, thread);
threadObj = J9_JNI_UNWRAP_REFERENCE(thread);
}

VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_TRUE);
}

/* Caller must have VMAccess. */
Expand All @@ -361,8 +361,6 @@ virtualThreadMountEnd(JNIEnv *env, jobject thread)
J9JavaVM *vm = currentThread->javaVM;
j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread);

VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_FALSE);

Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObj));

if (TrcEnabled_Trc_SC_VirtualThread_Info) {
Expand All @@ -377,6 +375,8 @@ virtualThreadMountEnd(JNIEnv *env, jobject thread)
J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, continuationObj));
}

VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_FALSE);

/* Allow thread to be inspected again. */
exitVThreadTransitionCritical(currentThread, threadObj);

Expand Down Expand Up @@ -409,7 +409,6 @@ virtualThreadUnmountBegin(JNIEnv *env, jobject thread)
TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_UNMOUNT(vm->hookInterface, currentThread);

enterVThreadTransitionCritical(currentThread, thread);
VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_TRUE);

J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
j9object_t carrierThreadObject = currentThread->carrierThreadObject;
Expand All @@ -432,6 +431,8 @@ virtualThreadUnmountBegin(JNIEnv *env, jobject thread)
carrierThreadObject = currentThread->carrierThreadObject;
threadObj = J9_JNI_UNWRAP_REFERENCE(thread);
}

VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_TRUE);
}

/* Caller must have VMAccess. */
Expand All @@ -442,8 +443,6 @@ virtualThreadUnmountEnd(JNIEnv *env, jobject thread)
J9JavaVM *vm = currentThread->javaVM;
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;

VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_FALSE);

j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread);
j9object_t continuationObj = J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObj);
ContinuationState continuationState = *VM_ContinuationHelpers::getContinuationStateAddress(currentThread, continuationObj);
Expand All @@ -465,6 +464,8 @@ virtualThreadUnmountEnd(JNIEnv *env, jobject thread)
vmFuncs->freeTLS(currentThread, threadObj);
}

VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_FALSE);

/* Allow thread to be inspected again. */
exitVThreadTransitionCritical(currentThread, threadObj);
}
Expand Down Expand Up @@ -577,13 +578,31 @@ JNIEXPORT void JNICALL
JVM_VirtualThreadHideFrames(JNIEnv *env, jobject vthread, jboolean hide)
{
J9VMThread *currentThread = (J9VMThread *)env;
J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions;

vmFuncs->internalEnterVMFromJNI(currentThread);

j9object_t vThreadObj = currentThread->threadObject;
Assert_SC_true(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, vThreadObj));
/* Do not allow JVMTI operations because J9VMThread->threadObject is modified
* between the first invocation with hide=true and the second invocation with
* hide=false. Otherwise, JVMTI functions will see an unstable
* J9VMThread->threadObject.
*/
bool hiddenFrames = J9_ARE_ALL_BITS_SET(currentThread->privateFlags, J9_PRIVATE_FLAGS_VIRTUAL_THREAD_HIDDEN_FRAMES);
if (hide) {
Assert_SC_true(J9_ARE_NO_BITS_SET(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));
Assert_SC_true(!hiddenFrames && (vThreadObj == J9_JNI_UNWRAP_REFERENCE(vthread)));
enterVThreadTransitionCritical(currentThread, vthread);
}

VM_VMHelpers::virtualThreadHideFrames(currentThread, hide);

if (!hide) {
Assert_SC_true(hiddenFrames);
exitVThreadTransitionCritical(currentThread, vThreadObj);
}

vmFuncs->internalExitVMToJNI(currentThread);
}
#endif /* JAVA_SPEC_VERSION >= 20 */

Expand Down
2 changes: 1 addition & 1 deletion runtime/jvmti/CMakeLists.txt
Expand Up @@ -49,7 +49,7 @@ j9vm_add_library(j9jvmti SHARED
jvmtiStackFrame.c
jvmtiStartup.c
jvmtiSystemProperties.c
jvmtiThread.c
jvmtiThread.cpp
jvmtiThreadGroup.c
jvmtiTimers.c
jvmtiWatchedField.c
Expand Down
17 changes: 2 additions & 15 deletions runtime/jvmti/jvmtiHelpers.cpp
Expand Up @@ -846,25 +846,12 @@ getVirtualThreadState(J9VMThread *currentThread, jthread thread)
break;
case JVMTI_VTHREAD_STATE_STARTED:
{
JNIEnv *env = (JNIEnv *)currentThread;
jfieldID fid = NULL;
jclass jlThread = NULL;

vm->internalVMFunctions->internalExitVMToJNI(currentThread);
jlThread = env->FindClass("java/lang/Thread");
if (NULL != jlThread) {
fid = env->GetFieldID(jlThread, "container", "Ljdk/internal/vm/ThreadContainer;");
}
if ((NULL != fid)
&& (NULL == env->GetObjectField(thread, fid))
) {
j9object_t threadContainer = J9VMJAVALANGTHREAD_CONTAINER(currentThread, vThreadObject);
if (NULL == threadContainer) {
rc = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
} else {
rc = JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE;
}
vm->internalVMFunctions->internalEnterVMFromJNI(currentThread);
/* Re-fetch object to correctly set the isSuspendedInternal field. */
vThreadObject = J9_JNI_UNWRAP_REFERENCE(thread);
break;
}
case JVMTI_VTHREAD_STATE_RUNNABLE:
Expand Down
24 changes: 14 additions & 10 deletions runtime/jvmti/jvmtiThread.c → runtime/jvmti/jvmtiThread.cpp
Expand Up @@ -24,6 +24,8 @@
#include "jvmtiHelpers.h"
#include "jvmti_internal.h"

extern "C" {

typedef struct J9JVMTIRunAgentThreadArgs {
jvmtiEnv *jvmti_env;
jvmtiStartFunction proc;
Expand Down Expand Up @@ -180,7 +182,7 @@ jvmtiGetAllThreads(jvmtiEnv *env,

vm->internalVMFunctions->acquireExclusiveVMAccess(currentThread);

threads = j9mem_allocate_memory(sizeof(jthread) * vm->totalThreadCount, J9MEM_CATEGORY_JVMTI_ALLOCATE);
threads = (jthread *)j9mem_allocate_memory(sizeof(jthread) * vm->totalThreadCount, J9MEM_CATEGORY_JVMTI_ALLOCATE);
if (NULL == threads) {
rc = JVMTI_ERROR_OUT_OF_MEMORY;
} else {
Expand Down Expand Up @@ -525,7 +527,7 @@ jvmtiGetThreadInfo(jvmtiEnv *env,
j9object_t threadName = J9VMJAVALANGTHREAD_NAME(currentThread, threadObject);

if (NULL == threadName) {
name = j9mem_allocate_memory(1, J9MEM_CATEGORY_JVMTI_ALLOCATE);
name = (char *)j9mem_allocate_memory(1, J9MEM_CATEGORY_JVMTI_ALLOCATE);
if (NULL == name) {
rc = JVMTI_ERROR_OUT_OF_MEMORY;
goto release;
Expand All @@ -543,7 +545,7 @@ jvmtiGetThreadInfo(jvmtiEnv *env,
size_t threadNameLen = (NULL == threadName) ? 1 : (strlen(threadName) + 1);

/* Be sure to allocate at least one byte for the nul termination. */
name = j9mem_allocate_memory(threadNameLen, J9MEM_CATEGORY_JVMTI_ALLOCATE);
name = (char *)j9mem_allocate_memory(threadNameLen, J9MEM_CATEGORY_JVMTI_ALLOCATE);
if (NULL == name) {
/* Failed to allocate memory, so release VMTthread and exit. */
releaseOMRVMThreadName(targetThread->omrVMThread);
Expand Down Expand Up @@ -698,7 +700,7 @@ jvmtiGetOwnedMonitorInfo(jvmtiEnv *env,

count = walkLocalMonitorRefs(currentThread, NULL, targetThread, threadToWalk, UDATA_MAX);

locks = j9mem_allocate_memory(sizeof(jobject) * count, J9MEM_CATEGORY_JVMTI_ALLOCATE);
locks = (jobject *)j9mem_allocate_memory(sizeof(jobject) * count, J9MEM_CATEGORY_JVMTI_ALLOCATE);
if (NULL == locks) {
rc = JVMTI_ERROR_OUT_OF_MEMORY;
} else if (0 != count) {
Expand Down Expand Up @@ -817,7 +819,7 @@ jvmtiGetOwnedMonitorStackDepthInfo(jvmtiEnv *env,

/* Do we have any records at all? */
if (maxRecords > 0) {
resultArray = j9mem_allocate_memory((jlong)maxRecords * sizeof(jvmtiMonitorStackDepthInfo), J9MEM_CATEGORY_JVMTI_ALLOCATE);
resultArray = (jvmtiMonitorStackDepthInfo *)j9mem_allocate_memory((jlong)maxRecords * sizeof(jvmtiMonitorStackDepthInfo), J9MEM_CATEGORY_JVMTI_ALLOCATE);
if (NULL == resultArray) {
maxRecords = 0;
resultArray = NULL;
Expand Down Expand Up @@ -970,7 +972,7 @@ jvmtiRunAgentThread(jvmtiEnv *env,
}

/* Create entry args for the thread proc. */
args = j9mem_allocate_memory(sizeof(J9JVMTIRunAgentThreadArgs), J9MEM_CATEGORY_JVMTI);
args = (J9JVMTIRunAgentThreadArgs *)j9mem_allocate_memory(sizeof(J9JVMTIRunAgentThreadArgs), J9MEM_CATEGORY_JVMTI);
if (NULL == args) {
rc = JVMTI_ERROR_OUT_OF_MEMORY;
} else {
Expand Down Expand Up @@ -1169,7 +1171,7 @@ static int J9THREAD_PROC
agentThreadStart(void *entryArg)
{
UDATA result = 0;
J9JVMTIRunAgentThreadArgs *args = entryArg;
J9JVMTIRunAgentThreadArgs *args = (J9JVMTIRunAgentThreadArgs *)entryArg;
J9JavaVM *vm = JAVAVM_FROM_ENV((J9JVMTIEnv *)args->jvmti_env);
J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm);
PORT_ACCESS_FROM_JAVAVM(vm);
Expand All @@ -1189,7 +1191,7 @@ agentThreadStart(void *entryArg)
static UDATA
wrappedAgentThreadStart(J9PortLibrary *portLib, void *entryArg)
{
J9JVMTIRunAgentThreadArgs *args = entryArg;
J9JVMTIRunAgentThreadArgs *args = (J9JVMTIRunAgentThreadArgs *)entryArg;
J9JavaVM *vm = JAVAVM_FROM_ENV((J9JVMTIEnv *)args->jvmti_env);
J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm);
jvmtiEnv *jvmti_env = args->jvmti_env;
Expand Down Expand Up @@ -1279,10 +1281,10 @@ walkLocalMonitorRefs(J9VMThread *currentThread, jobject *locks, J9VMThread *targ

/* Check the local JNI refs. */
while (NULL != frame) {
ref = pool_startDo(frame->references, &poolState);
ref = (j9object_t *)pool_startDo((J9Pool *)frame->references, &poolState);
while (NULL != ref) {
ownedMonitorIterator(currentThread, &walkState, ref, ref);
ref = pool_nextDo(&poolState);
ref = (j9object_t *)pool_nextDo(&poolState);
}
frame = frame->previous;
}
Expand Down Expand Up @@ -1475,3 +1477,5 @@ jvmtiResumeAllVirtualThreads(jvmtiEnv *env,
TRACE_JVMTI_RETURN(jvmtiResumeAllVirtualThreads);
}
#endif /* JAVA_SPEC_VERSION >= 19 */

} /* extern "C" */
2 changes: 1 addition & 1 deletion runtime/jvmti/jvmti_internal.h
Expand Up @@ -2238,7 +2238,7 @@ jvmtiSetSystemProperty(jvmtiEnv* env,
const char* value);


/* ---------------- jvmtiThread.c ---------------- */
/* ---------------- jvmtiThread.cpp ---------------- */

/**
* @brief
Expand Down
1 change: 1 addition & 0 deletions runtime/oti/vmconstantpool.xml
Expand Up @@ -247,6 +247,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
<!-- Field references for Java 19 Virtual Thread. -->
<fieldref class="java/lang/Thread" name="cont" signature="Ljdk/internal/vm/Continuation;" versions="19-"/>
<fieldref class="java/lang/Thread" name="holder" signature="Ljava/lang/Thread$FieldHolder;" versions="19-"/>
<fieldref class="java/lang/Thread" name="container" signature="Ljdk/internal/vm/ThreadContainer;" versions="19-"/>
<fieldref class="java/lang/Thread$FieldHolder" name="daemon" signature="Z" versions="19-"/>
<fieldref class="java/lang/Thread$FieldHolder" name="group" signature="Ljava/lang/ThreadGroup;" versions="19-"/>
<fieldref class="java/lang/Thread$FieldHolder" name="priority" signature="I" versions="19-"/>
Expand Down

0 comments on commit 12fb70a

Please sign in to comment.