Skip to content

Commit

Permalink
Loom: GC Thread scanning
Browse files Browse the repository at this point in the history
Threads should be scanned as they normally would. If a thread is mounted
with a VirtualThread, then the virtual thread stack will be scanned, the
carrier thread stack will be stored in a continuation instance.

currentContinuation field of the J9vmThread point to either NULL or the
continuation with carrier thread stack(mounting with a VirtualThread
case). scanning currentContinuation if needed.

Signed-off-by: Lin Hu <linhu@ca.ibm.com>
  • Loading branch information
LinHu2016 committed Sep 27, 2022
1 parent 02c32d0 commit 26a25f9
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 47 deletions.
14 changes: 13 additions & 1 deletion runtime/gc_base/RootScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,19 @@ MM_RootScanner::scanOneThread(MM_EnvironmentBase *env, J9VMThread* walkThread, v
doVMThreadSlot(slot, &vmThreadIterator);
}

GC_VMThreadStackSlotIterator::scanSlots((J9VMThread *)env->getOmrVMThread()->_language_vmthread, walkThread, localData, stackSlotIterator, isStackFrameClassWalkNeeded(), _trackVisibleStackFrameDepth);
J9VMThread *currentThread = (J9VMThread *)env->getOmrVMThread()->_language_vmthread;
/* In a case this thread is a carrier thread, and a virtual thread is mounted, we will scan virtual thread's stack.
* If virtual thread is not mounted, or this is just a regular thread, this will scan its own stack. */
GC_VMThreadStackSlotIterator::scanSlots(currentThread, walkThread, localData, stackSlotIterator, isStackFrameClassWalkNeeded(), _trackVisibleStackFrameDepth);

#if JAVA_SPEC_VERSION >= 19
if (NULL != walkThread->currentContinuation)
{
/* At this point we know that a virtual thread is mounted. We previously scanned its stack,
* and now we will scan carrier's stack, that continuation struct is currently pointing to. */
GC_VMThreadStackSlotIterator::scanSlots(currentThread, walkThread->currentContinuation, localData, stackSlotIterator, isStackFrameClassWalkNeeded(), _trackVisibleStackFrameDepth);
}
#endif /* JAVA_SPEC_VERSION >= 19 */
return false;
}

Expand Down
7 changes: 7 additions & 0 deletions runtime/gc_glue_java/ConcurrentMarkingDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,15 @@ MM_ConcurrentMarkingDelegate::scanThreadRoots(MM_EnvironmentBase *env)
markSchemeStackIteratorData localData;
localData.markingScheme = _markingScheme;
localData.env = env;
/* In a case this thread is a carrier thread, and a virtual thread is mounted, we will scan virtual thread's stack. */
GC_VMThreadStackSlotIterator::scanSlots(vmThread, vmThread, (void *)&localData, concurrentStackSlotIterator, true, false);

#if JAVA_SPEC_VERSION >= 19
if (NULL != vmThread->currentContinuation) {
GC_VMThreadStackSlotIterator::scanSlots(vmThread, vmThread->currentContinuation, (void *)&localData, concurrentStackSlotIterator, true, false);
}
#endif /* JAVA_SPEC_VERSION >= 19 */

return true;
}

Expand Down
102 changes: 56 additions & 46 deletions runtime/gc_structs/VMThreadStackSlotIterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,42 @@ vmThreadStackFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkSt

} /* extern "C" */

void
GC_VMThreadStackSlotIterator::initializeStackWalkState(
J9StackWalkState *stackWalkState,
J9VMThread *vmThread,
void *userData,
J9MODRON_OSLOTITERATOR *oSlotIterator,
bool includeStackFrameClassReferences,
bool trackVisibleFrameDepth
)
{
J9JavaVM *vm = vmThread->javaVM;

stackWalkState->objectSlotWalkFunction = vmThreadStackDoOSlotIterator;
stackWalkState->userData1 = (void *)oSlotIterator;
stackWalkState->userData2 = (void *)vm;
stackWalkState->userData3 = userData;

stackWalkState->flags = J9_STACKWALK_ITERATE_O_SLOTS | J9_STACKWALK_DO_NOT_SNIFF_AND_WHACK;
stackWalkState->walkThread = NULL;

if (trackVisibleFrameDepth) {
stackWalkState->skipCount = 0;
stackWalkState->flags |= J9_STACKWALK_VISIBLE_ONLY;
} else {
if (NULL != vm->collectJitPrivateThreadData) {
stackWalkState->frameWalkFunction = vmThreadStackFrameIterator;
stackWalkState->flags |= J9_STACKWALK_ITERATE_FRAMES;
}
stackWalkState->flags |= J9_STACKWALK_SKIP_INLINES;
}

if (includeStackFrameClassReferences) {
stackWalkState->flags |= J9_STACKWALK_ITERATE_METHOD_CLASS_SLOTS;
}

}
/**
* Walk all slots of the walk thread which contain object references.
* For every object slot found in <code>walkThread</code> call the <code>oSlotIterator</code> function.
Expand All @@ -87,32 +123,10 @@ GC_VMThreadStackSlotIterator::scanSlots(
)
{
J9StackWalkState stackWalkState;
J9JavaVM *vm = vmThread->javaVM;

stackWalkState.objectSlotWalkFunction = vmThreadStackDoOSlotIterator;
stackWalkState.userData1 = (void *)oSlotIterator;
stackWalkState.userData2 = (void *)vm;
stackWalkState.userData3 = userData;

stackWalkState.flags = J9_STACKWALK_ITERATE_O_SLOTS | J9_STACKWALK_DO_NOT_SNIFF_AND_WHACK;
initializeStackWalkState(&stackWalkState, vmThread, userData, oSlotIterator, includeStackFrameClassReferences, trackVisibleFrameDepth);
stackWalkState.walkThread = walkThread;

if (trackVisibleFrameDepth) {
stackWalkState.skipCount = 0;
stackWalkState.flags |= J9_STACKWALK_VISIBLE_ONLY;
} else {
if (NULL != vm->collectJitPrivateThreadData) {
stackWalkState.frameWalkFunction = vmThreadStackFrameIterator;
stackWalkState.flags |= J9_STACKWALK_ITERATE_FRAMES;
}
stackWalkState.flags |= J9_STACKWALK_SKIP_INLINES;
}

if (includeStackFrameClassReferences) {
stackWalkState.flags |= J9_STACKWALK_ITERATE_METHOD_CLASS_SLOTS;
}

vm->walkStackFrames(vmThread, &stackWalkState);
vmThread->javaVM->walkStackFrames(vmThread, &stackWalkState);
}

void
Expand All @@ -126,29 +140,25 @@ GC_VMThreadStackSlotIterator::scanSlots(
)
{
J9StackWalkState stackWalkState;
J9JavaVM *vm = vmThread->javaVM;
initializeStackWalkState(&stackWalkState, vmThread, userData, oSlotIterator, includeStackFrameClassReferences, trackVisibleFrameDepth);

stackWalkState.objectSlotWalkFunction = vmThreadStackDoOSlotIterator;
stackWalkState.userData1 = (void *)oSlotIterator;
stackWalkState.userData2 = (void *)vm;
stackWalkState.userData3 = userData;

stackWalkState.flags = J9_STACKWALK_ITERATE_O_SLOTS | J9_STACKWALK_DO_NOT_SNIFF_AND_WHACK;

if (trackVisibleFrameDepth) {
stackWalkState.skipCount = 0;
stackWalkState.flags |= J9_STACKWALK_VISIBLE_ONLY;
} else {
if (NULL != vm->collectJitPrivateThreadData) {
stackWalkState.frameWalkFunction = vmThreadStackFrameIterator;
stackWalkState.flags |= J9_STACKWALK_ITERATE_FRAMES;
}
stackWalkState.flags |= J9_STACKWALK_SKIP_INLINES;
}
VM_VMHelpers::walkContinuationStackFramesWrapper(vmThread, continuationObjectPtr, &stackWalkState);
}

if (includeStackFrameClassReferences) {
stackWalkState.flags |= J9_STACKWALK_ITERATE_METHOD_CLASS_SLOTS;
}
#if JAVA_SPEC_VERSION >= 19
void
GC_VMThreadStackSlotIterator::scanSlots(
J9VMThread *vmThread,
J9VMContinuation *continuation,
void *userData,
J9MODRON_OSLOTITERATOR *oSlotIterator,
bool includeStackFrameClassReferences,
bool trackVisibleFrameDepth
)
{
J9StackWalkState stackWalkState;
initializeStackWalkState(&stackWalkState, vmThread, userData, oSlotIterator, includeStackFrameClassReferences, trackVisibleFrameDepth);

VM_VMHelpers::walkContinuationStackFramesWrapper(vmThread, continuationObjectPtr, &stackWalkState);
vmThread->javaVM->internalVMFunctions->walkContinuationStackFrames(vmThread, continuation, &stackWalkState);
}
#endif /* JAVA_SPEC_VERSION >= 19 */
18 changes: 18 additions & 0 deletions runtime/gc_structs/VMThreadStackSlotIterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ typedef void J9MODRON_OSLOTITERATOR(J9JavaVM *javaVM, J9Object **objectIndirect,
*/
class GC_VMThreadStackSlotIterator
{
private:
static void initializeStackWalkState(
J9StackWalkState *stackWalkState,
J9VMThread *vmThread,
void *userData,
J9MODRON_OSLOTITERATOR *oSlotIterator,
bool includeStackFrameClassReferences,
bool trackVisibleFrameDepth);
public:
static void scanSlots(
J9VMThread *vmThread,
Expand All @@ -59,6 +67,16 @@ class GC_VMThreadStackSlotIterator
J9MODRON_OSLOTITERATOR *oSlotIterator,
bool includeStackFrameClassReferences,
bool trackVisibleFrameDepth);

#if JAVA_SPEC_VERSION >= 19
static void scanSlots(
J9VMThread *vmThread,
J9VMContinuation *continuation,
void *userData,
J9MODRON_OSLOTITERATOR *oSlotIterator,
bool includeStackFrameClassReferences,
bool trackVisibleFrameDepth);
#endif /* JAVA_SPEC_VERSION >= 19 */
};

#endif /* VMTHREADSTACKSLOTITERATOR_HPP_ */
Expand Down

0 comments on commit 26a25f9

Please sign in to comment.