Path: blob/master/runtime/gc_glue_java/ConcurrentMarkingDelegate.cpp
5985 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 "ConcurrentMarkingDelegate.hpp"23#if defined(OMR_GC_MODRON_CONCURRENT_MARK)24#include "AsyncCallbackHandler.hpp"25#include "ClassLoaderIterator.hpp"26#include "ConfigurationDelegate.hpp"27#include "FinalizeListManager.hpp"28#include "Heap.hpp"29#include "HeapRegionDescriptorStandard.hpp"30#include "HeapRegionIteratorStandard.hpp"31#include "ReferenceObjectList.hpp"32#include "StackSlotValidator.hpp"33#include "VMInterface.hpp"34#include "VMThreadListIterator.hpp"3536/**37* Concurrents stack slot iterator.38* Called for each slot in a threads active stack frames which contains a object reference.39*40* @param objectIndirect41* @param localdata42* @param isDerivedPointer43* @param objectIndirectBase44*/45void46concurrentStackSlotIterator(J9JavaVM *javaVM, omrobjectptr_t *objectIndirect, void *localData, J9StackWalkState *walkState, const void *stackLocation)47{48MM_ConcurrentMarkingDelegate::markSchemeStackIteratorData *data = (MM_ConcurrentMarkingDelegate::markSchemeStackIteratorData *)localData;4950omrobjectptr_t object = *objectIndirect;51if (data->env->getExtensions()->heap->objectIsInGap(object)) {52/* 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 */53Assert_MM_validStackSlot(MM_StackSlotValidator(MM_StackSlotValidator::NOT_ON_HEAP, object, stackLocation, walkState).validate(data->env));54} else if (data->markingScheme->isHeapObject(object)) {55/* heap object - validate and mark */56Assert_MM_validStackSlot(MM_StackSlotValidator(0, object, stackLocation, walkState).validate(data->env));57data->markingScheme->markObject(data->env, object);58} else if (NULL != object) {59/* stack object - just validate */60Assert_MM_validStackSlot(MM_StackSlotValidator(MM_StackSlotValidator::NOT_ON_HEAP, object, stackLocation, walkState).validate(data->env));61}62}6364bool65MM_ConcurrentMarkingDelegate::initialize(MM_EnvironmentBase *env, MM_ConcurrentGC *collector)66{67MM_GCExtensionsBase *extensions = env->getExtensions();68_javaVM = (J9JavaVM *)extensions->getOmrVM()->_language_vm;69_objectModel = &(extensions->objectModel);70_markingScheme = collector->getMarkingScheme();71_collector = collector;72return true;73}7475void76MM_ConcurrentMarkingDelegate::signalThreadsToTraceStacks(MM_EnvironmentBase *env)77{78uintptr_t threadCount = 0;7980MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);81GC_VMInterface::lockVMThreadList(extensions);8283GC_VMThreadListIterator vmThreadListIterator(_javaVM);84J9VMThread *walkThread;8586while((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {87MM_AsyncCallbackHandler::signalThreadForCallback(walkThread);88threadCount += 1;89}90GC_VMInterface::unlockVMThreadList(extensions);9192_collector->getConcurrentGCStats()->setThreadsToScanCount(threadCount);93}9495void96MM_ConcurrentMarkingDelegate::signalThreadsToActivateWriteBarrier(MM_EnvironmentBase *env)97{98MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);99GC_VMInterface::lockVMThreadList(extensions);100101J9VMThread *walkThread;102GC_VMThreadListIterator vmThreadListIterator(_javaVM);103while ((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {104walkThread->privateFlags |= J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE;105}106GC_VMInterface::unlockVMThreadList(extensions);107}108109void110MM_ConcurrentMarkingDelegate::signalThreadsToDeactivateWriteBarrier(MM_EnvironmentBase *env)111{112MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(_javaVM);113if (extensions->optimizeConcurrentWB) {114GC_VMInterface::lockVMThreadList(extensions);115GC_VMThreadListIterator vmThreadListIterator(_javaVM);116J9VMThread *walkThread;117118/* Reset vmThread flag so mutators don't dirty cards or run write barriers until next concurrent KO */119while ((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {120walkThread->privateFlags &= ~J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE;121}122GC_VMInterface::unlockVMThreadList(extensions);123}124}125126bool127MM_ConcurrentMarkingDelegate::scanThreadRoots(MM_EnvironmentBase *env)128{129J9VMThread *vmThread = (J9VMThread *)env->getLanguageVMThread();130Assert_GC_true_with_message(env, vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n",131_collector->getConcurrentGCStats()->getExecutionMode());132133GC_VMThreadIterator vmThreadIterator(vmThread);134omrobjectptr_t *slotPtr;135uintptr_t slotNum = 0;136while (NULL != (slotPtr = vmThreadIterator.nextSlot())) {137slotNum +=1;138if (!_collector->isExclusiveAccessRequestWaitingSparseSample(env, slotNum)) {139omrobjectptr_t objectPtr = *slotPtr;140if (_markingScheme->isHeapObject(objectPtr) && !env->getExtensions()->heap->objectIsInGap(objectPtr)) {141_markingScheme->markObject(env, objectPtr);142} else if (NULL != objectPtr) {143Assert_MM_true(vmthreaditerator_state_monitor_records == vmThreadIterator.getState());144}145} else {146break;147}148}149150markSchemeStackIteratorData localData;151localData.markingScheme = _markingScheme;152localData.env = env;153GC_VMThreadStackSlotIterator::scanSlots(vmThread, vmThread, (void *)&localData, concurrentStackSlotIterator, true, false);154155return true;156}157158/**159* Collect any JNI global references.160* Iterate over all JNI global references; mark and push any found.161*162*/163void164MM_ConcurrentMarkingDelegate::collectJNIRoots(MM_EnvironmentBase *env, bool *completedJNIRoots)165{166*completedJNIRoots = false;167168Assert_GC_true_with_message(env, ((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());169MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);170GC_VMInterface::lockJNIGlobalReferences(extensions);171GC_PoolIterator jniGlobalReferenceIterator(_javaVM->jniGlobalReferences);172omrobjectptr_t *slotPtr;173uintptr_t slotNum = 0;174while((slotPtr = (omrobjectptr_t *)jniGlobalReferenceIterator.nextSlot()) != NULL) {175slotNum += 1;176if (_collector->isExclusiveAccessRequestWaitingSparseSample(env, slotNum)) {177goto quitTracingJNIRefs;178} else {179_markingScheme->markObject(env, *slotPtr);180}181}182183*completedJNIRoots = true;184185quitTracingJNIRefs:186GC_VMInterface::unlockJNIGlobalReferences(extensions);187}188189/**190* Collect any roots in classes191* Iterate over all classes and mark and push all references192*193*/194void195MM_ConcurrentMarkingDelegate::collectClassRoots(MM_EnvironmentBase *env, bool *completedClassRoots, bool *classesMarkedAsRoots)196{197*completedClassRoots = false;198*classesMarkedAsRoots = false;199MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);200201if (!setupClassScanning(env)) {202/* mark classes as roots, scanning classes is disabled by default */203*classesMarkedAsRoots = true;204205Assert_GC_true_with_message(env, ((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());206207GC_VMInterface::lockClasses(extensions);208209GC_SegmentIterator segmentIterator(_javaVM->classMemorySegments, MEMORY_TYPE_RAM_CLASS);210J9MemorySegment *segment;211J9Class *clazz;212213while((segment = segmentIterator.nextSegment()) != NULL) {214GC_ClassHeapIterator classHeapIterator(_javaVM, segment);215while((clazz = classHeapIterator.nextClass()) != NULL) {216if (env->isExclusiveAccessRequestWaiting()) {217goto quitMarkClasses;218} else {219_markingScheme->getMarkingDelegate()->scanClass(env, clazz);220}221}222}223224*completedClassRoots = true;225226quitMarkClasses:227GC_VMInterface::unlockClasses(extensions);228}229}230231/**232* Mark all finalizable objects233* Iterate over finalizable list and mark and push all finalizable objects234*235*/236void237MM_ConcurrentMarkingDelegate::collectFinalizableRoots(MM_EnvironmentBase *env, bool *completedFinalizableRoots)238{239*completedFinalizableRoots = false;240241Assert_GC_true_with_message(env, ((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());242243MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);244GC_VMInterface::lockFinalizeList(extensions);245246GC_FinalizeListManager * finalizeListManager = extensions->finalizeListManager;247{248/* walk finalizable objects created by the system class loader */249j9object_t systemObject = finalizeListManager->peekSystemFinalizableObject();250while (!env->isExclusiveAccessRequestWaiting() && (NULL != systemObject)) {251_markingScheme->markObject(env, systemObject);252systemObject = finalizeListManager->peekNextSystemFinalizableObject(systemObject);253}254}255256{257/* walk finalizable objects created by all other class loaders*/258j9object_t defaultObject = finalizeListManager->peekDefaultFinalizableObject();259while (!env->isExclusiveAccessRequestWaiting() && (NULL != defaultObject)) {260_markingScheme->markObject(env, defaultObject);261defaultObject = finalizeListManager->peekNextDefaultFinalizableObject(defaultObject);262}263}264265{266/* walk reference objects */267j9object_t referenceObject = finalizeListManager->peekReferenceObject();268while (!env->isExclusiveAccessRequestWaiting() && (NULL != referenceObject)) {269_markingScheme->markObject(env, referenceObject);270referenceObject = finalizeListManager->peekNextReferenceObject(referenceObject);271}272}273274*completedFinalizableRoots = !env->isExclusiveAccessRequestWaiting();275276GC_VMInterface::unlockFinalizeList(extensions);277}278279/**280* Collect all roots in string table281* Iterate over string table and mark and push all strings282*283*/284void285MM_ConcurrentMarkingDelegate::collectStringRoots(MM_EnvironmentBase *env, bool *completedStringRoots, bool *collectedStringRoots)286{287*completedStringRoots = false;288MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);289*collectedStringRoots = !extensions->collectStringConstants;290if (*collectedStringRoots) {291/* CMVC 103513 - Do not mark strings as roots if extensions->collectStringConstants is set292* since this will not allow them to be collected unless the concurrent mark is aborted293* before we hit this point.294*/295MM_StringTable *stringTable = extensions->getStringTable();296297Assert_GC_true_with_message(env, ((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());298299for (uintptr_t tableIndex = 0; tableIndex < stringTable->getTableCount(); tableIndex++) {300301stringTable->lockTable(tableIndex);302303GC_HashTableIterator stringTableIterator(stringTable->getTable(tableIndex));304omrobjectptr_t* slotPtr;305306while((slotPtr = (omrobjectptr_t *)stringTableIterator.nextSlot()) != NULL) {307if (env->isExclusiveAccessRequestWaiting()) {308stringTable->unlockTable(tableIndex);309goto quitMarkStrings;310} else {311_markingScheme->markObject(env, *slotPtr);312}313}314315stringTable->unlockTable(tableIndex);316}317318*completedStringRoots = true;319}320321quitMarkStrings:322return;323}324325void326MM_ConcurrentMarkingDelegate::abortCollection(MM_EnvironmentBase *env)327{328MM_HeapRegionDescriptorStandard *region = NULL;329GC_HeapRegionIteratorStandard regionIterator(env->getExtensions()->heap->getHeapRegionManager());330331while(NULL != (region = regionIterator.nextRegion())) {332MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);333for (uintptr_t i = 0; i < regionExtension->_maxListIndex; i++) {334MM_ReferenceObjectList *list = ®ionExtension->_referenceObjectLists[i];335list->resetLists();336}337}338}339340341bool342MM_ConcurrentMarkingDelegate::setupClassScanning(MM_EnvironmentBase *env)343{344#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)345MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);346MM_GCExtensions::DynamicClassUnloading dynamicClassUnloadingFlag = (MM_GCExtensions::DynamicClassUnloading )extensions->dynamicClassUnloading;347if (MM_GCExtensions::DYNAMIC_CLASS_UNLOADING_NEVER != dynamicClassUnloadingFlag) {348setConcurrentScanning(env);349return true;350}351#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */352353return false;354}355356#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)357uintptr_t358MM_ConcurrentMarkingDelegate::concurrentClassMark(MM_EnvironmentBase *env, bool *completedClassMark)359{360J9ClassLoader *classLoader;361uintptr_t sizeTraced = 0;362*completedClassMark = false;363364Trc_MM_concurrentClassMarkStart(env->getLanguageVMThread());365366MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);367368Assert_GC_true_with_message(env, (((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE) || (extensions->isSATBBarrierActive()), "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());369370GC_VMInterface::lockClasses(extensions);371GC_VMInterface::lockClassLoaders(extensions);372373MM_MarkingDelegate *markingDelegate = _markingScheme->getMarkingDelegate();374GC_ClassLoaderIterator classLoaderIterator(_javaVM->classLoaderBlocks);375while((classLoader = classLoaderIterator.nextSlot()) != NULL) {376/* skip dead and anonymous classloaders */377if ((0 == (classLoader->gcFlags & J9_GC_CLASS_LOADER_DEAD)) && (0 == (classLoader->flags & J9CLASSLOADER_ANON_CLASS_LOADER))) {378/* Check if the class loader has not been scanned but the class loader is live */379if( !(classLoader->gcFlags & J9_GC_CLASS_LOADER_SCANNED) && _markingScheme->isMarkedOutline(classLoader->classLoaderObject)) {380GC_ClassLoaderSegmentIterator segmentIterator(classLoader, MEMORY_TYPE_RAM_CLASS);381J9MemorySegment *segment = NULL;382J9Class *clazz;383384while(NULL != (segment = segmentIterator.nextSegment())) {385GC_ClassHeapIterator classHeapIterator(_javaVM, segment);386while(NULL != (clazz = classHeapIterator.nextClass())) {387/* TODO CRGTMP investigate proper value here */388sizeTraced += sizeof(J9Class);389markingDelegate->scanClass(env, clazz);390if (env->isExclusiveAccessRequestWaiting()) { /* interrupt if exclusive access request is waiting */391goto quitConcurrentClassMark;392}393}394}395396/* CMVC 131487 */397J9HashTableState walkState;398/*399* We believe that (NULL == classLoader->classHashTable) is set ONLY for DEAD class loader400* so, if this pointer happened to be NULL at this point let it crash here401*/402Assert_MM_true(NULL != classLoader->classHashTable);403clazz = _javaVM->internalVMFunctions->hashClassTableStartDo(classLoader, &walkState, 0);404while (NULL != clazz) {405sizeTraced += sizeof(uintptr_t);406_markingScheme->markObject(env, (j9object_t)clazz->classObject);407if (env->isExclusiveAccessRequestWaiting()) { /* interrupt if exclusive access request is waiting */408goto quitConcurrentClassMark;409}410clazz = _javaVM->internalVMFunctions->hashClassTableNextDo(&walkState);411}412413if (NULL != classLoader->moduleHashTable) {414J9HashTableState moduleWalkState;415J9Module **modulePtr = (J9Module**)hashTableStartDo(classLoader->moduleHashTable, &moduleWalkState);416while (NULL != modulePtr) {417J9Module * const module = *modulePtr;418419_markingScheme->markObject(env, (j9object_t)module->moduleObject);420if (NULL != module->moduleName) {421_markingScheme->markObject(env, (j9object_t)module->moduleName);422}423if (NULL != module->version) {424_markingScheme->markObject(env, (j9object_t)module->version);425}426if (env->isExclusiveAccessRequestWaiting()) { /* interrupt if exclusive access request is waiting */427goto quitConcurrentClassMark;428}429modulePtr = (J9Module**)hashTableNextDo(&moduleWalkState);430}431432if (classLoader == _javaVM->systemClassLoader) {433_markingScheme->markObject(env, _javaVM->unamedModuleForSystemLoader->moduleObject);434}435}436437classLoader->gcFlags |= J9_GC_CLASS_LOADER_SCANNED;438}439}440}441442*completedClassMark = true;443444quitConcurrentClassMark:445GC_VMInterface::unlockClassLoaders(extensions);446GC_VMInterface::unlockClasses(extensions);447448return sizeTraced;449}450#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */451452#endif /* defined(OMR_GC_MODRON_CONCURRENT_MARK) */453454455