Skip to content

Commit

Permalink
Refactor getStackTraceImpl to remove use of VThreadInspector
Browse files Browse the repository at this point in the history
Signed-off-by: Jack Lu <[email protected]>
  • Loading branch information
fengxue-IS committed May 4, 2023
1 parent 7977a21 commit 9581f21
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 46 deletions.
46 changes: 35 additions & 11 deletions runtime/jcl/common/getstacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,33 +48,55 @@ getStackTraceForThread(J9VMThread *currentThread, J9VMThread *targetThread, UDAT
j9object_t throwable = NULL;
J9StackWalkState walkState = {0};
UDATA rc = J9_STACKWALK_RC_NONE;

#if JAVA_SPEC_VERSION >= 19
J9VMContinuation *continuation = targetThread->currentContinuation;
BOOLEAN isVirtual = IS_JAVA_LANG_VIRTUALTHREAD(currentThread, threadObject);
if (isVirtual) {
/* Return NULL if a valid CarrierThread object cannot be found through VirtualThread object,
* the caller of getStackTraceImpl will handle whether to retry or get the stack using the unmounted path.
*/
j9object_t carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(currentThread, threadObject);
/* Ensure the VirtualThread is mounted and not during transition. */
if (NULL == carrierThread) {
goto done;
}
/* Gets targetThread from the carrierThread object. */
targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, carrierThread);
Assert_JCL_notNull(targetThread);
}
PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, threadObject);
#endif /* JAVA_SPEC_VERSION >= 19 */
/* Halt the target thread */
/* Halt the target thread. */
vmfns->haltThreadForInspection(currentThread, targetThread);

/* walk stack and cache PCs */
/* walk stack and cache PCs. */
walkState.flags = J9_STACKWALK_CACHE_PCS | J9_STACKWALK_WALK_TRANSLATE_PC | J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_VISIBLE_ONLY;
#if JAVA_SPEC_VERSION >= 19
if ((NULL != continuation) && (threadObject != targetThread->threadObject)) {
/* If targetThread has a continuation mounted and its current threadObject doesn't match the
* target threadObject, then the carrier thread's stacktrace is retrieved through the cached
* state in the continuation.
threadObject = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);
/* Re-check thread state. */
if ((NULL != targetThread->currentContinuation) && (threadObject == targetThread->carrierThreadObject)) {
/* If targetThread has a continuation mounted and its threadObject matches its carrierThreadObject,
* then the carrier thread's stacktrace is retrieved through the cached state in the continuation.
*/
walkState.skipCount = 0;
rc = vmfns->walkContinuationStackFrames(currentThread, continuation, &walkState);
rc = vmfns->walkContinuationStackFrames(currentThread, targetThread->currentContinuation, &walkState);
} else if (isVirtual && (threadObject != targetThread->threadObject)) {
/* If the virtual thread object doesn't match the current thread object, it must have unmounted
* from this carrier thread, return NULL and the JCL code will handle the retry.
*/
vmfns->resumeThreadForInspection(currentThread, targetThread);
goto done;
} else
#endif /* JAVA_SPEC_VERSION >= 19 */
{
walkState.walkThread = targetThread;
walkState.skipCount = skipCount;
rc = vm->walkStackFrames(currentThread, &walkState);
}
/* Now that the stack trace has been copied, resume the thread */
/* Now that the stack trace has been copied, resume the thread. */
vmfns->resumeThreadForInspection(currentThread, targetThread);

/* Check for stack walk failure */
/* Check for stack walk failure. */
if (rc != J9_STACKWALK_RC_NONE) {
vmfns->setNativeOutOfMemoryError(currentThread, 0, 0);
goto fail;
Expand All @@ -84,7 +106,9 @@ getStackTraceForThread(J9VMThread *currentThread, J9VMThread *targetThread, UDAT

fail:
vmfns->freeStackWalkCaches(currentThread, &walkState);

#if JAVA_SPEC_VERSION >= 19
done:
#endif /* JAVA_SPEC_VERSION >= 19 */
/* Return the result - any pending exception will be checked by the caller and the result discarded */
return throwable;
}
Expand Down
39 changes: 4 additions & 35 deletions runtime/jcl/common/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,45 +336,14 @@ Java_java_lang_Thread_getStackTraceImpl(JNIEnv *env, jobject rcv)
/* Assume the thread is alive (guaranteed by java caller). */
J9VMThread *targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, receiverObject);

#if JAVA_SPEC_VERSION >= 19
BOOLEAN releaseInspector = FALSE;
if (IS_JAVA_LANG_VIRTUALTHREAD(currentThread, receiverObject)) {
/* Do not spin when acquiring access, if acquire failed, return NULL.
* The caller of getStackTraceImpl will handle if should retry or get stack using unmounted path.
*/
if (!vmFuncs->acquireVThreadInspector(currentThread, rcv, FALSE)) {
goto done;
}
j9object_t carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(currentThread, receiverObject);
/* Ensure virtual thread is mounted and not during transition. */
if (NULL != carrierThread) {
releaseInspector = TRUE;
} else {
vmFuncs->releaseVThreadInspector(currentThread, rcv);
goto done;
}
/* Gets targetThread from the carrierThread object. */
targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, carrierThread);
Assert_JCL_notNull(targetThread);
}
{
#endif /* JAVA_SPEC_VERSION >= 19 */
/* If calling getStackTrace on the current Thread, drop the first element, which is this method. */
UDATA skipCount = (currentThread == targetThread) ? 1 : 0;

/* If calling getStackTrace on the current Thread, drop the first element, which is this method. */
UDATA skipCount = (currentThread == targetThread) ? 1 : 0;
j9object_t resultObject = getStackTraceForThread(currentThread, targetThread, skipCount, receiverObject);

j9object_t resultObject = getStackTraceForThread(currentThread, targetThread, skipCount, receiverObject);
if (NULL != resultObject) {
result = vmFuncs->j9jni_createLocalRef(env, resultObject);

#if JAVA_SPEC_VERSION >= 19
}
if (releaseInspector) {
receiverObject = J9_JNI_UNWRAP_REFERENCE(rcv);
/* Release the virtual thread (allow it to die) now that we are no longer inspecting it. */
vmFuncs->releaseVThreadInspector(currentThread, rcv);
}
done:
#endif /* JAVA_SPEC_VERSION >= 19 */

vmFuncs->internalExitVMToJNI(currentThread);
return result;
Expand Down

0 comments on commit 9581f21

Please sign in to comment.