Path: blob/master/runtime/gc_glue_java/MetronomeDelegate.hpp
5985 views
/*******************************************************************************1* Copyright (c) 2019, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#if !defined(METRONOMEDELEGATE_HPP_)23#define METRONOMEDELEGATE_HPP_2425#include "j9.h"26#include "j9cfg.h"2728#if defined(J9VM_GC_REALTIME)2930#include "BaseNonVirtual.hpp"31#include "EnvironmentRealtime.hpp"32#include "GCExtensions.hpp"33#include "RealtimeAccessBarrier.hpp"34#include "RealtimeMarkingScheme.hpp"35#include "ReferenceObjectBuffer.hpp"36#include "Scheduler.hpp"3738class MM_HeapRegionDescriptorRealtime;39class MM_RealtimeMarkingSchemeRootMarker;40class MM_RealtimeRootScanner;41class MM_Scheduler;4243class MM_MetronomeDelegate : public MM_BaseNonVirtual44{45private:46MM_GCExtensions *_extensions;47MM_RealtimeGC *_realtimeGC;48J9JavaVM *_javaVM;49MM_Scheduler *_scheduler;50MM_RealtimeMarkingScheme *_markingScheme;51UDATA _vmResponsesRequiredForExclusiveVMAccess; /**< Used to support the (request/wait)ExclusiveVMAccess methods. */52UDATA _jniResponsesRequiredForExclusiveVMAccess; /**< Used to support the (request/wait)ExclusiveVMAccess methods. */5354public:55void yieldWhenRequested(MM_EnvironmentBase *env);56static int J9THREAD_PROC metronomeAlarmThreadWrapper(void* userData);57static uintptr_t signalProtectedFunction(J9PortLibrary *privatePortLibrary, void* userData);5859MM_MetronomeDelegate(MM_EnvironmentBase *env) :60_extensions(MM_GCExtensions::getExtensions(env)),61_realtimeGC(NULL),62_javaVM((J9JavaVM*)env->getOmrVM()->_language_vm) {}6364#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)65bool _unmarkedImpliesClasses; /**< if true the mark bit can be used to check is class alive or not */66#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */67bool _unmarkedImpliesCleared;68bool _unmarkedImpliesStringsCleared; /**< If true, we can assume that unmarked strings in the string table will be cleared */6970#if defined(J9VM_GC_FINALIZATION)71bool _finalizationRequired;72#endif /* J9VM_GC_FINALIZATION */73#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)74bool _dynamicClassUnloadingEnabled;75#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */7677bool initialize(MM_EnvironmentBase *env);78void tearDown(MM_EnvironmentBase *env);7980bool allocateAndInitializeReferenceObjectLists(MM_EnvironmentBase *env);81bool allocateAndInitializeUnfinalizedObjectLists(MM_EnvironmentBase *env);82bool allocateAndInitializeOwnableSynchronizerObjectLists(MM_EnvironmentBase *env);8384#if defined(J9VM_GC_FINALIZATION)85bool isFinalizationRequired() { return _finalizationRequired; }86#endif /* J9VM_GC_FINALIZATION */8788void mainSetupForGC(MM_EnvironmentBase *env);89void mainCleanupAfterGC(MM_EnvironmentBase *env);90void incrementalCollectStart(MM_EnvironmentRealtime *env);91void incrementalCollect(MM_EnvironmentRealtime *env);92void doAuxiliaryGCWork(MM_EnvironmentBase *env);93void clearGCStats();94void clearGCStatsEnvironment(MM_EnvironmentRealtime *env);95void mergeGCStats(MM_EnvironmentRealtime *env);96uintptr_t getSplitArraysProcessed(MM_EnvironmentRealtime *env);97void reportSyncGCEnd(MM_EnvironmentBase *env);9899#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)100MMINLINE bool isDynamicClassUnloadingEnabled() { return _dynamicClassUnloadingEnabled; };101void unloadDeadClassLoaders(MM_EnvironmentBase *env);102103void reportClassUnloadingStart(MM_EnvironmentBase *env);104void reportClassUnloadingEnd(MM_EnvironmentBase *env);105#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */106107#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)108/**109* Perform initial cleanup for classloader unloading. The current thread has exclusive access.110* The J9AccClassDying bit is set and J9HOOK_VM_CLASS_UNLOAD is triggered for each class that will be unloaded.111* The J9_GC_CLASS_LOADER_DEAD bit is set for each class loader that will be unloaded.112* J9HOOK_VM_CLASSES_UNLOAD is triggered if any classes will be unloaded.113*114* @param env[in] the main GC thread115* @param classUnloadCountResult[out] returns the number of classes about to be unloaded116* @param anonymousClassUnloadCount[out] returns the number of anonymous classes about to be unloaded117* @param classLoaderUnloadCountResult[out] returns the number of class loaders about to be unloaded118* @param classLoaderUnloadListResult[out] returns a linked list of class loaders about to be unloaded119*/120void processDyingClasses(MM_EnvironmentRealtime *env, UDATA* classUnloadCountResult, UDATA* anonymousClassUnloadCount, UDATA* classLoaderUnloadCountResult, J9ClassLoader** classLoaderUnloadListResult);121void processUnlinkedClassLoaders(MM_EnvironmentBase *env, J9ClassLoader *deadClassLoaders);122void updateClassUnloadStats(MM_EnvironmentBase *env, UDATA classUnloadCount, UDATA anonymousClassUnloadCount, UDATA classLoaderUnloadCount);123124/**125* Scan classloader for dying classes and add them to the list126* @param env[in] the current thread127* @param classLoader[in] the list of class loaders to clean up128* @param setAll[in] bool if true if all classes must be set dying, if false unmarked classes only129* @param classUnloadListStart[in] root of list dying classes should be added to130* @param classUnloadCountOut[out] number of classes dying added to the list131* @return new root to list of dying classes132*/133J9Class *addDyingClassesToList(MM_EnvironmentRealtime *env, J9ClassLoader * classLoader, bool setAll, J9Class *classUnloadListStart, UDATA *classUnloadCountResult);134#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */135136void yieldFromClassUnloading(MM_EnvironmentRealtime *env);137void lockClassUnloadMonitor(MM_EnvironmentRealtime *env);138void unlockClassUnloadMonitor(MM_EnvironmentRealtime *env);139140UDATA getUnfinalizedObjectListCount(MM_EnvironmentBase *env) { return _extensions->gcThreadCount; }141UDATA getOwnableSynchronizerObjectListCount(MM_EnvironmentBase *env) { return _extensions->gcThreadCount; }142UDATA getReferenceObjectListCount(MM_EnvironmentBase *env) { return _extensions->gcThreadCount; }143144void defaultMemorySpaceAllocated(MM_GCExtensionsBase *extensions, void* defaultMemorySpace);145MM_RealtimeAccessBarrier* allocateAccessBarrier(MM_EnvironmentBase *env);146void enableDoubleBarrier(MM_EnvironmentBase* env);147void disableDoubleBarrierOnThread(MM_EnvironmentBase* env, OMR_VMThread* vmThread);148void disableDoubleBarrier(MM_EnvironmentBase* env);149150/* New methods */151#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)152bool doClassTracing(MM_EnvironmentRealtime* env);153#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */154bool doTracing(MM_EnvironmentRealtime* env);155156/*157* These functions are used by classic Metronome gang-scheduling and158* also transitionally used for the parts of realtime that have not159* been made concurrent.160*/161void preRequestExclusiveVMAccess(OMR_VMThread *threadRequestingExclusive);162void postRequestExclusiveVMAccess(OMR_VMThread *threadRequestingExclusive);163uintptr_t requestExclusiveVMAccess(MM_EnvironmentBase *env, uintptr_t block, uintptr_t *gcPriority);164void waitForExclusiveVMAccess(MM_EnvironmentBase *env, bool waitRequired);165void acquireExclusiveVMAccess(MM_EnvironmentBase *env, bool waitRequired);166void releaseExclusiveVMAccess(MM_EnvironmentBase *env, bool releaseRequired);167168void markLiveObjectsRoots(MM_EnvironmentRealtime *env);169void markLiveObjectsScan(MM_EnvironmentRealtime *env);170void markLiveObjectsComplete(MM_EnvironmentRealtime *env);171void checkReferenceBuffer(MM_EnvironmentRealtime *env);172void setUnmarkedImpliesCleared();173void unsetUnmarkedImpliesCleared();174#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)175MMINLINE void176markClassOfObject(MM_EnvironmentRealtime *env, J9Object *objectPtr)177{178markClassNoCheck(env, J9GC_J9OBJECT_CLAZZ(objectPtr, env));179}180181MMINLINE bool182markClassNoCheck(MM_EnvironmentRealtime *env, J9Class *clazz)183{184bool result = false;185if (J9_ARE_ANY_BITS_SET(J9CLASS_EXTENDED_FLAGS(clazz), J9ClassIsAnonymous)) {186/*187* If class is anonymous it's classloader will not be rescanned188* so class object should be marked directly189*/190result = _markingScheme->markObject(env, clazz->classObject);191} else {192result = _markingScheme->markObject(env, clazz->classLoader->classLoaderObject);193}194return result;195}196bool markClass(MM_EnvironmentRealtime *env, J9Class *objectPtr);197#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */198199MMINLINE uintptr_t200scanPointerArraylet(MM_EnvironmentRealtime *env, fomrobject_t *arraylet)201{202fomrobject_t *startScanPtr = arraylet;203fomrobject_t *endScanPtr = (fomrobject_t*)((uintptr_t)startScanPtr + _javaVM->arrayletLeafSize);204return scanPointerRange(env, startScanPtr, endScanPtr);205}206207MMINLINE uintptr_t208scanObject(MM_EnvironmentRealtime *env, omrobjectptr_t objectPtr)209{210UDATA pointersScanned = 0;211switch(_extensions->objectModel.getScanType(objectPtr)) {212case GC_ObjectModel::SCAN_MIXED_OBJECT_LINKED:213case GC_ObjectModel::SCAN_ATOMIC_MARKABLE_REFERENCE_OBJECT:214case GC_ObjectModel::SCAN_MIXED_OBJECT:215case GC_ObjectModel::SCAN_OWNABLESYNCHRONIZER_OBJECT:216case GC_ObjectModel::SCAN_CLASS_OBJECT:217case GC_ObjectModel::SCAN_CLASSLOADER_OBJECT:218pointersScanned = scanMixedObject(env, objectPtr);219break;220case GC_ObjectModel::SCAN_POINTER_ARRAY_OBJECT:221pointersScanned = scanPointerArrayObject(env, (J9IndexableObject *)objectPtr);222break;223case GC_ObjectModel::SCAN_REFERENCE_MIXED_OBJECT:224pointersScanned = scanReferenceMixedObject(env, objectPtr);225break;226case GC_ObjectModel::SCAN_PRIMITIVE_ARRAY_OBJECT:227pointersScanned = 0;228break;229default:230Assert_MM_unreachable();231}232233return pointersScanned;234}235236MMINLINE UDATA237scanPointerRange(MM_EnvironmentRealtime *env, fj9object_t *startScanPtr, fj9object_t *endScanPtr)238{239UDATA pointerField = 0;240241if (env->compressObjectReferences()) {242uint32_t *scanPtr = (uint32_t*)startScanPtr;243uint32_t *endPtr = (uint32_t*)endScanPtr;244pointerField = endPtr - scanPtr;245while(scanPtr < endPtr) {246GC_SlotObject slotObject(_javaVM->omrVM, (fj9object_t*)scanPtr);247_markingScheme->markObject(env, slotObject.readReferenceFromSlot());248scanPtr++;249}250} else {251uintptr_t *scanPtr = (uintptr_t*)startScanPtr;252uintptr_t *endPtr = (uintptr_t*)endScanPtr;253pointerField = endPtr - scanPtr;254while(scanPtr < endPtr) {255GC_SlotObject slotObject(_javaVM->omrVM, (fj9object_t*)scanPtr);256_markingScheme->markObject(env, slotObject.readReferenceFromSlot());257scanPtr++;258}259}260261return pointerField;262}263264MMINLINE UDATA265scanMixedObject(MM_EnvironmentRealtime *env, J9Object *objectPtr)266{267/* Object slots */268269bool const compressed = env->compressObjectReferences();270fj9object_t *scanPtr = _extensions->mixedObjectModel.getHeadlessObject(objectPtr);271UDATA objectSize = _extensions->mixedObjectModel.getSizeInBytesWithHeader(objectPtr);272fj9object_t *endScanPtr = (fj9object_t*)(((U_8 *)objectPtr) + objectSize);273UDATA *descriptionPtr;274UDATA descriptionBits;275UDATA descriptionIndex;276#if defined(J9VM_GC_LEAF_BITS)277UDATA *leafPtr;278UDATA leafBits;279#endif /* J9VM_GC_LEAF_BITS */280281#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)282if(isDynamicClassUnloadingEnabled()) {283markClassOfObject(env, objectPtr);284}285#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */286287descriptionPtr = (UDATA *)J9GC_J9OBJECT_CLAZZ(objectPtr, env)->instanceDescription;288#if defined(J9VM_GC_LEAF_BITS)289leafPtr = (UDATA *)J9GC_J9OBJECT_CLAZZ(objectPtr, env)->instanceLeafDescription;290#endif /* J9VM_GC_LEAF_BITS */291292if(((UDATA)descriptionPtr) & 1) {293descriptionBits = ((UDATA)descriptionPtr) >> 1;294#if defined(J9VM_GC_LEAF_BITS)295leafBits = ((UDATA)leafPtr) >> 1;296#endif /* J9VM_GC_LEAF_BITS */297} else {298descriptionBits = *descriptionPtr++;299#if defined(J9VM_GC_LEAF_BITS)300leafBits = *leafPtr++;301#endif /* J9VM_GC_LEAF_BITS */302}303descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;304305UDATA pointerFields = 0;306while(scanPtr < endScanPtr) {307/* Determine if the slot should be processed */308if(descriptionBits & 1) {309pointerFields++;310GC_SlotObject slotObject(_javaVM->omrVM, scanPtr);311#if defined(J9VM_GC_LEAF_BITS)312_markingScheme->markObject(env, slotObject.readReferenceFromSlot(), 1 == (leafBits & 1));313#else /* J9VM_GC_LEAF_BITS */314_markingScheme->markObject(env, slotObject.readReferenceFromSlot(), false);315#endif /* J9VM_GC_LEAF_BITS */316}317descriptionBits >>= 1;318#if defined(J9VM_GC_LEAF_BITS)319leafBits >>= 1;320#endif /* J9VM_GC_LEAF_BITS */321if(descriptionIndex-- == 0) {322descriptionBits = *descriptionPtr++;323#if defined(J9VM_GC_LEAF_BITS)324leafBits = *leafPtr++;325#endif /* J9VM_GC_LEAF_BITS */326descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;327}328scanPtr = GC_SlotObject::addToSlotAddress(scanPtr, 1, compressed);329}330331env->incScannedObjects();332333return pointerFields;334}335336MMINLINE UDATA337scanPointerArrayObject(MM_EnvironmentRealtime *env, J9IndexableObject *objectPtr)338{339UDATA pointerFields = 0;340bool const compressed = env->compressObjectReferences();341342#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)343if(isDynamicClassUnloadingEnabled()) {344markClassOfObject(env, (J9Object *)objectPtr);345}346#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */347348bool isContiguous = _extensions->indexableObjectModel.isInlineContiguousArraylet(objectPtr);349350/* Very small arrays cannot be set as scanned (no scanned bit in Mark Map reserved for them) */351bool canSetAsScanned = (isContiguous352&& (_extensions->minArraySizeToSetAsScanned <= _extensions->indexableObjectModel.arrayletSize(objectPtr, 0)));353354if (canSetAsScanned && _markingScheme->isScanned((J9Object *)objectPtr)) {355/* Already scanned by ref array copy optimization */356return pointerFields;357}358359/* if NUA is enabled, separate path for contiguous arrays */360UDATA sizeInElements = _extensions->indexableObjectModel.getSizeInElements(objectPtr);361if (isContiguous || (0 == sizeInElements)) {362fj9object_t *startScanPtr = (fj9object_t *)_extensions->indexableObjectModel.getDataPointerForContiguous(objectPtr);363fj9object_t *endScanPtr = GC_SlotObject::addToSlotAddress(startScanPtr, sizeInElements, compressed);364pointerFields += scanPointerRange(env, startScanPtr, endScanPtr);365} else {366fj9object_t *arrayoid = _extensions->indexableObjectModel.getArrayoidPointer(objectPtr);367UDATA numArraylets = _extensions->indexableObjectModel.numArraylets(objectPtr);368for (UDATA i=0; i<numArraylets; i++) {369UDATA arrayletSize = _extensions->indexableObjectModel.arrayletSize(objectPtr, i);370/* need to check leaf pointer because this can be a partially allocated arraylet (not all leafs are allocated) */371GC_SlotObject slotObject(_javaVM->omrVM, GC_SlotObject::addToSlotAddress(arrayoid, i, compressed));372fj9object_t *startScanPtr = (fj9object_t*) (slotObject.readReferenceFromSlot());373if (NULL != startScanPtr) {374fj9object_t *endScanPtr = (fj9object_t*)((uintptr_t)startScanPtr + arrayletSize);375if (i == (numArraylets - 1)) {376pointerFields += scanPointerRange(env, startScanPtr, endScanPtr);377if (canSetAsScanned) {378_markingScheme->setScanAtomic((J9Object *)objectPtr);379}380} else {381env->getWorkStack()->push(env, (void *)ARRAYLET_TO_ITEM(startScanPtr));382}383}384}385}386387/* check for yield if we've actually scanned a leaf */388if (0 != pointerFields) {389_scheduler->condYieldFromGC(env);390}391392env->incScannedObjects();393394return pointerFields;395}396397MMINLINE UDATA398scanReferenceMixedObject(MM_EnvironmentRealtime *env, J9Object *objectPtr)399{400bool const compressed = env->compressObjectReferences();401fj9object_t *scanPtr = _extensions->mixedObjectModel.getHeadlessObject(objectPtr);402UDATA objectSize = _extensions->mixedObjectModel.getSizeInBytesWithHeader(objectPtr);403fj9object_t *endScanPtr = (fj9object_t*)(((U_8 *)objectPtr) + objectSize);404UDATA *descriptionPtr;405UDATA descriptionBits;406UDATA descriptionIndex;407#if defined(J9VM_GC_LEAF_BITS)408UDATA *leafPtr;409UDATA leafBits;410#endif /* J9VM_GC_LEAF_BITS */411412#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)413if(isDynamicClassUnloadingEnabled()) {414markClassOfObject(env, objectPtr);415}416#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */417418descriptionPtr = (UDATA *)J9GC_J9OBJECT_CLAZZ(objectPtr, env)->instanceDescription;419#if defined(J9VM_GC_LEAF_BITS)420leafPtr = (UDATA *)J9GC_J9OBJECT_CLAZZ(objectPtr, env)->instanceLeafDescription;421#endif /* J9VM_GC_LEAF_BITS */422423if(((UDATA)descriptionPtr) & 1) {424descriptionBits = ((UDATA)descriptionPtr) >> 1;425#if defined(J9VM_GC_LEAF_BITS)426leafBits = ((UDATA)leafPtr) >> 1;427#endif /* J9VM_GC_LEAF_BITS */428} else {429descriptionBits = *descriptionPtr++;430#if defined(J9VM_GC_LEAF_BITS)431leafBits = *leafPtr++;432#endif /* J9VM_GC_LEAF_BITS */433}434descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;435436I_32 referenceState = J9GC_J9VMJAVALANGREFERENCE_STATE(env, objectPtr);437UDATA referenceObjectType = J9CLASS_FLAGS(J9GC_J9OBJECT_CLAZZ(objectPtr, env)) & J9AccClassReferenceMask;438UDATA referenceObjectOptions = env->_cycleState->_referenceObjectOptions;439bool isReferenceCleared = (GC_ObjectModel::REF_STATE_CLEARED == referenceState) || (GC_ObjectModel::REF_STATE_ENQUEUED == referenceState);440bool referentMustBeMarked = isReferenceCleared;441bool referentMustBeCleared = false;442443switch (referenceObjectType) {444case J9AccClassReferenceWeak:445referentMustBeCleared = (0 != (referenceObjectOptions & MM_CycleState::references_clear_weak));446break;447case J9AccClassReferenceSoft:448referentMustBeCleared = (0 != (referenceObjectOptions & MM_CycleState::references_clear_soft));449referentMustBeMarked = referentMustBeMarked || (450((0 == (referenceObjectOptions & MM_CycleState::references_soft_as_weak))451&& ((UDATA)J9GC_J9VMJAVALANGSOFTREFERENCE_AGE(env, objectPtr) < _extensions->getDynamicMaxSoftReferenceAge())));452break;453case J9AccClassReferencePhantom:454referentMustBeCleared = (0 != (referenceObjectOptions & MM_CycleState::references_clear_phantom));455break;456default:457Assert_MM_unreachable();458}459460GC_SlotObject referentPtr(_javaVM->omrVM, J9GC_J9VMJAVALANGREFERENCE_REFERENT_ADDRESS(env, objectPtr));461462if (referentMustBeCleared) {463/* Discovering this object at this stage in the GC indicates that it is being resurrected. Clear its referent slot. */464referentPtr.writeReferenceToSlot(NULL);465/* record that the reference has been cleared if it's not already in the cleared or enqueued state */466if (!isReferenceCleared) {467J9GC_J9VMJAVALANGREFERENCE_STATE(env, objectPtr) = GC_ObjectModel::REF_STATE_CLEARED;468}469} else {470/* we don't need to process cleared or enqueued references */471if (!isReferenceCleared) {472env->getGCEnvironment()->_referenceObjectBuffer->add(env, objectPtr);473}474}475476UDATA pointerFields = 0;477while(scanPtr < endScanPtr) {478/* Determine if the slot should be processed */479if((descriptionBits & 1) && ((scanPtr != referentPtr.readAddressFromSlot()) || referentMustBeMarked)) {480pointerFields++;481GC_SlotObject slotObject(_javaVM->omrVM, scanPtr);482#if defined(J9VM_GC_LEAF_BITS)483_markingScheme->markObject(env, slotObject.readReferenceFromSlot(), 1 == (leafBits & 1));484#else /* J9VM_GC_LEAF_BITS */485_markingScheme->markObject(env, slotObject.readReferenceFromSlot(), false);486#endif /* J9VM_GC_LEAF_BITS */487}488descriptionBits >>= 1;489#if defined(J9VM_GC_LEAF_BITS)490leafBits >>= 1;491#endif /* J9VM_GC_LEAF_BITS */492if(descriptionIndex-- == 0) {493descriptionBits = *descriptionPtr++;494#if defined(J9VM_GC_LEAF_BITS)495leafBits = *leafPtr++;496#endif /* J9VM_GC_LEAF_BITS */497descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;498}499scanPtr = GC_SlotObject::addToSlotAddress(scanPtr, 1, compressed);500}501502env->incScannedObjects();503504return pointerFields;505}506507#if defined(J9VM_GC_FINALIZATION)508void scanUnfinalizedObjects(MM_EnvironmentRealtime *env);509#endif /* J9VM_GC_FINALIZATION */510511/**512* Wraps the MM_RootScanner::scanOwnableSynchronizerObjects method to disable yielding during the scan513* then yield after scanning.514* @see MM_RootScanner::scanOwnableSynchronizerObjects()515*/516void scanOwnableSynchronizerObjects(MM_EnvironmentRealtime *env);517518private:519/**520* Called by the root scanner to scan all WeakReference objects discovered by the mark phase,521* clearing and enqueuing them if necessary.522* @param env[in] the current thread523*/524void scanWeakReferenceObjects(MM_EnvironmentRealtime *env);525/**526* Process the list of reference objects recorded in the specified list.527* References with unmarked referents are cleared and optionally enqueued.528* SoftReferences have their ages incremented.529* @param env[in] the current thread530* @param region[in] the region all the objects in the list belong to531* @param headOfList[in] the first object in the linked list532*/533void processReferenceList(MM_EnvironmentRealtime *env, MM_HeapRegionDescriptorRealtime* region, J9Object* headOfList, MM_ReferenceStats *referenceStats);534535/**536* Called by the root scanner to scan all SoftReference objects discovered by the mark phase,537* clearing and enqueuing them if necessary.538* @param env[in] the current thread539*/540void scanSoftReferenceObjects(MM_EnvironmentRealtime *env);541542/**543* Called by the root scanner to scan all PhantomReference objects discovered by the mark phase,544* clearing and enqueuing them if necessary.545* @param env[in] the current thread546*/547void scanPhantomReferenceObjects(MM_EnvironmentRealtime *env);548549/*550* Friends551*/552friend class MM_RealtimeGC;553friend class MM_RealtimeMarkingSchemeRootClearer;554};555556#endif /* defined(J9VM_GC_REALTIME) */557558#endif /* defined(METRONOMEDELEGATE_HPP_) */559560561562