Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix stackwalk related jvmti functions #15872

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions runtime/jvmti/jvmtiHelpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1809,3 +1809,37 @@ jvmtiTLSGet(J9VMThread *vmThread, j9object_t thread, UDATA key)
return (J9JVMTIThreadData *)omrthread_tls_get(vmThread->osThread, key);
#endif /* JAVA_SPEC_VERSION >= 19 */
}

UDATA
genericWalkStackFramesHelper(J9VMThread *currentThread, J9VMThread *targetThread, j9object_t threadObject, J9StackWalkState *walkState)
{
J9JavaVM *vm = currentThread->javaVM;
UDATA rc = J9_STACKWALK_RC_NONE;

#if JAVA_SPEC_VERSION >= 19
if (IS_VIRTUAL_THREAD(currentThread, threadObject)) {
if (NULL != targetThread) {
walkState->walkThread = targetThread;
rc = vm->walkStackFrames(currentThread, walkState);
} else {
j9object_t contObject = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObject);
J9VMContinuation *continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, contObject);
vm->internalVMFunctions->walkContinuationStackFrames(currentThread, continuation, walkState);
}
} else
#endif /* JAVA_SPEC_VERSION >= 19 */
{
#if JAVA_SPEC_VERSION >= 19
J9VMContinuation *currentContinuation = targetThread->currentContinuation;
if (NULL != currentContinuation) {
rc = vm->internalVMFunctions->walkContinuationStackFrames(currentThread, currentContinuation, walkState);
} else
#endif /* JAVA_SPEC_VERSION >= 19 */
{
walkState->walkThread = targetThread;
rc = vm->walkStackFrames(currentThread, walkState);
}
}

return rc;
}
90 changes: 34 additions & 56 deletions runtime/jvmti/jvmtiStackFrame.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@
static UDATA popFrameCheckIterator (J9VMThread * currentThread, J9StackWalkState * walkState);
static UDATA jvmtiInternalGetStackTraceIterator (J9VMThread * currentThread, J9StackWalkState * walkState);
static jvmtiError jvmtiInternalGetStackTrace(
jvmtiEnv *env, J9VMThread *currentThread, J9VMThread *targetThread,
#if JAVA_SPEC_VERSION >= 19
j9object_t continuationObject,
#endif /* JAVA_SPEC_VERSION >= 19 */
jvmtiEnv *env, J9VMThread *currentThread, J9VMThread *targetThread, j9object_t threadObject,
jint start_depth, UDATA max_frame_count, jvmtiFrameInfo *frame_buffer, jint *count_ptr);


Expand Down Expand Up @@ -63,23 +60,18 @@ jvmtiGetStackTrace(jvmtiEnv* env,

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
if (rc == JVMTI_ERROR_NONE) {
j9object_t threadObject = (NULL == thread) ? currentThread->threadObject : J9_JNI_UNWRAP_REFERENCE(thread);
#if JAVA_SPEC_VERSION >= 19
if (NULL == targetThread) {
j9object_t threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
j9object_t contObject = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObject);
rc = jvmtiInternalGetStackTrace(env, currentThread, NULL, contObject, start_depth, (UDATA) max_frame_count, frame_buffer, &rv_count);
} else
if (NULL != targetThread)
#endif /* JAVA_SPEC_VERSION >= 19 */
{
vmFuncs->haltThreadForInspection(currentThread, targetThread);

rc = jvmtiInternalGetStackTrace(
env, currentThread, targetThread,
}
rc = jvmtiInternalGetStackTrace(env, currentThread, targetThread, threadObject, start_depth, (UDATA) max_frame_count, frame_buffer, &rv_count);
#if JAVA_SPEC_VERSION >= 19
NULL,
if (NULL != targetThread)
#endif /* JAVA_SPEC_VERSION >= 19 */
start_depth, (UDATA) max_frame_count, frame_buffer, &rv_count);

{
vmFuncs->resumeThreadForInspection(currentThread, targetThread);
}
releaseVMThread(currentThread, targetThread, thread);
Expand Down Expand Up @@ -146,7 +138,9 @@ jvmtiGetAllStackTraces(jvmtiEnv* env,
currentThread,
targetThread,
#if JAVA_SPEC_VERSION >= 19
NULL,
targetThread->carrierThreadObject,
#else /* JAVA_SPEC_VERSION >= 19 */
targetThread->threadObject,
#endif /* JAVA_SPEC_VERSION >= 19 */
0,
(UDATA) max_frame_count,
Expand Down Expand Up @@ -247,9 +241,7 @@ jvmtiGetThreadListStackTraces(jvmtiEnv* env,
env,
currentThread,
targetThread,
#if JAVA_SPEC_VERSION >= 19
NULL,
#endif /* JAVA_SPEC_VERSION >= 19 */
threadObject,
0,
(UDATA) max_frame_count,
(void *) currentFrameInfo,
Expand Down Expand Up @@ -311,21 +303,22 @@ jvmtiGetFrameCount(jvmtiEnv* env,

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
if (rc == JVMTI_ERROR_NONE) {
j9object_t threadObject = (NULL == thread) ? currentThread->threadObject : J9_JNI_UNWRAP_REFERENCE(thread);
J9StackWalkState walkState;
walkState.flags = J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_VISIBLE_ONLY;
walkState.skipCount = 0;

#if JAVA_SPEC_VERSION >= 19
if (NULL == targetThread) {
j9object_t threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
j9object_t contObject = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObject);
vmFuncs->walkContinuationStackFrames(currentThread, contObject, &walkState);
} else
if (NULL != targetThread)
#endif /* JAVA_SPEC_VERSION >= 19 */
{
babsingh marked this conversation as resolved.
Show resolved Hide resolved
vmFuncs->haltThreadForInspection(currentThread, targetThread);
walkState.walkThread = targetThread;
vm->walkStackFrames(currentThread, &walkState);
}
genericWalkStackFramesHelper(currentThread, targetThread, threadObject, &walkState);
#if JAVA_SPEC_VERSION >= 19
if (NULL != targetThread)
#endif /* JAVA_SPEC_VERSION >= 19 */
{
vmFuncs->resumeThreadForInspection(currentThread, targetThread);
}

Expand Down Expand Up @@ -439,24 +432,26 @@ jvmtiGetFrameLocation(jvmtiEnv *env,

rc = getVMThread(currentThread, thread, &targetThread, TRUE, TRUE);
if (rc == JVMTI_ERROR_NONE) {
j9object_t threadObject = (NULL == thread) ? currentThread->threadObject : J9_JNI_UNWRAP_REFERENCE(thread);
J9StackWalkState walkState = {0};
walkState.flags = J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_COUNT_SPECIFIED | J9_STACKWALK_RECORD_BYTECODE_PC_OFFSET;
walkState.skipCount = (UDATA) depth;
walkState.maxFrames = 1;

#if JAVA_SPEC_VERSION >= 19
if (NULL == targetThread) {
j9object_t threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
j9object_t contObject = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, threadObject);
vmFuncs->walkContinuationStackFrames(currentThread, contObject, &walkState);
} else
if (NULL != targetThread)
#endif /* JAVA_SPEC_VERSION >= 19 */
{
vmFuncs->haltThreadForInspection(currentThread, targetThread);
walkState.walkThread = targetThread;
vm->walkStackFrames(currentThread, &walkState);
}
genericWalkStackFramesHelper(currentThread, targetThread, threadObject, &walkState);
#if JAVA_SPEC_VERSION >= 19
if (NULL != targetThread)
#endif /* JAVA_SPEC_VERSION >= 19 */
{
vmFuncs->resumeThreadForInspection(currentThread, targetThread);
}

if (1 == walkState.framesWalked) {
jmethodID methodID = getCurrentMethodID(currentThread, walkState.method);

Expand Down Expand Up @@ -639,28 +634,18 @@ jvmtiInternalGetStackTrace(
jvmtiEnv *env,
J9VMThread *currentThread,
J9VMThread *targetThread,
#if JAVA_SPEC_VERSION >= 19
j9object_t continuationObject,
#endif /* JAVA_SPEC_VERSION >= 19 */
j9object_t threadObject,
jint start_depth,
UDATA max_frame_count,
jvmtiFrameInfo *frame_buffer,
jint *count_ptr
) {
J9JavaVM *vm = JAVAVM_FROM_ENV(env);
jint *count_ptr)
{
J9StackWalkState walkState = {0};

walkState.flags = J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_VISIBLE_ONLY;
walkState.skipCount = 0;
if (NULL != targetThread) {
walkState.walkThread = targetThread;
vm->walkStackFrames(currentThread, &walkState);
}
#if JAVA_SPEC_VERSION >= 19
else if (NULL != continuationObject) {
vm->internalVMFunctions->walkContinuationStackFrames(currentThread, continuationObject, &walkState);
}
#endif /* JAVA_SPEC_VERSION >= 19 */

genericWalkStackFramesHelper(currentThread, targetThread, threadObject, &walkState);
if (start_depth == 0) {
/* This violates the spec, but matches JDK behaviour - allows querying an empty stack with start_depth == 0 */
walkState.skipCount = 0;
Expand All @@ -682,14 +667,7 @@ jvmtiInternalGetStackTrace(
walkState.userData1 = frame_buffer;
walkState.frameWalkFunction = jvmtiInternalGetStackTraceIterator;

if (NULL != targetThread) {
vm->walkStackFrames(currentThread, &walkState);
}
#if JAVA_SPEC_VERSION >= 19
else if (NULL != continuationObject) {
vm->internalVMFunctions->walkContinuationStackFrames(currentThread, continuationObject, &walkState);
}
#endif /* JAVA_SPEC_VERSION >= 19 */
genericWalkStackFramesHelper(currentThread, targetThread, threadObject, &walkState);
if (NULL == walkState.userData1) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
Expand Down
11 changes: 11 additions & 0 deletions runtime/jvmti/jvmti_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,17 @@ suspendAgentBreakpoint(J9VMThread * currentThread, J9JVMTIAgentBreakpoint * agen
UDATA
findDecompileInfo(J9VMThread *currentThread, J9VMThread *targetThread, UDATA depth, J9StackWalkState *walkState);

/**
* A helper to walk a platform thread or virtual thread
* @param[in] currentThread current thread
* @param[in] targetThread the thread to walk
* @param[in] threadObject the thread to walk
* @param[in] walkState a stack walk state
* @return 0 on success and non-zero on failure
*/
UDATA
genericWalkStackFramesHelper(J9VMThread *currentThread, J9VMThread *targetThread, j9object_t threadObject, J9StackWalkState *walkState);

/* ---------------- jvmtiHook.c ---------------- */

/**
Expand Down
3 changes: 2 additions & 1 deletion runtime/oti/VMHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2046,7 +2046,8 @@ class VM_VMHelpers
{
UDATA rc = J9_STACKWALK_RC_NONE;
#if JAVA_SPEC_VERSION >= 19
rc = vmThread->javaVM->internalVMFunctions->walkContinuationStackFrames(vmThread, continuationObject, walkState);
J9VMContinuation *continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF(vmThread, continuationObject);
rc = vmThread->javaVM->internalVMFunctions->walkContinuationStackFrames(vmThread, continuation, walkState);
#endif /* JAVA_SPEC_VERSION >= 19 */
return rc;
}
Expand Down
5 changes: 4 additions & 1 deletion runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ struct J9UpcallSigType;
struct J9UpcallMetaData;
struct J9UpcallNativeSignature;
#endif /* JAVA_SPEC_VERSION >= 16 */
#if JAVA_SPEC_VERSION >= 19
struct J9VMContinuation;
#endif /* JAVA_SPEC_VERSION >= 19 */

/* @ddr_namespace: map_to_type=J9CfrError */

Expand Down Expand Up @@ -4901,7 +4904,7 @@ typedef struct J9InternalVMFunctions {
U_8 * (JNICALL *native2InterpJavaUpcallStruct)(struct J9UpcallMetaData *data, void *argsListPointer);
#endif /* JAVA_SPEC_VERSION >= 16 */
#if JAVA_SPEC_VERSION >= 19
UDATA (*walkContinuationStackFrames)(struct J9VMThread *currentThread, j9object_t continuationObject, J9StackWalkState *walkState);
UDATA (*walkContinuationStackFrames)(struct J9VMThread *currentThread, struct J9VMContinuation *continuation, J9StackWalkState *walkState);
#endif /* JAVA_SPEC_VERSION >= 19 */
} J9InternalVMFunctions;

Expand Down
10 changes: 5 additions & 5 deletions runtime/oti/vm_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -4345,14 +4345,14 @@ jint
isPinnedContinuation(J9VMThread *currentThread);

/**
* @brief Walk the stackframes associated with Continuation object
* @brief Walk the stackframes associated with a continuation
*
* @param currentThread
* @param continuationObject
* @return UDATA
* @param currentThread current thread
* @param continuation the continuation to be walked
* @return 0 on success and non-zero on failure
*/
UDATA
walkContinuationStackFrames(J9VMThread *currentThread, j9object_t continuationObject, J9StackWalkState *walkState);
walkContinuationStackFrames(J9VMThread *currentThread, J9VMContinuation *continuation, J9StackWalkState *walkState);
babsingh marked this conversation as resolved.
Show resolved Hide resolved
#endif /* JAVA_SPEC_VERSION >= 19 */

/* ---------------- hookableAsync.c ---------------- */
Expand Down
3 changes: 1 addition & 2 deletions runtime/vm/ContinuationHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,11 @@ isPinnedContinuation(J9VMThread *currentThread)
}

UDATA
walkContinuationStackFrames(J9VMThread *currentThread, j9object_t continuationObject, J9StackWalkState *walkState)
walkContinuationStackFrames(J9VMThread *currentThread, J9VMContinuation *continuation, J9StackWalkState *walkState)
{
Assert_VM_notNull(currentThread);

UDATA rc = J9_STACKWALK_RC_NONE;
J9VMContinuation *continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, continuationObject);

if (NULL != continuation) {
J9VMThread stackThread = {0};
Expand Down