Skip to content

Commit

Permalink
Merge pull request #16008 from babsingh/fix_GetCurrentContendedMonitor
Browse files Browse the repository at this point in the history
Fix JVMTI methods
  • Loading branch information
gacholio committed Oct 3, 2022
2 parents c11c5f0 + f0c5ffc commit 2d9d132
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 120 deletions.
2 changes: 1 addition & 1 deletion runtime/j9vm/javanextvmi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ JVM_VirtualThreadMountBegin(JNIEnv *env, jobject thread, jboolean firstMount)
f_monitorEnter(vm->liveVirtualThreadListMutex);
j9object_t threadObj = J9_JNI_UNWRAP_REFERENCE(thread);

assert(IS_VIRTUAL_THREAD(currentThread, threadObj));
assert(IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObj));

while (0 != J9OBJECT_I64_LOAD(currentThread, threadObj, vm->virtualThreadInspectorCountOffset)) {
/* Thread is being inspected or unmounted, wait. */
Expand Down
2 changes: 1 addition & 1 deletion runtime/jcl/common/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ Java_java_lang_Thread_getStackTraceImpl(JNIEnv *env, jobject rcv)

#if JAVA_SPEC_VERSION >= 19
BOOLEAN releaseInspector = FALSE;
if (IS_VIRTUAL_THREAD(currentThread, receiverObject)) {
if (IS_JAVA_LANG_VIRTUALTHREAD(currentThread, receiverObject)) {
omrthread_monitor_enter(vm->liveVirtualThreadListMutex);
j9object_t carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(currentThread, receiverObject);
I_64 vthreadInspectorCount = J9OBJECT_I64_LOAD(currentThread, receiverObject, vm->virtualThreadInspectorCountOffset);
Expand Down
20 changes: 12 additions & 8 deletions runtime/jvmti/jvmtiExtensionMechanism.c
Original file line number Diff line number Diff line change
Expand Up @@ -1465,13 +1465,14 @@ jvmtiGetOSThreadID(jvmtiEnv* jvmti_env, ...)
ENSURE_PHASE_START_OR_LIVE(jvmti_env);
ENSURE_NON_NULL(threadid_ptr);

rc = getVMThread(
currentThread, thread, &targetThread,
#if JAVA_SPEC_VERSION >= 19
if (NULL != thread) {
ENSURE_JTHREAD_NOT_VIRTUAL(currentThread, thread, JVMTI_ERROR_UNSUPPORTED_OPERATION);
}
JVMTI_ERROR_UNSUPPORTED_OPERATION,
#else /* JAVA_SPEC_VERSION >= 19 */
JVMTI_ERROR_NONE,
#endif /* JAVA_SPEC_VERSION >= 19 */

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD | J9JVMTI_GETVMTHREAD_ERROR_ON_VIRTUALTHREAD);
if (rc == JVMTI_ERROR_NONE) {
rv_threadid = (jlong) omrthread_get_osId(targetThread->osThread);
releaseVMThread(currentThread, targetThread, thread);
Expand Down Expand Up @@ -1524,7 +1525,9 @@ jvmtiGetStackTraceExtended(jvmtiEnv* env, ...)
ENSURE_NON_NULL(frame_buffer);
ENSURE_NON_NULL(count_ptr);

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD);
if (rc == JVMTI_ERROR_NONE) {
vm->internalVMFunctions->haltThreadForInspection(currentThread, targetThread);

Expand Down Expand Up @@ -3455,10 +3458,11 @@ jvmtiGetJ9vmThread(jvmtiEnv *env, ...)
vm->internalVMFunctions->internalEnterVMFromJNI(currentThread);

ENSURE_PHASE_START_OR_LIVE(env);
ENSURE_JTHREAD_NON_NULL(thread);
ENSURE_NON_NULL(vmThreadPtr);

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD);
if (rc == JVMTI_ERROR_NONE) {
rv_vmThread = targetThread;
releaseVMThread(currentThread, targetThread, thread);
Expand Down
14 changes: 3 additions & 11 deletions runtime/jvmti/jvmtiForceEarlyReturn.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,10 @@ jvmtiForceEarlyReturn(jvmtiEnv* env,

ENSURE_PHASE_LIVE(env);
ENSURE_CAPABILITY(env, can_force_early_return);

/* Check if the jthread is really a j.l.Thread. a NULL jthread indicates that
* the user wants to use the current thread hence defer the assignment to getVMThread */

if (NULL != thread) {
ENSURE_JTHREAD(currentThread, thread);
#if JAVA_SPEC_VERSION >= 19
ENSURE_JTHREAD_NOT_VIRTUAL(currentThread, thread, JVMTI_ERROR_OPAQUE_FRAME);
#endif /* JAVA_SPEC_VERSION >= 19 */
}

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_OPAQUE_FRAME,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD | J9JVMTI_GETVMTHREAD_ERROR_ON_VIRTUALTHREAD);
if (rc == JVMTI_ERROR_NONE) {
/* Does this thread need to be suspended at an event? */
vm->internalVMFunctions->haltThreadForInspection(currentThread, targetThread);
Expand Down
59 changes: 41 additions & 18 deletions runtime/jvmti/jvmtiHelpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ static UDATA watchedClassEqual (void *lhsEntry, void *rhsEntry, void *userData);


jvmtiError
getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr, UDATA allowNull, UDATA mustBeAlive)
getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr, jvmtiError vThreadError, UDATA flags)
{
J9JavaVM *vm = currentThread->javaVM;
j9object_t threadObject = NULL;
Expand All @@ -106,13 +106,30 @@ getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr,
#endif /* JAVA_SPEC_VERSION >= 19 */

if (NULL == thread) {
if (allowNull) {
*vmThreadPtr = currentThread;
return JVMTI_ERROR_NONE;
if (OMR_ARE_ANY_BITS_SET(flags, J9JVMTI_GETVMTHREAD_ERROR_ON_NULL_JTHREAD)) {
return JVMTI_ERROR_INVALID_THREAD;
}
#if JAVA_SPEC_VERSION >= 19
if (OMR_ARE_ANY_BITS_SET(flags, J9JVMTI_GETVMTHREAD_ERROR_ON_VIRTUALTHREAD)
&& IS_JAVA_LANG_VIRTUALTHREAD(currentThread, currentThread->threadObject)
) {
return vThreadError;
}
return JVMTI_ERROR_INVALID_THREAD;
#endif /* JAVA_SPEC_VERSION >= 19 */
*vmThreadPtr = currentThread;
return JVMTI_ERROR_NONE;
} else {
threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
if (!IS_JAVA_LANG_THREAD(currentThread, threadObject)) {
return JVMTI_ERROR_INVALID_THREAD;
}
#if JAVA_SPEC_VERSION >= 19
if (OMR_ARE_ANY_BITS_SET(flags, J9JVMTI_GETVMTHREAD_ERROR_ON_VIRTUALTHREAD)
&& IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObject)
) {
return vThreadError;
}
#endif /* JAVA_SPEC_VERSION >= 19 */
if (currentThread->threadObject == threadObject) {
*vmThreadPtr = currentThread;
return JVMTI_ERROR_NONE;
Expand All @@ -122,7 +139,7 @@ getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr,
/* Make sure the vmThread stays alive while it is being used. */
omrthread_monitor_enter(vm->vmThreadListMutex);
#if JAVA_SPEC_VERSION >= 19
isVirtualThread = IS_VIRTUAL_THREAD(currentThread, threadObject);
isVirtualThread = IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObject);
if (isVirtualThread) {
omrthread_monitor_enter(vm->liveVirtualThreadListMutex);

Expand All @@ -148,7 +165,7 @@ getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr,
}

if (!isThreadAlive) {
if (mustBeAlive) {
if (OMR_ARE_ANY_BITS_SET(flags, J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD)) {
#if JAVA_SPEC_VERSION >= 19
if (isVirtualThread) {
omrthread_monitor_exit(vm->liveVirtualThreadListMutex);
Expand All @@ -174,8 +191,9 @@ getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr,
omrthread_monitor_exit(vm->vmThreadListMutex);

#if JAVA_SPEC_VERSION >= 19
if (mustBeAlive) {
Assert_JVMTI_true((NULL != targetThread) || isVirtualThread);
if (isThreadAlive && !isVirtualThread) {
/* targetThread should not be NULL for alive non-virtual threads. */
Assert_JVMTI_true(NULL != targetThread);
}
#endif /* JAVA_SPEC_VERSION >= 19 */

Expand All @@ -190,7 +208,7 @@ releaseVMThread(J9VMThread *currentThread, J9VMThread *targetThread, jthread thr
#if JAVA_SPEC_VERSION >= 19
if (NULL != thread) {
j9object_t threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
if ((currentThread->threadObject != threadObject) && IS_VIRTUAL_THREAD(currentThread, threadObject)) {
if ((currentThread->threadObject != threadObject) && IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObject)) {
J9JavaVM *vm = currentThread->javaVM;
I_64 vthreadInspectorCount = 0;
/* Release the virtual thread (allow it to die) now that we are no longer inspecting it. */
Expand Down Expand Up @@ -788,7 +806,10 @@ getVirtualThreadState(J9VMThread *currentThread, jthread thread)
J9VMThread *targetThread = NULL;
Assert_JVMTI_notNull(thread);
Assert_JVMTI_mustHaveVMAccess(currentThread);
if (JVMTI_ERROR_NONE == getVMThread(currentThread, thread, &targetThread, FALSE, FALSE)) {
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_NULL_JTHREAD);
if (JVMTI_ERROR_NONE == rc) {
if (NULL != targetThread) {
vm->internalVMFunctions->haltThreadForInspection(currentThread, targetThread);
rc = getThreadState(currentThread, targetThread->carrierThreadObject);
Expand Down Expand Up @@ -1604,7 +1625,9 @@ setEventNotificationMode(J9JVMTIEnv * j9env, J9VMThread * currentThread, jint mo
} else {
j9object_t threadObject = J9_JNI_UNWRAP_REFERENCE(event_thread);
J9VMThread *vmThreadForTLS = NULL;
rc = getVMThread(currentThread, event_thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, event_thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD);
if (rc != JVMTI_ERROR_NONE) {
goto done;
}
Expand All @@ -1616,10 +1639,10 @@ setEventNotificationMode(J9JVMTIEnv * j9env, J9VMThread * currentThread, jint mo
goto done;
}
if (NULL == targetThread) {
/* targetThread is NULL only for virtual threads, as per the assertion in getVMThread,
* when mustBeAlive is TRUE. vmThreadForTLS is only used to acquire J9JavaVM in
* createThreadData and jvmtiTLSGet. If targetThread is NULL, currentThread is passed
* to createThreadData and jvmtiTLSGet for retrieving J9JavaVM in JDK19+.
/* targetThread is NULL only for virtual threads, as per the assertion in getVMThread.
* vmThreadForTLS is only used to acquire J9JavaVM in createThreadData and jvmtiTLSGet.
* If targetThread is NULL, currentThread is passed to createThreadData and jvmtiTLSGet
* for retrieving J9JavaVM in JDK19+.
*/
vmThreadForTLS = currentThread;
}
Expand Down Expand Up @@ -1915,7 +1938,7 @@ genericWalkStackFramesHelper(J9VMThread *currentThread, J9VMThread *targetThread
UDATA rc = J9_STACKWALK_RC_NONE;

#if JAVA_SPEC_VERSION >= 19
if (IS_VIRTUAL_THREAD(currentThread, threadObject)) {
if (IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObject)) {
if (NULL != targetThread) {
walkState->walkThread = targetThread;
rc = vm->walkStackFrames(currentThread, walkState);
Expand Down Expand Up @@ -1947,7 +1970,7 @@ J9VMContinuation *
getJ9VMContinuationToWalk(J9VMThread *currentThread, J9VMThread *targetThread, j9object_t threadObject)
{
J9VMContinuation *continuation = NULL;
if (IS_VIRTUAL_THREAD(currentThread, threadObject)) {
if (IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObject)) {
if (NULL == targetThread) {
/* An unmounted virtual thread will have a valid J9VMContinuation. */
j9object_t contObject = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObject);
Expand Down
4 changes: 3 additions & 1 deletion runtime/jvmti/jvmtiLocalVariable.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,9 @@ jvmtiGetOrSetLocal(jvmtiEnv *env,
J9VMThread *targetThread = NULL;

vm->internalVMFunctions->internalEnterVMFromJNI(currentThread);
rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD);
if (rc == JVMTI_ERROR_NONE) {
J9StackWalkState walkState = {0};
BOOLEAN objectFetched = FALSE;
Expand Down
36 changes: 20 additions & 16 deletions runtime/jvmti/jvmtiStackFrame.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ jvmtiGetStackTrace(jvmtiEnv* env,
ENSURE_NON_NULL(frame_buffer);
ENSURE_NON_NULL(count_ptr);

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD);
if (rc == JVMTI_ERROR_NONE) {
j9object_t threadObject = (NULL == thread) ? currentThread->threadObject : J9_JNI_UNWRAP_REFERENCE(thread);
#if JAVA_SPEC_VERSION >= 19
Expand Down Expand Up @@ -216,9 +218,9 @@ jvmtiGetThreadListStackTraces(jvmtiEnv* env,
while (0 != thread_count) {
jthread thread = *thread_list;

if ((NULL != thread) && IS_VIRTUAL_THREAD(currentThread, J9_JNI_UNWRAP_REFERENCE(thread))) {
if ((NULL != thread) && IS_JAVA_LANG_VIRTUALTHREAD(currentThread, J9_JNI_UNWRAP_REFERENCE(thread))) {
J9VMThread *targetThread = NULL;
getVMThread(currentThread, thread, &targetThread, TRUE, FALSE);
getVMThread(currentThread, thread, &targetThread, JVMTI_ERROR_NONE, 0);
}
++thread_list;
--thread_count;
Expand Down Expand Up @@ -254,13 +256,13 @@ jvmtiGetThreadListStackTraces(jvmtiEnv* env,
}

threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
if (!isSameOrSuperClassOf(J9VMJAVALANGTHREAD_OR_NULL(vm), J9OBJECT_CLAZZ(currentThread, threadObject))) {
if (!IS_JAVA_LANG_THREAD(currentThread, threadObject)) {
rc = JVMTI_ERROR_INVALID_THREAD;
goto deallocate;
}

#if JAVA_SPEC_VERSION >= 19
if (IS_VIRTUAL_THREAD(currentThread, threadObject)) {
if (IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObject)) {
isVirtual = TRUE;
j9object_t carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(currentThread, threadObject);
jint vthreadState = J9VMJAVALANGVIRTUALTHREAD_STATE(currentThread, threadObject);
Expand Down Expand Up @@ -323,7 +325,7 @@ jvmtiGetThreadListStackTraces(jvmtiEnv* env,

if (NULL != thread) {
j9object_t threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
if (IS_VIRTUAL_THREAD(currentThread, threadObject)) {
if (IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObject)) {
J9VMThread *targetThread = NULL;
j9object_t carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(currentThread, threadObject);
if (NULL != carrierThread) {
Expand Down Expand Up @@ -371,7 +373,9 @@ jvmtiGetFrameCount(jvmtiEnv* env,

ENSURE_NON_NULL(count_ptr);

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD);
if (rc == JVMTI_ERROR_NONE) {
j9object_t threadObject = (NULL == thread) ? currentThread->threadObject : J9_JNI_UNWRAP_REFERENCE(thread);
J9StackWalkState walkState;
Expand Down Expand Up @@ -434,13 +438,9 @@ jvmtiPopFrame(jvmtiEnv* env,
ENSURE_PHASE_LIVE(env);
ENSURE_CAPABILITY(env, can_pop_frame);

#if JAVA_SPEC_VERSION >= 19
if (NULL != thread) {
ENSURE_JTHREAD_NOT_VIRTUAL(currentThread, thread, JVMTI_ERROR_OPAQUE_FRAME);
}
#endif /* JAVA_SPEC_VERSION >= 19 */

rc = getVMThread(currentThread, thread, &targetThread, FALSE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_OPAQUE_FRAME,
J9JVMTI_GETVMTHREAD_ERROR_ON_NULL_JTHREAD | J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD | J9JVMTI_GETVMTHREAD_ERROR_ON_VIRTUALTHREAD);
if (rc == JVMTI_ERROR_NONE) {
/* Does this thread need to be suspended at an event? */
vm->internalVMFunctions->haltThreadForInspection(currentThread, targetThread);
Expand Down Expand Up @@ -500,7 +500,9 @@ jvmtiGetFrameLocation(jvmtiEnv *env,
ENSURE_NON_NULL(method_ptr);
ENSURE_NON_NULL(location_ptr);

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD);
if (rc == JVMTI_ERROR_NONE) {
j9object_t threadObject = (NULL == thread) ? currentThread->threadObject : J9_JNI_UNWRAP_REFERENCE(thread);
J9StackWalkState walkState = {0};
Expand Down Expand Up @@ -574,7 +576,9 @@ jvmtiNotifyFramePop(jvmtiEnv *env,

ENSURE_NON_NEGATIVE(depth);

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
rc = getVMThread(
currentThread, thread, &targetThread, JVMTI_ERROR_NONE,
J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD);
if (JVMTI_ERROR_NONE == rc) {
#if JAVA_SPEC_VERSION >= 19
BOOLEAN isVThreadSuspended = FALSE;
Expand Down

0 comments on commit 2d9d132

Please sign in to comment.