Path: blob/master/runtime/gc_realtime/RealtimeMarkingScheme.cpp
5986 views
/*******************************************************************************1* Copyright (c) 1991, 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#include "omr.h"2324#include "CycleState.hpp"25#include "EnvironmentRealtime.hpp"26#include "RealtimeGC.hpp"27#include "RealtimeMarkingScheme.hpp"28#include "RealtimeMarkTask.hpp"2930/**31* Allocate and initialize a new instance of the receiver.32* @return a new instance of the receiver, or NULL on failure.33*/34MM_RealtimeMarkingScheme *35MM_RealtimeMarkingScheme::newInstance(MM_EnvironmentBase *env, MM_RealtimeGC *realtimeGC)36{37MM_RealtimeMarkingScheme *instance;3839instance = (MM_RealtimeMarkingScheme *)env->getForge()->allocate(sizeof(MM_RealtimeMarkingScheme), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());40if (instance) {41new(instance) MM_RealtimeMarkingScheme(env, realtimeGC);42if (!instance->initialize(env)) {43instance->kill(env);44instance = NULL;45}46}4748return instance;49}5051/**52* Free the receiver and all associated resources.53*/54void55MM_RealtimeMarkingScheme::kill(MM_EnvironmentBase *env)56{57tearDown(env);58env->getForge()->free(this);59}6061/**62* Intialize the RealtimeMarkingScheme instance.63*64*/65bool66MM_RealtimeMarkingScheme::initialize(MM_EnvironmentBase *env)67{68if (!MM_SegregatedMarkingScheme::initialize(env)) {69return false;70}7172_scheduler = _realtimeGC->_sched;7374return true;75}7677/**78* Teardown the RealtimeMarkingScheme instance.79*80*/81void82MM_RealtimeMarkingScheme::tearDown(MM_EnvironmentBase *env)83{84MM_SegregatedMarkingScheme::tearDown(env);85}8687void88MM_RealtimeMarkingScheme::markLiveObjectsInit(MM_EnvironmentBase *env, bool initMarkMap)89{90MM_EnvironmentRealtime *realtimeEnv = MM_EnvironmentRealtime::getEnvironment(env);91realtimeEnv->getWorkStack()->reset(realtimeEnv, _realtimeGC->_workPackets);9293/* These are thread-local stats that should probably be moved94* into the MM_MarkStats structure.95*/96realtimeEnv->resetScannedCounters();9798/* The write barrier must be enabled before any scanning begins. The double barrier will99* be enabled for the duration of the thread scans. It gets disabled on a per thread basis100* as the threads get scanned. It also gets "disabled" on a global basis once all threads101* are scanned.102*/103if (realtimeEnv->_currentTask->synchronizeGCThreadsAndReleaseMain(realtimeEnv, UNIQUE_ID)) {104_realtimeGC->enableWriteBarrier(realtimeEnv);105_realtimeGC->enableDoubleBarrier(realtimeEnv);106/* BEN TODO: Ragged barrier here */107realtimeEnv->_currentTask->releaseSynchronizedGCThreads(realtimeEnv);108}109}110111void112MM_RealtimeMarkingScheme::markLiveObjectsRoots(MM_EnvironmentBase *env)113{114MM_EnvironmentRealtime *realtimeEnv = MM_EnvironmentRealtime::getEnvironment(env);115MM_MetronomeDelegate *metronomeDelegate = _realtimeGC->getRealtimeDelegate();116117metronomeDelegate->markLiveObjectsRoots(realtimeEnv);118_scheduler->condYieldFromGC(realtimeEnv);119}120121void122MM_RealtimeMarkingScheme::markLiveObjectsScan(MM_EnvironmentBase *env)123{124MM_EnvironmentRealtime *realtimeEnv = MM_EnvironmentRealtime::getEnvironment(env);125MM_MetronomeDelegate *metronomeDelegate = _realtimeGC->getRealtimeDelegate();126127/* Heap Marking and barrier processing. Cannot delay barrier processing until the end.*/128_realtimeGC->completeMarking(realtimeEnv);129130metronomeDelegate->markLiveObjectsScan(realtimeEnv);131132if (realtimeEnv->_currentTask->synchronizeGCThreadsAndReleaseMain(realtimeEnv, UNIQUE_ID)) {133metronomeDelegate->setUnmarkedImpliesCleared();134realtimeEnv->_currentTask->releaseSynchronizedGCThreads(realtimeEnv);135}136}137138void139MM_RealtimeMarkingScheme::markLiveObjectsComplete(MM_EnvironmentBase *env)140{141MM_EnvironmentRealtime *realtimeEnv = MM_EnvironmentRealtime::getEnvironment(env);142MM_MetronomeDelegate *metronomeDelegate = _realtimeGC->getRealtimeDelegate();143144metronomeDelegate->markLiveObjectsComplete(realtimeEnv);145146_scheduler->condYieldFromGC(realtimeEnv);147148/* Do a final tracing phase to complete the marking phase. It should not be possible for any thread,149* including NHRT's, to add elements to the rememberedSet between the end of this completeMarking() call and when150* we disable the write barrier since the entire live set will be completed.151*/152_realtimeGC->completeMarking(realtimeEnv);153154metronomeDelegate->checkReferenceBuffer(realtimeEnv);155156if (realtimeEnv->_currentTask->synchronizeGCThreadsAndReleaseMain(realtimeEnv, UNIQUE_ID)) {157metronomeDelegate->unsetUnmarkedImpliesCleared();158159/* This is the symmetric call to the enabling of the write barrier that happens at the top of this method. */160_realtimeGC->disableWriteBarrier(realtimeEnv);161/* BEN TODO: Ragged barrier here */162163/* reset flag "overflow happened this GC cycle" */164_realtimeGC->_workPackets->getIncrementalOverflowHandler()->resetOverflowThisGCCycle();165166Assert_MM_true(_realtimeGC->_workPackets->isAllPacketsEmpty());167168realtimeEnv->_currentTask->releaseSynchronizedGCThreads(realtimeEnv);169}170}171172/**173* If maxCount == MAX_UNIT, we run till work stack is empty and we return true, if at least one174* object is marked.175* Otherwise, mark up to maxCount of objects. If we reached the limit return false, which means we are176* not finished yet.177*/178bool179MM_RealtimeMarkingScheme::incrementalCompleteScan(MM_EnvironmentRealtime *env, uintptr_t maxCount)180{181uintptr_t item;182uintptr_t count = 0, countSinceLastYieldCheck = 0;183uintptr_t scannedPointersSumSinceLastYieldCheck = 0;184185while(0 != (item = (uintptr_t)env->getWorkStack()->pop(env))) {186uintptr_t scannedPointers;187if (IS_ITEM_ARRAYLET(item)) {188fomrobject_t *arraylet = ITEM_TO_ARRAYLET(item);189scannedPointers = _realtimeGC->getRealtimeDelegate()->scanPointerArraylet(env, arraylet);190} else {191omrobjectptr_t objectPtr = ITEM_TO_OBJECT(item);192scannedPointers = _realtimeGC->getRealtimeDelegate()->scanObject(env, objectPtr);193}194195countSinceLastYieldCheck += 1;196scannedPointersSumSinceLastYieldCheck += scannedPointers;197198if (((countSinceLastYieldCheck * 2) + scannedPointersSumSinceLastYieldCheck) > _extensions->traceCostToCheckYield) {199_scheduler->condYieldFromGC(env);200201scannedPointersSumSinceLastYieldCheck = 0;202countSinceLastYieldCheck = 0;203}204205if (++count >= maxCount) {206return false;207}208}209210if (maxCount == MAX_UINT) {211return (count != 0);212} else {213return true;214}215}216217218219