Path: blob/master/runtime/gc_base/RootScanner.cpp
5986 views
/*******************************************************************************1* Copyright (c) 1991, 2022 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#include <stdlib.h>23#include <stdio.h>24#include <limits.h> // or <climits> for CHAR_BIT25#include <string.h> // memcpy2627#include "j9cfg.h"28#include "j9.h"29#if defined(J9VM_OPT_JVMTI)30#include "jvmtiInternal.h"31#endif /* defined(J9VM_OPT_JVMTI) */3233#include "RootScanner.hpp"3435#include "ClassIterator.hpp"36#include "ClassHeapIterator.hpp"37#include "ClassLoaderIterator.hpp"38#include "Debug.hpp"39#include "EnvironmentBase.hpp"40#if defined(J9VM_GC_FINALIZATION)41#include "FinalizeListManager.hpp"42#endif /* J9VM_GC_FINALIZATION*/43#include "Heap.hpp"44#include "HeapRegionDescriptor.hpp"45#include "HeapRegionIterator.hpp"46#include "HeapRegionManager.hpp"47#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)48#include "HeapRegionIteratorVLHGC.hpp"49#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */50#include "MemoryPool.hpp"51#include "MemorySubSpace.hpp"52#include "MemorySpace.hpp"53#include "MixedObjectIterator.hpp"54#include "ModronTypes.hpp"55#include "ObjectAccessBarrier.hpp"56#include "ObjectHeapIteratorAddressOrderedList.hpp"57#include "ObjectModel.hpp"58#include "OwnableSynchronizerObjectList.hpp"59#include "ParallelDispatcher.hpp"60#include "PointerArrayIterator.hpp"61#include "SlotObject.hpp"62#include "StringTable.hpp"63#include "StringTableIncrementalIterator.hpp"64#include "Task.hpp"65#include "UnfinalizedObjectList.hpp"66#include "VMClassSlotIterator.hpp"67#include "VMInterface.hpp"68#include "VMThreadListIterator.hpp"69#include "VMThreadIterator.hpp"7071/**72* @todo Provide function documentation73*/74void75MM_RootScanner::doClassLoader(J9ClassLoader *classLoader)76{77doSlot(J9GC_J9CLASSLOADER_CLASSLOADEROBJECT_EA(classLoader));7879scanModularityObjects(classLoader);80}8182void83MM_RootScanner::scanModularityObjects(J9ClassLoader * classLoader)84{85if (NULL != classLoader->moduleHashTable) {86J9HashTableState moduleWalkState;87J9JavaVM *javaVM = static_cast<J9JavaVM*>(_omrVM->_language_vm);88J9Module **modulePtr = (J9Module**)hashTableStartDo(classLoader->moduleHashTable, &moduleWalkState);89while (NULL != modulePtr) {90J9Module * const module = *modulePtr;9192doSlot(&module->moduleObject);93if (NULL != module->moduleName) {94doSlot(&module->moduleName);95}96if (NULL != module->version) {97doSlot(&module->version);98}99modulePtr = (J9Module**)hashTableNextDo(&moduleWalkState);100}101102if (classLoader == javaVM->systemClassLoader) {103doSlot(&javaVM->unamedModuleForSystemLoader->moduleObject);104}105}106}107108/**109* @todo Provide function documentation110*/111MM_RootScanner::CompletePhaseCode112MM_RootScanner::scanWeakReferencesComplete(MM_EnvironmentBase *env)113{114return complete_phase_OK;115}116117118/**119* @todo Provide function documentation120*/121MM_RootScanner::CompletePhaseCode122MM_RootScanner::scanSoftReferencesComplete(MM_EnvironmentBase *env)123{124return complete_phase_OK;125}126127/**128* @todo Provide function documentation129*/130MM_RootScanner::CompletePhaseCode131MM_RootScanner::scanPhantomReferencesComplete(MM_EnvironmentBase *env)132{133return complete_phase_OK;134}135136#if defined(J9VM_GC_FINALIZATION)137void138MM_RootScanner::doUnfinalizedObject(J9Object *objectPtr, MM_UnfinalizedObjectList *list)139{140/* This function needs to be overridden if the default implementation of scanUnfinalizedObjects141* is used.142*/143Assert_MM_unreachable();144}145146/**147* @todo Provide function documentation148*/149MM_RootScanner::CompletePhaseCode150MM_RootScanner::scanUnfinalizedObjectsComplete(MM_EnvironmentBase *env)151{152return complete_phase_OK;153}154#endif /* J9VM_GC_FINALIZATION */155156void157MM_RootScanner::doOwnableSynchronizerObject(J9Object *objectPtr, MM_OwnableSynchronizerObjectList *list)158{159/* This function needs to be overridden if the default implementation of scanOwnableSynchronizerObjects160* is used.161*/162Assert_MM_unreachable();163}164165MM_RootScanner::CompletePhaseCode166MM_RootScanner::scanOwnableSynchronizerObjectsComplete(MM_EnvironmentBase *env)167{168return complete_phase_OK;169}170171/**172* @todo Provide function documentation173*/174void175MM_RootScanner::doMonitorReference(J9ObjectMonitor *objectMonitor, GC_HashTableIterator *monitorReferenceIterator)176{177J9ThreadAbstractMonitor * monitor = (J9ThreadAbstractMonitor*)objectMonitor->monitor;178doSlot((J9Object **)& monitor->userData);179}180181MM_RootScanner::CompletePhaseCode182MM_RootScanner::scanMonitorReferencesComplete(MM_EnvironmentBase *env)183{184return complete_phase_OK;185}186187188/**189* @todo Provide function documentation190*/191void192MM_RootScanner::doMonitorLookupCacheSlot(j9objectmonitor_t* slotPtr)193{194if(0 != *slotPtr) {195*slotPtr = 0;196}197}198199200/**201* @todo Provide function documentation202*/203void204MM_RootScanner::doJNIWeakGlobalReference(J9Object **slotPtr)205{206doSlot(slotPtr);207}208209#if defined(J9VM_GC_MODRON_SCAVENGER)210/**211* @todo Provide function documentation212*/213void214MM_RootScanner::doRememberedSetSlot(J9Object **slotPtr, GC_RememberedSetSlotIterator *rememberedSetSlotIterator)215{216doSlot(slotPtr);217}218#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */219220/**221* @todo Provide function documentation222*/223void224MM_RootScanner::doStringTableSlot(J9Object **slotPtr, GC_StringTableIterator *stringTableIterator)225{226doSlot(slotPtr);227}228229#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)230void231MM_RootScanner::doDoubleMappedObjectSlot(J9Object *objectPtr, struct J9PortVmemIdentifier *identifier)232{233/* No need to call doSlot() here since there's nothing to update */234}235#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */236237/**238* @Perform operation on the given string cache table slot.239* @String table cache contains cached entries of string table, it's240* @a subset of string table entries.241*/242void243MM_RootScanner::doStringCacheTableSlot(J9Object **slotPtr)244{245doSlot(slotPtr);246}247248/**249* @todo Provide function documentation250*/251void252MM_RootScanner::doVMClassSlot(J9Class *classPtr)253{254doClassSlot(classPtr);255}256257/**258* General object field slot handler to be reimplemented by specializing class. This handler is called259* for every reference through an instance field.260* Implementation for slotObject input format261* @param slotObject Input field for scan in slotObject format262*/263void264MM_RootScanner::doFieldSlot(GC_SlotObject *slotObject)265{266J9Object* object = slotObject->readReferenceFromSlot();267doSlot(&object);268slotObject->writeReferenceToSlot(object);269}270271#if defined(J9VM_OPT_JVMTI)272/**273* @todo Provide function documentation274*/275void276MM_RootScanner::doJVMTIObjectTagSlot(J9Object **slotPtr, GC_JVMTIObjectTagTableIterator *objectTagTableIterator)277{278doSlot(slotPtr);279}280#endif /* J9VM_OPT_JVMTI */281282/**283* @todo Provide function documentation284*/285void286MM_RootScanner::scanClasses(MM_EnvironmentBase *env)287{288reportScanningStarted(RootScannerEntity_Classes);289290GC_SegmentIterator segmentIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm)->classMemorySegments, MEMORY_TYPE_RAM_CLASS);291292while(J9MemorySegment *segment = segmentIterator.nextSegment()) {293if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {294GC_ClassHeapIterator classHeapIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm), segment);295J9Class *clazz = NULL;296while(NULL != (clazz = classHeapIterator.nextClass())) {297doClass(clazz);298if (shouldYieldFromClassScan(100000)) {299yield();300}301}302}303}304305condYield();306307reportScanningEnded(RootScannerEntity_Classes);308}309310/**311* Scan through the slots in the VM containing known classes312*/313void314MM_RootScanner::scanVMClassSlots(MM_EnvironmentBase *env)315{316/* VM Class Slot Iterator */317if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {318reportScanningStarted(RootScannerEntity_VMClassSlots);319320GC_VMClassSlotIterator classSlotIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm));321J9Class *classPtr;322323while (NULL != (classPtr = classSlotIterator.nextSlot())) {324doVMClassSlot(classPtr);325}326327reportScanningEnded(RootScannerEntity_VMClassSlots);328}329}330331/**332* General class slot handler to be reimplemented by specializing class.333* This handler is called for every reference to a J9Class.334*/335void336MM_RootScanner::doClassSlot(J9Class *classPtr)337{338/* ignore class slots by default */339}340341/**342* @todo Provide function documentation343*/344void345MM_RootScanner::doStackSlot(J9Object **slotPtr, void *walkState, const void* stackLocation)346{347/* ensure that this isn't a slot pointing into the gap (only matters for split heap VMs) */348if (!_extensions->heap->objectIsInGap(*slotPtr)) {349doSlot(slotPtr);350}351}352353/**354* @todo Provide function documentation355*/356void357MM_RootScanner::doVMThreadSlot(J9Object **slotPtr, GC_VMThreadIterator *vmThreadIterator)358{359doSlot(slotPtr);360}361362/**363* @todo Provide function documentation364*/365void366MM_RootScanner::doJNIGlobalReferenceSlot(J9Object **slotPtr, GC_JNIGlobalReferenceIterator *jniGlobalReferenceIterator)367{368doSlot(slotPtr);369}370371#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)372/**373* Scan all classes which will never be unloaded (those that374* were loaded either by the system class loader or the application375* class loader).376*/377void378MM_RootScanner::scanPermanentClasses(MM_EnvironmentBase *env)379{380reportScanningStarted(RootScannerEntity_PermanentClasses);381382J9MemorySegment *segment = NULL;383J9Class *clazz = NULL;384385/* Do systemClassLoader */386if (NULL != static_cast<J9JavaVM*>(_omrVM->_language_vm)->systemClassLoader) {387GC_ClassLoaderSegmentIterator segmentIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm)->systemClassLoader, MEMORY_TYPE_RAM_CLASS);388while(NULL != (segment = segmentIterator.nextSegment())) {389if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {390GC_ClassHeapIterator classHeapIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm), segment);391while(NULL != (clazz = classHeapIterator.nextClass())) {392doClass(clazz);393if (shouldYieldFromClassScan(100000)) {394yield();395}396}397}398}399}400401/* Do applicationClassLoader */402if (NULL != static_cast<J9JavaVM*>(_omrVM->_language_vm)->applicationClassLoader) {403GC_ClassLoaderSegmentIterator segmentIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm)->applicationClassLoader, MEMORY_TYPE_RAM_CLASS);404while(NULL != (segment = segmentIterator.nextSegment())) {405if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {406GC_ClassHeapIterator classHeapIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm), segment);407while(NULL != (clazz = classHeapIterator.nextClass())) {408doClass(clazz);409if (shouldYieldFromClassScan(100000)) {410yield();411}412}413}414}415}416417condYield();418419reportScanningEnded(RootScannerEntity_PermanentClasses);420}421#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */422423/**424* Checkpoint signalling completion of scanning of class data (classes and classloaders).425* This checkpoint is called once for any larger scanning phase426* which includes class scanning.427* @see scanClasses428* @see scanPermanentClasses429*/430MM_RootScanner::CompletePhaseCode431MM_RootScanner::scanClassesComplete(MM_EnvironmentBase *env)432{433return complete_phase_OK;434}435436/**437* @todo Provide function documentation438*/439void440MM_RootScanner::scanClassLoaders(MM_EnvironmentBase *env)441{442if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {443reportScanningStarted(RootScannerEntity_ClassLoaders);444445J9ClassLoader *classLoader;446447GC_ClassLoaderIterator classLoaderIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm)->classLoaderBlocks);448while((classLoader = classLoaderIterator.nextSlot()) != NULL) {449doClassLoader(classLoader);450}451452reportScanningEnded(RootScannerEntity_ClassLoaders);453}454}455456/**457* @todo Provide function documentation458*/459void460stackSlotIterator(J9JavaVM *javaVM, J9Object **slot, void *localData, J9StackWalkState *walkState, const void *stackLocation)461{462StackIteratorData *data = (StackIteratorData *)localData;463data->rootScanner->doStackSlot(slot, walkState, stackLocation);464}465466/**467* @todo Provide function documentation468*469* This function iterates through all the threads, calling scanOneThread on each one that470* should be scanned. The scanOneThread function scans exactly one thread and returns471* either true (if it took an action that requires the thread list iterator to return to472* the beginning) or false (if the thread list iterator should just continue with the next473* thread).474*/475void476MM_RootScanner::scanThreads(MM_EnvironmentBase *env)477{478reportScanningStarted(RootScannerEntity_Threads);479480/* TODO This assumes that while exclusive vm access is held the thread481* list is also locked.482*/483484GC_VMThreadListIterator vmThreadListIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm));485StackIteratorData localData;486487localData.rootScanner = this;488localData.env = env;489490while(J9VMThread *walkThread = vmThreadListIterator.nextVMThread()) {491if (_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {492if (scanOneThread(env, walkThread, (void*) &localData)) {493vmThreadListIterator.reset(static_cast<J9JavaVM*>(_omrVM->_language_vm)->mainThread);494}495}496}497498reportScanningEnded(RootScannerEntity_Threads);499}500501/**502* This function scans exactly one thread for potential roots. It is designed as503* an overridable subroutine of the primary functions scanThreads and scanSingleThread.504* @param walkThead the thread to be scanned505* @param localData opaque data to be passed to the stack walker callback function.506* The root scanner fixes that callback function to the stackSlotIterator function507* defined above508* @return true if the thread scan included an action that requires the thread list509* iterator to begin over again at the beginning, false otherwise. This implementation510* always returns false but an overriding implementation may take actions that require511* a true return (for example, RealtimeRootScanner returns true if it yielded after the512* scan, allowing other threads to run and perhaps be created or terminated).513**/514bool515MM_RootScanner::scanOneThread(MM_EnvironmentBase *env, J9VMThread* walkThread, void* localData)516{517GC_VMThreadIterator vmThreadIterator(walkThread);518519while(J9Object **slot = vmThreadIterator.nextSlot()) {520doVMThreadSlot(slot, &vmThreadIterator);521}522523GC_VMThreadStackSlotIterator::scanSlots((J9VMThread *)env->getOmrVMThread()->_language_vmthread, walkThread, localData, stackSlotIterator, isStackFrameClassWalkNeeded(), _trackVisibleStackFrameDepth);524return false;525}526527/**528* This function scans exactly one thread for potential roots.529* @param walkThead the thread to be scanned530**/531void532MM_RootScanner::scanSingleThread(MM_EnvironmentBase *env, J9VMThread* walkThread)533{534StackIteratorData localData;535localData.rootScanner = this;536localData.env = env;537scanOneThread(env, walkThread, &localData);538}539540#if defined(J9VM_GC_FINALIZATION)541/**542* @todo Provide function documentation543*/544void545MM_RootScanner::scanFinalizableObjects(MM_EnvironmentBase *env)546{547if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {548reportScanningStarted(RootScannerEntity_FinalizableObjects);549550GC_FinalizeListManager * finalizeListManager = _extensions->finalizeListManager;551{552/* walk finalizable objects loaded by the system class loader */553j9object_t systemObject = finalizeListManager->peekSystemFinalizableObject();554while (NULL != systemObject) {555doFinalizableObject(systemObject);556systemObject = finalizeListManager->peekNextSystemFinalizableObject(systemObject);557}558}559560{561/* walk finalizable objects loaded by all other class loaders*/562j9object_t defaultObject = finalizeListManager->peekDefaultFinalizableObject();563while (NULL != defaultObject) {564doFinalizableObject(defaultObject);565defaultObject = finalizeListManager->peekNextDefaultFinalizableObject(defaultObject);566}567}568569{570/* walk reference objects */571j9object_t referenceObject = finalizeListManager->peekReferenceObject();572while (NULL != referenceObject) {573doFinalizableObject(referenceObject);574referenceObject = finalizeListManager->peekNextReferenceObject(referenceObject);575}576}577578reportScanningEnded(RootScannerEntity_FinalizableObjects);579}580}581#endif /* J9VM_GC_FINALIZATION */582583/**584* @todo Provide function documentation585*/586void587MM_RootScanner::scanJNIGlobalReferences(MM_EnvironmentBase *env)588{589/* JNI Global References */590if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {591reportScanningStarted(RootScannerEntity_JNIGlobalReferences);592593GC_JNIGlobalReferenceIterator jniGlobalReferenceIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm)->jniGlobalReferences);594J9Object **slot;595596while((slot = (J9Object **)jniGlobalReferenceIterator.nextSlot()) != NULL) {597doJNIGlobalReferenceSlot(slot, &jniGlobalReferenceIterator);598}599600reportScanningEnded(RootScannerEntity_JNIGlobalReferences);601}602}603604/**605* @todo Provide function documentation606*/607void608MM_RootScanner::scanStringTable(MM_EnvironmentBase *env)609{610MM_StringTable *stringTable = _extensions->getStringTable();611reportScanningStarted(RootScannerEntity_StringTable);612bool isMetronomeGC = _extensions->isMetronomeGC();613614/* String Table */615for (UDATA tableIndex = 0; tableIndex < stringTable->getTableCount(); tableIndex++) {616if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {617618if (isMetronomeGC) {619GC_StringTableIncrementalIterator stringTableIterator(stringTable->getTable(tableIndex));620J9Object **slot = NULL;621622stringTableIterator.disableTableGrowth();623while (stringTableIterator.nextIncrement()) {624while (NULL != (slot = (J9Object **)stringTableIterator.nextSlot())) {625doStringTableSlot(slot, &stringTableIterator);626}627if (shouldYieldFromStringScan()) {628yield();629}630}631stringTableIterator.enableTableGrowth();632} else {633GC_StringTableIterator stringTableIterator(stringTable->getTable(tableIndex));634J9Object **slot = NULL;635while (NULL != (slot = (J9Object **)stringTableIterator.nextSlot())) {636doStringTableSlot(slot, &stringTableIterator);637}638}639}640}641642if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {643j9object_t *stringCacheTable = stringTable->getStringInternCache();644UDATA cacheTableIndex = 0;645for (; cacheTableIndex < MM_StringTable::getCacheSize(); cacheTableIndex++) {646doStringCacheTableSlot(&stringCacheTable[cacheTableIndex]);647}648}649650reportScanningEnded(RootScannerEntity_StringTable);651}652653/**654* Scan the weak reference list.655* @note Extra locking for NHRTs can be omitted, because it is impossible for656* an NHRT to create a reference object that will live longer than its referent;657* thus reference objects created by NHRTs do not need to go on the list.658*/659void660MM_RootScanner::scanWeakReferenceObjects(MM_EnvironmentBase *env)661{662}663664/**665* Scan the soft reference list.666* @note Extra locking for NHRTs can be omitted, because it is impossible for667* an NHRT to create a reference object that will live longer than its referent;668* thus reference objects created by NHRTs do not need to go on the list.669*/670void671MM_RootScanner::scanSoftReferenceObjects(MM_EnvironmentBase *env)672{673}674675/**676* Scan the phantom reference list.677* @note Extra locking for NHRTs can be omitted, because it is impossible for678* an NHRT to create a reference object that will live longer than its referent;679* thus reference objects created by NHRTs do not need to go on the list.680*/681void682MM_RootScanner::scanPhantomReferenceObjects(MM_EnvironmentBase *env)683{684}685686#if defined(J9VM_GC_FINALIZATION)687/**688* @todo Provide function documentation689*690* @NOTE this can only be used as a READ-ONLY version of the unfinalizedObjectList.691* If you need to modify elements with-in the list you will need to provide your own functionality.692* See MM_MarkingScheme::scanUnfinalizedObjects(MM_EnvironmentStandard *env) as an example693* which modifies elements within the list.694*/695void696MM_RootScanner::scanUnfinalizedObjects(MM_EnvironmentBase *env)697{698reportScanningStarted(RootScannerEntity_UnfinalizedObjects);699700MM_ObjectAccessBarrier *barrier = _extensions->accessBarrier;701MM_UnfinalizedObjectList *unfinalizedObjectList = _extensions->unfinalizedObjectLists;702while(NULL != unfinalizedObjectList) {703if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {704J9Object *objectPtr = unfinalizedObjectList->getHeadOfList();705while (NULL != objectPtr) {706doUnfinalizedObject(objectPtr, unfinalizedObjectList);707objectPtr = barrier->getFinalizeLink(objectPtr);708}709}710unfinalizedObjectList = unfinalizedObjectList->getNextList();711}712713reportScanningEnded(RootScannerEntity_UnfinalizedObjects);714}715#endif /* J9VM_GC_FINALIZATION */716717void718MM_RootScanner::scanOwnableSynchronizerObjects(MM_EnvironmentBase *env)719{720reportScanningStarted(RootScannerEntity_OwnableSynchronizerObjects);721722MM_ObjectAccessBarrier *barrier = _extensions->accessBarrier;723MM_OwnableSynchronizerObjectList *ownableSynchronizerObjectList = _extensions->getOwnableSynchronizerObjectLists();724while(NULL != ownableSynchronizerObjectList) {725if (_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {726J9Object *objectPtr = ownableSynchronizerObjectList->getHeadOfList();727while (NULL != objectPtr) {728doOwnableSynchronizerObject(objectPtr, ownableSynchronizerObjectList);729objectPtr = barrier->getOwnableSynchronizerLink(objectPtr);730}731}732ownableSynchronizerObjectList = ownableSynchronizerObjectList->getNextList();733}734735reportScanningEnded(RootScannerEntity_OwnableSynchronizerObjects);736}737738/**739* Scan the per-thread object monitor lookup caches.740* Note that this is not a root since the cache contains monitors from the global monitor table741* which will be scanned by scanMonitorReferences. It should be scanned first, however, since742* scanMonitorReferences may destroy monitors that appear in caches.743*/744void745MM_RootScanner::scanMonitorLookupCaches(MM_EnvironmentBase *env)746{747reportScanningStarted(RootScannerEntity_MonitorLookupCaches);748GC_VMThreadListIterator vmThreadListIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm));749while (J9VMThread *walkThread = vmThreadListIterator.nextVMThread()) {750if (_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {751j9objectmonitor_t *objectMonitorLookupCache = walkThread->objectMonitorLookupCache;752UDATA cacheIndex = 0;753for (; cacheIndex < J9VMTHREAD_OBJECT_MONITOR_CACHE_SIZE; cacheIndex++) {754doMonitorLookupCacheSlot(&objectMonitorLookupCache[cacheIndex]);755}756}757}758reportScanningEnded(RootScannerEntity_MonitorLookupCaches);759}760761/**762* @todo Provide function documentation763*/764void765MM_RootScanner::scanMonitorReferences(MM_EnvironmentBase *env)766{767reportScanningStarted(RootScannerEntity_MonitorReferences);768769J9ObjectMonitor *objectMonitor = NULL;770J9MonitorTableListEntry *monitorTableList = static_cast<J9JavaVM*>(_omrVM->_language_vm)->monitorTableList;771while (NULL != monitorTableList) {772J9HashTable *table = monitorTableList->monitorTable;773if (NULL != table) {774if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {775GC_HashTableIterator iterator(table);776while (NULL != (objectMonitor = (J9ObjectMonitor *)iterator.nextSlot())) {777doMonitorReference(objectMonitor, &iterator);778}779}780}781monitorTableList = monitorTableList->next;782}783784reportScanningEnded(RootScannerEntity_MonitorReferences);785}786787/**788* @todo Provide function documentation789*/790void791MM_RootScanner::scanJNIWeakGlobalReferences(MM_EnvironmentBase *env)792{793if (_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {794reportScanningStarted(RootScannerEntity_JNIWeakGlobalReferences);795796GC_JNIWeakGlobalReferenceIterator jniWeakGlobalReferenceIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm)->jniWeakGlobalReferences);797J9Object **slot;798799while((slot = (J9Object **)jniWeakGlobalReferenceIterator.nextSlot()) != NULL) {800doJNIWeakGlobalReference(slot);801}802803reportScanningEnded(RootScannerEntity_JNIWeakGlobalReferences);804}805}806807#if defined(J9VM_GC_MODRON_SCAVENGER)808/**809* @todo Provide function documentation810*/811void812MM_RootScanner::scanRememberedSet(MM_EnvironmentBase *env)813{814if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {815reportScanningStarted(RootScannerEntity_RememberedSet);816817MM_SublistPuddle *puddle;818J9Object **slotPtr;819GC_RememberedSetIterator rememberedSetIterator(&_extensions->rememberedSet);820821while((puddle = rememberedSetIterator.nextList()) != NULL) {822GC_RememberedSetSlotIterator rememberedSetSlotIterator(puddle);823while((slotPtr = (J9Object **)rememberedSetSlotIterator.nextSlot()) != NULL) {824doRememberedSetSlot(slotPtr, &rememberedSetSlotIterator);825}826}827828reportScanningEnded(RootScannerEntity_RememberedSet);829}830}831#endif /* J9VM_GC_MODRON_SCAVENGER */832833#if defined(J9VM_OPT_JVMTI)834/**835* Scan the JVMTI tag tables for object references836*/837void838MM_RootScanner::scanJVMTIObjectTagTables(MM_EnvironmentBase *env)839{840if(_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {841reportScanningStarted(RootScannerEntity_JVMTIObjectTagTables);842843J9JVMTIData * jvmtiData = J9JVMTI_DATA_FROM_VM(static_cast<J9JavaVM*>(_omrVM->_language_vm));844J9JVMTIEnv * jvmtiEnv;845J9Object **slotPtr;846if (NULL != jvmtiData) {847/* TODO: When JVMTI is supported in RTSJ, this structure needs to be locked848* when it is being scanned849*/850GC_JVMTIObjectTagTableListIterator objectTagTableList(jvmtiData->environments);851while(NULL != (jvmtiEnv = (J9JVMTIEnv *)objectTagTableList.nextSlot())) {852if (NULL != jvmtiEnv->objectTagTable) {853GC_JVMTIObjectTagTableIterator objectTagTableIterator(jvmtiEnv->objectTagTable);854while(NULL != (slotPtr = (J9Object **)objectTagTableIterator.nextSlot())) {855doJVMTIObjectTagSlot(slotPtr, &objectTagTableIterator);856}857}858}859}860861reportScanningEnded(RootScannerEntity_JVMTIObjectTagTables);862}863}864#endif /* J9VM_OPT_JVMTI */865866#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)867void868MM_RootScanner::scanDoubleMappedObjects(MM_EnvironmentBase *env)869{870if (_singleThread || J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {871GC_HeapRegionIteratorVLHGC regionIterator(_extensions->heap->getHeapRegionManager());872MM_HeapRegionDescriptorVLHGC *region = NULL;873reportScanningStarted(RootScannerEntity_DoubleMappedObjects);874while (NULL != (region = regionIterator.nextRegion())) {875if (region->isArrayletLeaf()) {876J9Object *spineObject = (J9Object *)region->_allocateData.getSpine();877Assert_MM_true(NULL != spineObject);878J9PortVmemIdentifier *arrayletDoublemapID = ®ion->_arrayletDoublemapID;879if (NULL != arrayletDoublemapID->address) {880doDoubleMappedObjectSlot(spineObject, arrayletDoublemapID);881}882}883}884reportScanningEnded(RootScannerEntity_DoubleMappedObjects);885}886}887#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */888889/**890* Scan all root set references from the VM into the heap.891* For all slots that are hard root references into the heap, the appropriate slot handler will be called.892* @note This includes all references to classes.893*/894void895MM_RootScanner::scanRoots(MM_EnvironmentBase *env)896{897if (_classDataAsRoots || _nurseryReferencesOnly || _nurseryReferencesPossibly) {898/* The classLoaderObject of a class loader might be in the nursery, but a class loader899* can never be in the remembered set, so include class loaders here.900*/901scanClassLoaders(env);902}903904if (!_nurseryReferencesOnly && !_nurseryReferencesPossibly) {905#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)906if (_classDataAsRoots) {907#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */908scanClasses(env);909/* We are scanning all classes, no need to include stack frame references */910setIncludeStackFrameClassReferences(false);911#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)912} else {913scanPermanentClasses(env);914setIncludeStackFrameClassReferences(true);915}916#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */917918if(complete_phase_ABORT == scanClassesComplete(env)) {919return ;920}921}922923scanThreads(env);924#if defined(J9VM_GC_FINALIZATION)925scanFinalizableObjects(env);926#endif /* J9VM_GC_FINALIZATION */927scanJNIGlobalReferences(env);928929if (_jniWeakGlobalReferencesTableAsRoot) {930/* JNI Weak Global References table should be scanned as a hard root */931scanJNIWeakGlobalReferences(env);932}933934/* In the RT configuration, We can skip scanning the string table because935all interned strings are in immortal memory and will not move. */936if(_stringTableAsRoot && (!_nurseryReferencesOnly && !_nurseryReferencesPossibly)){937scanStringTable(env);938}939}940941/**942* Scan all clearable root set references from the VM into the heap.943* For all slots that are clearable root references into the heap, the appropriate slot handler will be944* called.945* @note This includes all references to classes.946*/947void948MM_RootScanner::scanClearable(MM_EnvironmentBase *env)949{950/* This may result in more marking, if aged soft references could not be enqueued. */951scanSoftReferenceObjects(env);952if(complete_phase_ABORT == scanSoftReferencesComplete(env)) {953return ;954}955956scanWeakReferenceObjects(env);957if(complete_phase_ABORT == scanWeakReferencesComplete(env)) {958return ;959}960961#if defined(J9VM_GC_FINALIZATION)962/* This may result in more marking, but any weak references963* must be cleared before, or at the same time as, the referent964* is moved to the finalizable list.965*/966scanUnfinalizedObjects(env);967if(complete_phase_ABORT == scanUnfinalizedObjectsComplete(env)) {968return ;969}970#endif /* J9VM_GC_FINALIZATION */971972if (!_jniWeakGlobalReferencesTableAsRoot) {973/* Skip Clearable phase if it was treated as a hard root already */974scanJNIWeakGlobalReferences(env);975}976977scanPhantomReferenceObjects(env);978if(complete_phase_ABORT == scanPhantomReferencesComplete(env)) {979return ;980}981982/*983* clear the following private references once resurrection is completed984*/985scanMonitorLookupCaches(env);986scanMonitorReferences(env);987if(complete_phase_ABORT == scanMonitorReferencesComplete(env)) {988return ;989}990991if(!_stringTableAsRoot && (!_nurseryReferencesOnly && !_nurseryReferencesPossibly)) {992scanStringTable(env);993}994995scanOwnableSynchronizerObjects(env);996997#if defined(J9VM_GC_MODRON_SCAVENGER)998/* Remembered set is clearable in a generational system -- if an object in old999* space dies, and it pointed to an object in new space, it needs to be removed1000* from the remembered set.1001* This must after any other marking might occur, e.g. phantom references.1002*/1003if(_includeRememberedSetReferences && !_nurseryReferencesOnly && !_nurseryReferencesPossibly) {1004scanRememberedSet(env);1005}1006#endif /* J9VM_GC_MODRON_SCAVENGER */10071008#if defined(J9VM_OPT_JVMTI)1009if(_includeJVMTIObjectTagTables) {1010scanJVMTIObjectTagTables(env);1011}1012#endif /* J9VM_OPT_JVMTI */10131014#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)1015if (_includeDoubleMap) {1016scanDoubleMappedObjects(env);1017}1018#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */1019}10201021/**1022* Scan all slots which contain references into the heap.1023* @note this includes class references.1024*/1025void1026MM_RootScanner::scanAllSlots(MM_EnvironmentBase *env)1027{1028if(!_nurseryReferencesOnly && !_nurseryReferencesPossibly) {1029scanClasses(env);1030scanVMClassSlots(env);1031}10321033scanClassLoaders(env);10341035scanThreads(env);1036#if defined(J9VM_GC_FINALIZATION)1037scanFinalizableObjects(env);1038#endif /* J9VM_GC_FINALIZATION */1039scanJNIGlobalReferences(env);10401041if(!_nurseryReferencesOnly && !_nurseryReferencesPossibly) {1042scanStringTable(env);1043}10441045scanWeakReferenceObjects(env);1046scanSoftReferenceObjects(env);1047scanPhantomReferenceObjects(env);10481049#if defined(J9VM_GC_FINALIZATION)1050scanUnfinalizedObjects(env);1051#endif /* J9VM_GC_FINALIZATION */10521053scanMonitorReferences(env);1054scanJNIWeakGlobalReferences(env);10551056#if defined(J9VM_GC_MODRON_SCAVENGER)1057if(_includeRememberedSetReferences && !_nurseryReferencesOnly && !_nurseryReferencesPossibly) {1058scanRememberedSet(env);1059}1060#endif /* J9VM_GC_MODRON_SCAVENGER */10611062#if defined(J9VM_OPT_JVMTI)1063if(_includeJVMTIObjectTagTables) {1064scanJVMTIObjectTagTables(env);1065}1066#endif /* J9VM_OPT_JVMTI */10671068#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)1069if (_includeDoubleMap) {1070scanDoubleMappedObjects(env);1071}1072#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */10731074scanOwnableSynchronizerObjects(env);1075}10761077bool1078MM_RootScanner::shouldYieldFromClassScan(UDATA timeSlackNanoSec)1079{1080return false;1081}10821083bool1084MM_RootScanner::shouldYieldFromStringScan()1085{1086return false;1087}10881089bool1090MM_RootScanner::shouldYieldFromMonitorScan()1091{1092return false;1093}10941095bool1096MM_RootScanner::shouldYield()1097{1098return false;1099}11001101void1102MM_RootScanner::yield()1103{1104}11051106bool1107MM_RootScanner::condYield(U_64 timeSlackNanoSec)1108{1109bool yielded = shouldYield();11101111if (yielded) {1112yield();1113}11141115return yielded;1116}111711181119