Path: blob/master/runtime/gc_glue_java/MarkingSchemeRootClearer.cpp
5985 views
1/*******************************************************************************2* Copyright (c) 1991, 2020 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* 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-exception21*******************************************************************************/2223#include "j9.h"24#include "j9cfg.h"25#include "j9consts.h"2627#if defined(J9VM_GC_FINALIZATION)28#include "CollectorLanguageInterfaceImpl.hpp"29#endif /* defined(J9VM_GC_FINALIZATION) */30#include "ConfigurationDelegate.hpp"31#include "EnvironmentBase.hpp"32#include "FinalizableObjectBuffer.hpp"33#include "FinalizableReferenceBuffer.hpp"34#include "GlobalCollector.hpp"35#include "Heap.hpp"36#include "HeapRegionDescriptorStandard.hpp"37#include "HeapRegionIteratorStandard.hpp"38#include "HeapRegionManager.hpp"39#include "MarkingScheme.hpp"40#include "MarkingSchemeRootClearer.hpp"41#include "ModronAssertions.h"42#include "OwnableSynchronizerObjectBuffer.hpp"43#include "ParallelDispatcher.hpp"44#include "ReferenceObjectBuffer.hpp"45#include "ReferenceStats.hpp"46#include "RootScanner.hpp"47#include "StackSlotValidator.hpp"48#include "UnfinalizedObjectBuffer.hpp"4950void51MM_MarkingSchemeRootClearer::doSlot(omrobjectptr_t *slotPtr)52{53Assert_MM_unreachable();54}5556void57MM_MarkingSchemeRootClearer::doClass(J9Class *clazz)58{59Assert_MM_unreachable();60}6162void63MM_MarkingSchemeRootClearer::doFinalizableObject(omrobjectptr_t object)64{65Assert_MM_unreachable();66}6768void69MM_MarkingSchemeRootClearer::scanWeakReferenceObjects(MM_EnvironmentBase *env)70{71reportScanningStarted(RootScannerEntity_WeakReferenceObjects);72GC_Environment *gcEnv = env->getGCEnvironment();73Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());7475MM_HeapRegionDescriptorStandard *region = NULL;76GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());77while (NULL != (region = regionIterator.nextRegion())) {78MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);79/* NOTE: we can't look at the list to determine if there's work to do since another thread may have already processed it and deleted everything */80for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {81if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {82MM_ReferenceObjectList *list = ®ionExtension->_referenceObjectLists[i];83list->startWeakReferenceProcessing();84if (!list->wasWeakListEmpty()) {85_markingDelegate->processReferenceList(env, region, list->getPriorWeakList(), &gcEnv->_markJavaStats._weakReferenceStats);86}87}88}89}9091Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());92reportScanningEnded(RootScannerEntity_WeakReferenceObjects);93}9495MM_RootScanner::CompletePhaseCode96MM_MarkingSchemeRootClearer::scanWeakReferencesComplete(MM_EnvironmentBase *env)97{98/* No new objects could have been discovered by soft / weak reference processing,99* but we must complete this phase prior to unfinalized processing to ensure that100* finalizable referents get cleared */101env->_currentTask->synchronizeGCThreads(env, UNIQUE_ID);102return complete_phase_OK;103}104105void106MM_MarkingSchemeRootClearer::scanSoftReferenceObjects(MM_EnvironmentBase *env)107{108reportScanningStarted(RootScannerEntity_SoftReferenceObjects);109GC_Environment *gcEnv = env->getGCEnvironment();110Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());111112MM_HeapRegionDescriptorStandard *region = NULL;113GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());114while (NULL != (region = regionIterator.nextRegion())) {115MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);116/* NOTE: we can't look at the list to determine if there's work to do since another thread may have already processed it and deleted everything */117for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {118if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {119MM_ReferenceObjectList *list = ®ionExtension->_referenceObjectLists[i];120list->startSoftReferenceProcessing();121if (!list->wasSoftListEmpty()) {122_markingDelegate->processReferenceList(env, region, list->getPriorSoftList(), &gcEnv->_markJavaStats._softReferenceStats);123}124}125}126}127128Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());129reportScanningEnded(RootScannerEntity_SoftReferenceObjects);130}131132MM_RootScanner::CompletePhaseCode133MM_MarkingSchemeRootClearer::scanSoftReferencesComplete(MM_EnvironmentBase *env)134{135/* do nothing -- no new objects could have been discovered by soft reference processing */136return complete_phase_OK;137}138139void140MM_MarkingSchemeRootClearer::scanPhantomReferenceObjects(MM_EnvironmentBase *env)141{142reportScanningStarted(RootScannerEntity_PhantomReferenceObjects);143144/* ensure that all _referenceObjectBuffers are flushed before phantom references145* are processed since scanning unfinalizedObjects may resurrect a phantom reference146*/147GC_Environment *gcEnv = env->getGCEnvironment();148gcEnv->_referenceObjectBuffer->flush(env);149env->_currentTask->synchronizeGCThreads(env, UNIQUE_ID);150151MM_HeapRegionDescriptorStandard *region = NULL;152GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());153while (NULL != (region = regionIterator.nextRegion())) {154MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);155/* NOTE: we can't look at the list to determine if there's work to do since another thread may have already processed it and deleted everything */156for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {157if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {158MM_ReferenceObjectList *list = ®ionExtension->_referenceObjectLists[i];159list->startPhantomReferenceProcessing();160if (!list->wasPhantomListEmpty()) {161_markingDelegate->processReferenceList(env, region, list->getPriorPhantomList(), &gcEnv->_markJavaStats._phantomReferenceStats);162}163}164}165}166167Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());168reportScanningEnded(RootScannerEntity_PhantomReferenceObjects);169}170171MM_RootScanner::CompletePhaseCode172MM_MarkingSchemeRootClearer::scanPhantomReferencesComplete(MM_EnvironmentBase *env)173{174reportScanningStarted(RootScannerEntity_PhantomReferenceObjectsComplete);175if (env->_currentTask->synchronizeGCThreadsAndReleaseSingleThread(env, UNIQUE_ID)) {176env->_cycleState->_referenceObjectOptions |= MM_CycleState::references_clear_phantom;177env->_currentTask->releaseSynchronizedGCThreads(env);178}179/* phantom reference processing may resurrect objects - scan them now */180_markingScheme->completeMarking(env);181reportScanningEnded(RootScannerEntity_PhantomReferenceObjectsComplete);182return complete_phase_OK;183}184185void186MM_MarkingSchemeRootClearer::scanUnfinalizedObjects(MM_EnvironmentBase *env)187{188if (_markingDelegate->shouldScanUnfinalizedObjects()) {189/* allow the marking scheme to handle this */190reportScanningStarted(RootScannerEntity_UnfinalizedObjects);191GC_Environment *gcEnv = env->getGCEnvironment();192GC_FinalizableObjectBuffer buffer(_extensions);193#if defined(J9VM_GC_FINALIZATION)194bool finalizationRequired = false;195#endif /* defined(J9VM_GC_FINALIZATION) */196197MM_HeapRegionDescriptorStandard *region = NULL;198GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());199while (NULL != (region = regionIterator.nextRegion())) {200MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);201for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {202MM_UnfinalizedObjectList *list = ®ionExtension->_unfinalizedObjectLists[i];203if (!list->wasEmpty()) {204if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {205omrobjectptr_t object = list->getPriorList();206while (NULL != object) {207gcEnv->_markJavaStats._unfinalizedCandidates += 1;208omrobjectptr_t next = _extensions->accessBarrier->getFinalizeLink(object);209if (_markingScheme->inlineMarkObject(env, object)) {210/* object was not previously marked -- it is now finalizable so push it to the local buffer */211buffer.add(env, object);212gcEnv->_markJavaStats._unfinalizedEnqueued += 1;213#if defined(J9VM_GC_FINALIZATION)214/* inform global GC if finalization is required */215if (!finalizationRequired) {216MM_GlobalCollector *globalCollector = (MM_GlobalCollector *)_extensions->getGlobalCollector();217globalCollector->getGlobalCollectorDelegate()->setFinalizationRequired();218finalizationRequired = true;219}220#endif /* defined(J9VM_GC_FINALIZATION) */221} else {222/* object was already marked. It is still unfinalized */223gcEnv->_unfinalizedObjectBuffer->add(env, object);224}225object = next;226}227}228}229}230}231232/* Flush the local buffer of finalizable objects to the global list */233buffer.flush(env);234235/* restore everything to a flushed state before exiting */236gcEnv->_unfinalizedObjectBuffer->flush(env);237238reportScanningEnded(RootScannerEntity_UnfinalizedObjects);239}240}241242MM_RootScanner::CompletePhaseCode243MM_MarkingSchemeRootClearer::scanUnfinalizedObjectsComplete(MM_EnvironmentBase *env)244{245if (_markingDelegate->shouldScanUnfinalizedObjects()) {246reportScanningStarted(RootScannerEntity_UnfinalizedObjectsComplete);247/* ensure that all unfinalized processing is complete before we start marking additional objects */248env->_currentTask->synchronizeGCThreads(env, UNIQUE_ID);249/* TODO: consider relaxing completeMarking into completeScan (which will skip over 'complete class marking' step).250* This is to avoid potentially unnecessary sync point in class marking step. The class marking step that we do after251* phantom processing might be sufficient.252*/253_markingScheme->completeMarking(env);254reportScanningEnded(RootScannerEntity_UnfinalizedObjectsComplete);255}256return complete_phase_OK;257}258259void260MM_MarkingSchemeRootClearer::scanOwnableSynchronizerObjects(MM_EnvironmentBase *env)261{262if (_markingDelegate->shouldScanOwnableSynchronizerObjects()) {263/* allow the marking scheme to handle this */264reportScanningStarted(RootScannerEntity_OwnableSynchronizerObjects);265GC_Environment *gcEnv = env->getGCEnvironment();266267MM_HeapRegionDescriptorStandard *region = NULL;268GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());269while (NULL != (region = regionIterator.nextRegion())) {270MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);271for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {272MM_OwnableSynchronizerObjectList *list = ®ionExtension->_ownableSynchronizerObjectLists[i];273if (!list->wasEmpty()) {274if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {275omrobjectptr_t object = list->getPriorList();276while (NULL != object) {277gcEnv->_markJavaStats._ownableSynchronizerCandidates += 1;278omrobjectptr_t next = _extensions->accessBarrier->getOwnableSynchronizerLink(object);279if (_markingScheme->isMarked(object)) {280/* object was already marked. */281gcEnv->_ownableSynchronizerObjectBuffer->add(env, object);282} else {283/* object was not previously marked */284gcEnv->_markJavaStats._ownableSynchronizerCleared += 1;285}286object = next;287}288}289}290}291#if defined(J9VM_GC_MODRON_SCAVENGER)292/* correct scavenger statistics for ownableSynchronizerObjects, adjust survived ownableSynchronizerObject count in Nursery, only in generational gc */293if (_extensions->scavengerEnabled && (MEMORY_TYPE_NEW == (region->getTypeFlags() & MEMORY_TYPE_NEW))) {294gcEnv->_scavengerJavaStats.updateOwnableSynchronizerNurseryCounts(gcEnv->_markJavaStats._ownableSynchronizerCandidates - gcEnv->_markJavaStats._ownableSynchronizerCleared);295}296#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */297}298299/* restore everything to a flushed state before exiting */300gcEnv->_ownableSynchronizerObjectBuffer->flush(env);301reportScanningEnded(RootScannerEntity_OwnableSynchronizerObjects);302}303}304305void306MM_MarkingSchemeRootClearer::doMonitorReference(J9ObjectMonitor *objectMonitor, GC_HashTableIterator *monitorReferenceIterator)307{308J9ThreadAbstractMonitor * monitor = (J9ThreadAbstractMonitor*)objectMonitor->monitor;309_env->getGCEnvironment()->_markJavaStats._monitorReferenceCandidates += 1;310311if(!_markingScheme->isMarked((omrobjectptr_t )monitor->userData)) {312monitorReferenceIterator->removeSlot();313_env->getGCEnvironment()->_markJavaStats._monitorReferenceCleared += 1;314/* We must call objectMonitorDestroy (as opposed to omrthread_monitor_destroy) when the315* monitor is not internal to the GC */316static_cast<J9JavaVM*>(_omrVM->_language_vm)->internalVMFunctions->objectMonitorDestroy(static_cast<J9JavaVM*>(_omrVM->_language_vm), (J9VMThread *)_env->getLanguageVMThread(), (omrthread_monitor_t)monitor);317}318}319320MM_RootScanner::CompletePhaseCode321MM_MarkingSchemeRootClearer::scanMonitorReferencesComplete(MM_EnvironmentBase *env)322{323J9JavaVM *javaVM = (J9JavaVM *)env->getLanguageVM();324reportScanningStarted(RootScannerEntity_MonitorReferenceObjectsComplete);325javaVM->internalVMFunctions->objectMonitorDestroyComplete(javaVM, (J9VMThread *)env->getLanguageVMThread());326reportScanningEnded(RootScannerEntity_MonitorReferenceObjectsComplete);327return complete_phase_OK;328}329330void331MM_MarkingSchemeRootClearer::doJNIWeakGlobalReference(omrobjectptr_t *slotPtr)332{333omrobjectptr_t objectPtr = *slotPtr;334if ((NULL != objectPtr) && !_markingScheme->isMarked(objectPtr)) {335*slotPtr = NULL;336}337}338339void340MM_MarkingSchemeRootClearer::doRememberedSetSlot(omrobjectptr_t *slotPtr, GC_RememberedSetSlotIterator *rememberedSetSlotIterator)341{342omrobjectptr_t objectPtr = *slotPtr;343if (objectPtr == NULL) {344rememberedSetSlotIterator->removeSlot();345} else if (!_markingScheme->isMarked(objectPtr)) {346_extensions->objectModel.clearRemembered(objectPtr);347rememberedSetSlotIterator->removeSlot();348}349}350351void352MM_MarkingSchemeRootClearer::doStringTableSlot(omrobjectptr_t *slotPtr, GC_StringTableIterator *stringTableIterator)353{354_env->getGCEnvironment()->_markJavaStats._stringConstantsCandidates += 1;355if(!_markingScheme->isMarked(*slotPtr)) {356_env->getGCEnvironment()->_markJavaStats._stringConstantsCleared += 1;357stringTableIterator->removeSlot();358}359}360361/**362* @Clear the string table cache slot if the object is not marked363*/364void365MM_MarkingSchemeRootClearer::doStringCacheTableSlot(omrobjectptr_t *slotPtr)366{367omrobjectptr_t objectPtr = *slotPtr;368if((NULL != objectPtr) && (!_markingScheme->isMarked(*slotPtr))) {369*slotPtr = NULL;370}371}372373void374MM_MarkingSchemeRootClearer::doJVMTIObjectTagSlot(omrobjectptr_t *slotPtr, GC_JVMTIObjectTagTableIterator *objectTagTableIterator)375{376if(!_markingScheme->isMarked(*slotPtr)) {377objectTagTableIterator->removeSlot();378}379}380381382