Skip to content

Commit cbe2b8c

Browse files
committed
GC update for supporting yield of pinned VirtualThread(JEP491)
In order to supporting yield of pinned VirtualThread a couple of heap references have been added in chain of continuation structures, GC need to maintain(scan/update) these references. 1, new ContunuationSlotIterator to iterate all of the references list of monitorRecord list of jniMonitorRecord vthread reference ContunuationSlotIterator also contains state and related vmThread state (can be state_monitor_records or state_vthread) for assert check in doContinuationSlot() (monitor_records can be non heap reference), vmThread is for retrieving related carrier context during rootscanning. 2, two new methods doSlot() and doContinuationSlot() are introduced doSlot() would handle basic processing, which can be shared between doContinuationSlot() and doStackSlot(). doContinuationSlot() would have condition check for heap reference and also get ContunuationSlotIterator as a parameter for the extra assert checks. 3, mounted continuations are scanned during rootscan/scanOneThread unmounted continuations are scanned during ContinuationNativeSlots 4, for doContinuationSlot in CopyForwardScheme case the reservingContext (numa node related) can be retrieved via ContunuationSlotIterator (carrier thread context) for root scanning phase, and retrieved via the region of related Continuation Object for heap scanning phase. Signed-off-by: lhu <linhu@ca.ibm.com>
1 parent 330959c commit cbe2b8c

31 files changed

+759
-113
lines changed

runtime/gc_base/ReferenceChainWalker.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232

3333
#include "ClassIteratorClassSlots.hpp"
3434
#include "ClassIteratorDeclarationOrder.hpp"
35+
#if JAVA_SPEC_VERSION >= 24
36+
#include "ContinuationSlotIterator.hpp"
37+
#endif /* JAVA_SPEC_VERSION >= 24 */
3538
#include "EnvironmentBase.hpp"
3639
#include "Forge.hpp"
3740
#include "GCExtensions.hpp"
@@ -418,6 +421,16 @@ MM_ReferenceChainWalker::scanContinuationNativeSlots(J9Object *objectPtr)
418421
}
419422
#endif /* JAVA_SPEC_VERSION >= 19 */
420423
GC_VMThreadStackSlotIterator::scanContinuationSlots(currentThread, objectPtr, (void *)&localData, stackSlotIteratorForReferenceChainWalker, false, _trackVisibleStackFrameDepth);
424+
425+
#if JAVA_SPEC_VERSION >= 24
426+
J9VMContinuation *continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, objectPtr);
427+
GC_ContinuationSlotIterator continuationSlotIterator(currentThread, continuation);
428+
429+
while (J9Object **slotPtr = continuationSlotIterator.nextSlot()) {
430+
doContinuationSlot(slotPtr, &continuationSlotIterator);
431+
}
432+
#endif /* JAVA_SPEC_VERSION >= 24 */
433+
421434
}
422435
}
423436

@@ -651,6 +664,31 @@ MM_ReferenceChainWalker::doVMClassSlot(J9Class *classPtr)
651664
doClassSlot(classPtr, J9GC_ROOT_TYPE_VM_CLASS_SLOT, -1, NULL);
652665
}
653666

667+
#if JAVA_SPEC_VERSION >= 24
668+
/**
669+
* @todo Provide function documentation
670+
*/
671+
void
672+
MM_ReferenceChainWalker::doContinuationSlot(J9Object **slotPtr, GC_ContinuationSlotIterator *continuationSlotIterator)
673+
{
674+
J9Object *slotValue = *slotPtr;
675+
/* Only report heap objects */
676+
if (isHeapObject(slotValue) && !_heap->objectIsInGap(slotValue)) {
677+
switch(continuationSlotIterator->getState()) {
678+
case GC_ContinuationSlotIterator::state_monitor_records:
679+
doSlot(slotPtr, J9GC_ROOT_TYPE_CONTINUATION_MONITOR, -1, NULL);
680+
break;
681+
case GC_ContinuationSlotIterator::state_vthread:
682+
doSlot(slotPtr, J9GC_ROOT_TYPE_CONTINUATION_VTHREAD, -1, NULL);
683+
break;
684+
default:
685+
doSlot(slotPtr, J9GC_ROOT_TYPE_UNKNOWN, -1, NULL);
686+
break;
687+
}
688+
}
689+
}
690+
#endif /* JAVA_SPEC_VERSION >= 24 */
691+
654692
/**
655693
* @todo Provide function documentation
656694
*/

runtime/gc_base/ReferenceChainWalker.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ class MM_ReferenceChainWalker : public MM_RootScanner
127127
virtual void doStringTableSlot(J9Object **slotPtr, GC_StringTableIterator *stringTableIterator);
128128
virtual void doVMClassSlot(J9Class *classPtr);
129129
virtual void doVMThreadSlot(J9Object **slotPtr, GC_VMThreadIterator *vmThreadIterator);
130+
#if JAVA_SPEC_VERSION >= 24
131+
virtual void doContinuationSlot(J9Object **slotPtr, GC_ContinuationSlotIterator *continuationSlotIterator);
132+
#endif /* JAVA_SPEC_VERSION >= 24 */
130133
virtual void doStackSlot(J9Object **slotPtr, void *walkState, const void* stackLocation);
131134
virtual void doSlot(J9Object **slotPtr);
132135
virtual void doClassSlot(J9Class *classPtr);

runtime/gc_base/RootScanner.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,20 @@ MM_RootScanner::doClassSlot(J9Class *classPtr)
356356
/* ignore class slots by default */
357357
}
358358

359+
#if JAVA_SPEC_VERSION >= 24
360+
/**
361+
* @todo Provide function documentation
362+
*/
363+
void
364+
MM_RootScanner::doContinuationSlot(J9Object **slotPtr, GC_ContinuationSlotIterator *continuationSlotIterator)
365+
{
366+
/* ensure that this isn't a slot pointing into the gap (only matters for split heap VMs) */
367+
if (!_extensions->heap->objectIsInGap(*slotPtr)) {
368+
doSlot(slotPtr);
369+
}
370+
}
371+
#endif /* JAVA_SPEC_VERSION >= 24 */
372+
359373
/**
360374
* @todo Provide function documentation
361375
*/
@@ -552,6 +566,14 @@ MM_RootScanner::scanOneThread(MM_EnvironmentBase *env, J9VMThread *walkThread, v
552566
/* At this point we know that a virtual thread is mounted. We previously scanned its stack,
553567
* and now we will scan carrier's stack, that continuation struct is currently pointing to. */
554568
GC_VMThreadStackSlotIterator::scanSlots(currentThread, walkThread, walkThread->currentContinuation, localData, stackSlotIterator, isStackFrameClassWalkNeeded(), _trackVisibleStackFrameDepth);
569+
#if JAVA_SPEC_VERSION >= 24
570+
GC_ContinuationSlotIterator continuationSlotIterator(walkThread, walkThread->currentContinuation);
571+
572+
while (J9Object **slot = continuationSlotIterator.nextSlot()) {
573+
/* do current continuation slot (mounted vthread case, the slot for saved carrier thread) */
574+
doContinuationSlot(slot, &continuationSlotIterator);
575+
}
576+
#endif /* JAVA_SPEC_VERSION >= 24 */
555577
}
556578
#endif /* JAVA_SPEC_VERSION >= 19 */
557579
return false;

runtime/gc_base/RootScanner.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535

3636
#include "BaseVirtual.hpp"
3737

38+
#if JAVA_SPEC_VERSION >= 24
39+
#include "ContinuationSlotIterator.hpp"
40+
#endif /* JAVA_SPEC_VERSION >= 24 */
3841
#include "EnvironmentBase.hpp"
3942
#include "GCExtensions.hpp"
4043
#include "JVMTIObjectTagTableIterator.hpp"
@@ -582,6 +585,10 @@ class MM_RootScanner : public MM_BaseVirtual
582585
virtual void doDoubleMappedObjectSlot(J9Object *objectPtr, struct J9PortVmemIdentifier *identifier);
583586
#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */
584587

588+
#if JAVA_SPEC_VERSION >= 24
589+
virtual void doContinuationSlot(J9Object **slotPtr, GC_ContinuationSlotIterator *continuationSlotIterator);
590+
#endif /* JAVA_SPEC_VERSION >= 24 */
591+
585592
/**
586593
* Called for each object stack slot. Subclasses may override.
587594
*

runtime/gc_glue_java/CompactSchemeFixupObject.cpp

+39-6
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,21 @@
2626
#include "objectdescription.h"
2727

2828
#include "CollectorLanguageInterfaceImpl.hpp"
29-
#include "EnvironmentStandard.hpp"
29+
#if JAVA_SPEC_VERSION >= 24
30+
#include "ContinuationSlotIterator.hpp"
31+
#endif /* JAVA_SPEC_VERSION >= 24 */
3032
#include "Debug.hpp"
33+
#include "EnvironmentStandard.hpp"
34+
#include "FlattenedContiguousArrayIterator.hpp"
3135
#include "HeapRegionIteratorStandard.hpp"
3236
#include "MixedObjectIterator.hpp"
3337
#include "ObjectAccessBarrier.hpp"
3438
#include "OwnableSynchronizerObjectBuffer.hpp"
35-
#include "VMHelpers.hpp"
3639
#include "ParallelDispatcher.hpp"
3740
#include "PointerContiguousArrayIterator.hpp"
38-
#include "FlattenedContiguousArrayIterator.hpp"
41+
#include "StackSlotValidator.hpp"
3942
#include "Task.hpp"
43+
#include "VMHelpers.hpp"
4044

4145
void
4246
MM_CompactSchemeFixupObject::fixupMixedObject(omrobjectptr_t objectPtr)
@@ -50,19 +54,38 @@ MM_CompactSchemeFixupObject::fixupMixedObject(omrobjectptr_t objectPtr)
5054
}
5155

5256
void
53-
MM_CompactSchemeFixupObject::doStackSlot(MM_EnvironmentBase *env, omrobjectptr_t fromObject, omrobjectptr_t *slot)
57+
MM_CompactSchemeFixupObject::doSlot(MM_EnvironmentBase *env, omrobjectptr_t fromObject, omrobjectptr_t *slotPtr)
58+
{
59+
*slotPtr = _compactScheme->getForwardingPtr(*slotPtr);
60+
}
61+
62+
#if JAVA_SPEC_VERSION >= 24
63+
void
64+
MM_CompactSchemeFixupObject::doContinuationSlot(MM_EnvironmentBase *env, omrobjectptr_t fromObject, omrobjectptr_t *slotPtr, GC_ContinuationSlotIterator *continuationSlotIterator)
5465
{
55-
*slot = _compactScheme->getForwardingPtr(*slot);
66+
if (isHeapObject(*slotPtr) && !_extensions->heap->objectIsInGap(*slotPtr)) {
67+
doSlot(env, fromObject, slotPtr);
68+
} else if (NULL != *slotPtr) {
69+
Assert_MM_true(GC_ContinuationSlotIterator::state_monitor_records == continuationSlotIterator->getState());
70+
}
5671
}
72+
#endif /* JAVA_SPEC_VERSION >= 24 */
5773

74+
void
75+
MM_CompactSchemeFixupObject::doStackSlot(MM_EnvironmentBase *env, omrobjectptr_t fromObject, omrobjectptr_t *slotPtr, J9StackWalkState *walkState, const void *stackLocation)
76+
{
77+
if (isHeapObject(*slotPtr) && !_extensions->heap->objectIsInGap(*slotPtr)) {
78+
doSlot(env, fromObject, slotPtr);
79+
}
80+
}
5881
/**
5982
* @todo Provide function documentation
6083
*/
6184
void
6285
stackSlotIteratorForCompactScheme(J9JavaVM *javaVM, J9Object **slotPtr, void *localData, J9StackWalkState *walkState, const void *stackLocation)
6386
{
6487
StackIteratorData4CompactSchemeFixupObject *data = (StackIteratorData4CompactSchemeFixupObject *)localData;
65-
data->compactSchemeFixupObject->doStackSlot(data->env, data->fromObject, slotPtr);
88+
data->compactSchemeFixupObject->doStackSlot(data->env, data->fromObject, slotPtr, walkState, stackLocation);
6689
}
6790

6891

@@ -85,6 +108,16 @@ MM_CompactSchemeFixupObject::fixupContinuationNativeSlots(MM_EnvironmentStandard
85108
localData.fromObject = objectPtr;
86109

87110
GC_VMThreadStackSlotIterator::scanContinuationSlots(currentThread, objectPtr, (void *)&localData, stackSlotIteratorForCompactScheme, false, false);
111+
112+
#if JAVA_SPEC_VERSION >= 24
113+
J9VMContinuation *continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, objectPtr);
114+
GC_ContinuationSlotIterator continuationSlotIterator(currentThread, continuation);
115+
116+
while (J9Object **slotPtr = continuationSlotIterator.nextSlot()) {
117+
doContinuationSlot(env, objectPtr, slotPtr, &continuationSlotIterator);
118+
}
119+
#endif /* JAVA_SPEC_VERSION >= 24 */
120+
88121
}
89122
}
90123

runtime/gc_glue_java/CompactSchemeFixupObject.hpp

+18-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
#include "CompactScheme.hpp"
3030
#include "GCExtensions.hpp"
3131

32+
#if JAVA_SPEC_VERSION >= 24
33+
class GC_ContinuationSlotIterator;
34+
#endif /* JAVA_SPEC_VERSION >= 24 */
35+
3236
class MM_CompactSchemeFixupObject {
3337
public:
3438
protected:
@@ -38,7 +42,11 @@ class MM_CompactSchemeFixupObject {
3842
MM_CompactScheme *_compactScheme;
3943
public:
4044

41-
void doStackSlot(MM_EnvironmentBase *env, omrobjectptr_t fromObject, omrobjectptr_t *slot);
45+
MMINLINE void doSlot(MM_EnvironmentBase *env, omrobjectptr_t fromObject, omrobjectptr_t *slotPtr);
46+
#if JAVA_SPEC_VERSION >= 24
47+
void doContinuationSlot(MM_EnvironmentBase *env, omrobjectptr_t fromObject, omrobjectptr_t *slotPtr, GC_ContinuationSlotIterator *continuationSlotIterator);
48+
#endif /* JAVA_SPEC_VERSION >= 24 */
49+
void doStackSlot(MM_EnvironmentBase *env, omrobjectptr_t fromObject, omrobjectptr_t *slotPtr, J9StackWalkState *walkState, const void *stackLocation);
4250
/**
4351
* Perform fixup for a single object
4452
* @param env[in] the current thread
@@ -82,6 +90,15 @@ class MM_CompactSchemeFixupObject {
8290
* @param object -- The object of type or subclass of java.util.concurrent.locks.AbstractOwnableSynchronizer.
8391
*/
8492
MMINLINE void addOwnableSynchronizerObjectInList(MM_EnvironmentBase *env, omrobjectptr_t objectPtr);
93+
94+
/**
95+
* Determine whether the object pointer is found within the heap proper.
96+
* @return Boolean indicating if the object pointer is within the heap boundaries.
97+
*/
98+
MMINLINE bool isHeapObject(J9Object *objectPtr)
99+
{
100+
return (_extensions->heap->getHeapBase() <= (uint8_t *)objectPtr) && (_extensions->heap->getHeapTop() > (uint8_t *)objectPtr);
101+
}
85102
};
86103

87104
typedef struct StackIteratorData4CompactSchemeFixupObject {

runtime/gc_glue_java/ConcurrentMarkingDelegate.cpp

+38-14
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
#include "AsyncCallbackHandler.hpp"
2626
#include "ClassLoaderIterator.hpp"
2727
#include "ConfigurationDelegate.hpp"
28+
#if JAVA_SPEC_VERSION >= 24
29+
#include "ContinuationSlotIterator.hpp"
30+
#endif /* JAVA_SPEC_VERSION >= 24 */
2831
#include "FinalizeListManager.hpp"
2932
#include "Heap.hpp"
3033
#include "HeapRegionDescriptorStandard.hpp"
@@ -35,6 +38,32 @@
3538
#include "VMInterface.hpp"
3639
#include "VMThreadListIterator.hpp"
3740

41+
void
42+
MM_ConcurrentMarkingDelegate::doSlot(MM_EnvironmentBase *env, omrobjectptr_t *slotPtr)
43+
{
44+
_markingScheme->markObject(env, *slotPtr);
45+
}
46+
47+
#if JAVA_SPEC_VERSION >= 24
48+
void
49+
MM_ConcurrentMarkingDelegate::doContinuationSlot(MM_EnvironmentBase *env, omrobjectptr_t *slotPtr, GC_ContinuationSlotIterator *continuationSlotIterator)
50+
{
51+
if (_markingScheme->isHeapObject(*slotPtr) && !env->getExtensions()->heap->objectIsInGap(*slotPtr)) {
52+
doSlot(env, slotPtr);
53+
} else if (NULL != *slotPtr) {
54+
Assert_MM_true(GC_ContinuationSlotIterator::state_monitor_records == continuationSlotIterator->getState());
55+
}
56+
}
57+
#endif /* JAVA_SPEC_VERSION >= 24 */
58+
59+
void
60+
MM_ConcurrentMarkingDelegate::doStackSlot(MM_EnvironmentBase *env, omrobjectptr_t *slotPtr, J9StackWalkState *walkState, const void *stackLocation)
61+
{
62+
omrobjectptr_t object = *slotPtr;
63+
if (_markingScheme->isHeapObject(object) && !env->getExtensions()->heap->objectIsInGap(object)) {
64+
doSlot(env, slotPtr);
65+
}
66+
}
3867
/**
3968
* Concurrents stack slot iterator.
4069
* Called for each slot in a threads active stack frames which contains a object reference.
@@ -48,19 +77,7 @@ void
4877
concurrentStackSlotIterator(J9JavaVM *javaVM, omrobjectptr_t *objectIndirect, void *localData, J9StackWalkState *walkState, const void *stackLocation)
4978
{
5079
MM_ConcurrentMarkingDelegate::markSchemeStackIteratorData *data = (MM_ConcurrentMarkingDelegate::markSchemeStackIteratorData *)localData;
51-
52-
omrobjectptr_t object = *objectIndirect;
53-
if (data->env->getExtensions()->heap->objectIsInGap(object)) {
54-
/* CMVC 136483: Ensure that the object is not in the gap of a split heap (stack-allocated object) since we can't mark that part of the address space */
55-
Assert_MM_validStackSlot(MM_StackSlotValidator(MM_StackSlotValidator::NOT_ON_HEAP, object, stackLocation, walkState).validate(data->env));
56-
} else if (data->markingScheme->isHeapObject(object)) {
57-
/* heap object - validate and mark */
58-
Assert_MM_validStackSlot(MM_StackSlotValidator(0, object, stackLocation, walkState).validate(data->env));
59-
data->markingScheme->markObject(data->env, object);
60-
} else if (NULL != object) {
61-
/* stack object - just validate */
62-
Assert_MM_validStackSlot(MM_StackSlotValidator(MM_StackSlotValidator::NOT_ON_HEAP, object, stackLocation, walkState).validate(data->env));
63-
}
80+
data->concurrentMarkingDelegate->doStackSlot(data->env, objectIndirect, walkState, stackLocation);
6481
}
6582

6683
bool
@@ -150,14 +167,21 @@ MM_ConcurrentMarkingDelegate::scanThreadRoots(MM_EnvironmentBase *env)
150167
}
151168

152169
markSchemeStackIteratorData localData;
153-
localData.markingScheme = _markingScheme;
170+
localData.concurrentMarkingDelegate = this;
154171
localData.env = env;
155172
/* In a case this thread is a carrier thread, and a virtual thread is mounted, we will scan virtual thread's stack. */
156173
GC_VMThreadStackSlotIterator::scanSlots(vmThread, vmThread, (void *)&localData, concurrentStackSlotIterator, true, false);
157174

158175
#if JAVA_SPEC_VERSION >= 19
159176
if (NULL != vmThread->currentContinuation) {
160177
GC_VMThreadStackSlotIterator::scanSlots(vmThread, vmThread, vmThread->currentContinuation, (void *)&localData, concurrentStackSlotIterator, true, false);
178+
#if JAVA_SPEC_VERSION >= 24
179+
GC_ContinuationSlotIterator continuationSlotIterator(vmThread, vmThread->currentContinuation);
180+
181+
while (J9Object **slot = continuationSlotIterator.nextSlot()) {
182+
doContinuationSlot(env, slot, &continuationSlotIterator);
183+
}
184+
#endif /* JAVA_SPEC_VERSION >= 24 */
161185
}
162186
#endif /* JAVA_SPEC_VERSION >= 19 */
163187

runtime/gc_glue_java/ConcurrentMarkingDelegate.hpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
#include "ScanClassesMode.hpp"
4747
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
4848

49+
#if JAVA_SPEC_VERSION >= 24
50+
class GC_ContinuationSlotIterator;
51+
#endif /* JAVA_SPEC_VERSION >= 24 */
4952
class GC_VMThreadIterator;
5053
class MM_ConcurrentGC;
5154
class MM_MarkingScheme;
@@ -87,7 +90,7 @@ class MM_ConcurrentMarkingDelegate
8790
};
8891

8992
typedef struct markSchemeStackIteratorData {
90-
MM_MarkingScheme *markingScheme;
93+
MM_ConcurrentMarkingDelegate *concurrentMarkingDelegate;
9194
MM_EnvironmentBase *env;
9295
} markSchemeStackIteratorData;
9396

@@ -114,6 +117,11 @@ class MM_ConcurrentMarkingDelegate
114117
*/
115118
bool initialize(MM_EnvironmentBase *env, MM_ConcurrentGC *collector);
116119

120+
MMINLINE void doSlot(MM_EnvironmentBase *env, omrobjectptr_t *slotPtr);
121+
#if JAVA_SPEC_VERSION >= 24
122+
void doContinuationSlot(MM_EnvironmentBase *env, omrobjectptr_t *slotPtr, GC_ContinuationSlotIterator *continuationSlotIterator);
123+
#endif /* JAVA_SPEC_VERSION >= 24 */
124+
void doStackSlot(MM_EnvironmentBase *env, omrobjectptr_t *slotPtr, J9StackWalkState *walkState, const void *stackLocation);
117125
/**
118126
* In the case of Weak Consistency platforms we require this method to bring mutator threads to a safe point. A safe
119127
* point is a point at which a GC may occur.

runtime/gc_glue_java/HeapWalkerDelegate.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include "HeapWalkerDelegate.hpp"
2525

2626
#include "j9.h"
27+
#if JAVA_SPEC_VERSION >= 24
28+
#include "ContinuationSlotIterator.hpp"
29+
#endif /* JAVA_SPEC_VERSION >= 24 */
2730
#include "EnvironmentBase.hpp"
2831
#include "GCExtensions.hpp"
2932
#include "ObjectModel.hpp"
@@ -72,5 +75,15 @@ MM_HeapWalkerDelegate::doContinuationNativeSlots(MM_EnvironmentBase *env, omrobj
7275
localData.userData = userData;
7376

7477
GC_VMThreadStackSlotIterator::scanContinuationSlots(currentThread, objectPtr, (void *)&localData, stackSlotIteratorForHeapWalker, false, false);
78+
79+
#if JAVA_SPEC_VERSION >= 24
80+
J9VMContinuation *continuation = J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, objectPtr);
81+
GC_ContinuationSlotIterator continuationSlotIterator(currentThread, continuation);
82+
83+
while (J9Object **slotPtr = continuationSlotIterator.nextSlot()) {
84+
_heapWalker->heapWalkerSlotCallback(env, slotPtr, function, userData);
85+
}
86+
#endif /* JAVA_SPEC_VERSION >= 24 */
87+
7588
}
7689
}

0 commit comments

Comments
 (0)