From fe4e1c2a5d34c2088bd206f8489a1399a30260c5 Mon Sep 17 00:00:00 2001 From: Jack Lu Date: Tue, 3 Sep 2024 01:04:42 -0400 Subject: [PATCH] Cache and fill in virtual thread object for jvmtiFollowReferences calls in ReferenceChainWalker Signed-off-by: Jack Lu --- runtime/gc_base/ReferenceChainWalker.cpp | 14 +++++++++++++- runtime/gc_base/ReferenceChainWalker.hpp | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/runtime/gc_base/ReferenceChainWalker.cpp b/runtime/gc_base/ReferenceChainWalker.cpp index b2b8752f192..403767569a4 100644 --- a/runtime/gc_base/ReferenceChainWalker.cpp +++ b/runtime/gc_base/ReferenceChainWalker.cpp @@ -88,6 +88,7 @@ j9gc_ext_reachable_objects_do( #endif /* J9VM_OPT_JVMTI */ referenceChainWalker.setTrackVisibleStackFrameDepth(0 != (walkFlags & J9_MU_WALK_TRACK_VISIBLE_FRAME_DEPTH)); referenceChainWalker.setPreindexInterfaceFields(0 != (walkFlags & J9_MU_WALK_PREINDEX_INTERFACE_FIELDS)); + referenceChainWalker.includeVThreadObject(); /* walker configuration complete. Scan objects... */ referenceChainWalker.scanReachableObjects(env); referenceChainWalker.tearDown(env); @@ -120,6 +121,7 @@ j9gc_ext_reachable_from_object_do( MM_ReferenceChainWalker referenceChainWalker(env, TEMP_RCW_STACK_SIZE, userCallback, userData); if (referenceChainWalker.initialize(env)) { referenceChainWalker.setPreindexInterfaceFields(0 != (walkFlags & J9_MU_WALK_PREINDEX_INTERFACE_FIELDS)); + referenceChainWalker.includeVThreadObject(); /* walker configuration complete. Scan objects... */ referenceChainWalker.scanReachableFromObject(env, objectPtr); referenceChainWalker.tearDown(env); @@ -401,7 +403,11 @@ MM_ReferenceChainWalker::scanContinuationNativeSlots(J9Object *objectPtr) if (MM_GCExtensions::needScanStacksForContinuationObject(currentThread, objectPtr, isConcurrentGC, isGlobalGC, beingMounted)) { StackIteratorData localData; localData.rootScanner = this; - +#if JAVA_SPEC_VERSION >= 19 + if (_includeVThreadObject) { + _vThreadObject = VM_ContinuationHelpers::getThreadObjectForContinuation(currentThread, NULL, objectPtr); + } +#endif /* JAVA_SPEC_VERSION >= 19 */ GC_VMThreadStackSlotIterator::scanContinuationSlots(currentThread, objectPtr, (void *)&localData, stackSlotIteratorForReferenceChainWalker, false, _trackVisibleStackFrameDepth); } } @@ -646,6 +652,12 @@ MM_ReferenceChainWalker::doStackSlot(J9Object **slotPtr, void *walkState, const /* Only report heap objects */ if (isHeapObject(slotValue) && !_heap->objectIsInGap(slotValue)) { +#if JAVA_SPEC_VERSION >= 19 + if (_includeVThreadObject && (NULL == ((J9StackWalkState *)walkState)->walkThread->threadObject)) { + /* Fill in the virtual thread object for jvmtiFollowReferences calls. */ + ((J9StackWalkState *)walkState)->walkThread->threadObject = _vThreadObject; + } +#endif /* JAVA_SPEC_VERSION >= 19 */ J9MM_StackSlotDescriptor stackSlotDescriptor = { ((J9StackWalkState *)walkState)->walkThread, (J9StackWalkState *)walkState }; if (J9_STACKWALK_SLOT_TYPE_JNI_LOCAL == ((J9StackWalkState *)walkState)->slotType) { doSlot(slotPtr, J9GC_ROOT_TYPE_JNI_LOCAL, -1, (J9Object *)&stackSlotDescriptor); diff --git a/runtime/gc_base/ReferenceChainWalker.hpp b/runtime/gc_base/ReferenceChainWalker.hpp index 6a9e2fece0f..90bb111d608 100644 --- a/runtime/gc_base/ReferenceChainWalker.hpp +++ b/runtime/gc_base/ReferenceChainWalker.hpp @@ -74,11 +74,16 @@ class MM_ReferenceChainWalker : public MM_RootScanner bool _isProcessingOverflow; /**< Set when the queue is currently processing the overflow */ bool _isTerminating; /**< Set when no more callbacks should be queued */ bool _shouldPreindexInterfaceFields; /**< if true, indexes interface fields of the class being visited before class and superclass fields, otherwise, returns them in the order they appear in an object instance (CMVC 142897) */ +#if JAVA_SPEC_VERSION >= 19 + bool _includeVThreadObject; /**< Set when VirtualThread object is needed by callback function. */ + J9Object *_vThreadObject; /**< Cached object ref of VirtualThread object. */ +#endif /* JAVA_SPEC_VERSION >= 19 */ MM_ReferenceChainWalkerMarkMap *_markMap; /**< Mark Map created for Reference Chain Walker */ MM_Heap *_heap; /**< Cached pointer to the heap */ void *_heapBase; /**< Cached value of the heap base */ void *_heapTop; /**< Cached value of the heap top */ + void clearQueue(); void pushObject(J9Object *obj); J9Object *popObject(); @@ -235,6 +240,10 @@ class MM_ReferenceChainWalker : public MM_RootScanner _isProcessingOverflow(false), _isTerminating(false), _shouldPreindexInterfaceFields(true), /* default to behaviour required for Java6/heap11 */ +#if JAVA_SPEC_VERSION >= 19 + _includeVThreadObject(false), + _vThreadObject(NULL), +#endif /* JAVA_SPEC_VERSION >= 19 */ _markMap(NULL), _heap(NULL), _heapBase(NULL), @@ -259,6 +268,9 @@ class MM_ReferenceChainWalker : public MM_RootScanner completeScan(); } +#if JAVA_SPEC_VERSION >= 19 + void includeVThreadObject() { _includeVThreadObject = true; } +#endif /* JAVA_SPEC_VERSION >= 19 */ /** * Added to support bi-modal interface indexing in JVMTI (CMVC 142897). * Detail: heap10 requires no pre-indexing in order to preserve Java5 behaviour but heap11 requires pre-indexing to pass a Java6 JCK