Path: blob/master/runtime/gc_realtime/MemorySubSpaceMetronome.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2019 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"23#include "omrcfg.h"2425#include "AllocateDescription.hpp"26#include "Collector.hpp"27#include "EnvironmentRealtime.hpp"28#include "GCCode.hpp"29#include "MemoryPool.hpp"30#include "MemorySubSpace.hpp"31#include "MetronomeDelegate.hpp"32#include "Scheduler.hpp"33#include "RealtimeGC.hpp"3435#include "MemorySubSpaceMetronome.hpp"3637/**38* Allocation.39* @todo Provide class documentation40*/41void *42MM_MemorySubSpaceMetronome::allocateObject(MM_EnvironmentBase *env, MM_AllocateDescription *allocDescription, MM_MemorySubSpace *baseSubSpace, MM_MemorySubSpace *previousSubSpace, bool shouldCollectOnFailure)43{44void *result = NULL;4546if (shouldCollectOnFailure) {47result = allocateMixedObjectOrArraylet((MM_EnvironmentRealtime *)env, allocDescription, mixedObject);48} else {49/* not setting these object flags causes a failure working with empty arrays but where this is set should probably be hoisted into the caller */50allocDescription->setObjectFlags(getObjectFlags());51result = _memoryPoolSegregated->allocateObject(env, allocDescription);52}53return result;54}5556/**57* Allocate an arraylet leaf.58*/59void *60MM_MemorySubSpaceMetronome::allocateArrayletLeaf(MM_EnvironmentBase *env, MM_AllocateDescription *allocDescription, MM_MemorySubSpace *baseSubSpace, MM_MemorySubSpace *previousSubSpace, bool shouldCollectOnFailure)61{62omrarrayptr_t spine = allocDescription->getSpine();63/* spine object refers to the barrier-safe "object" reference, as opposed to the internal "heap address" represented by the spine variable */64omrobjectptr_t spineObject = (omrobjectptr_t)spine;65void *leaf = NULL;66if(env->saveObjects(spineObject)) {67leaf = allocateMixedObjectOrArraylet(env, allocDescription, arrayletLeaf);68env->restoreObjects(&spineObject);69spine = (omrarrayptr_t)spineObject;70allocDescription->setSpine(spine);71}72return leaf;73}7475void76MM_MemorySubSpaceMetronome::collectOnOOM(MM_EnvironmentBase *env, MM_GCCode gcCode, MM_AllocateDescription *allocDescription)77{78MM_EnvironmentRealtime *envRealtime = MM_EnvironmentRealtime::getEnvironment(env);79MM_GCExtensionsBase *ext = envRealtime->getExtensions();80MM_Scheduler *sched = (MM_Scheduler *)ext->dispatcher;8182if (sched->isInitialized()) {83sched->startGC(envRealtime);84sched->setGCCode(gcCode);85sched->continueGC(envRealtime, OUT_OF_MEMORY_TRIGGER, allocDescription->getBytesRequested(), env->getOmrVMThread(), true);86}87/* TODO CRGTMP remove call to yieldWhenRequested since continueGC blocks */88ext->realtimeGC->getRealtimeDelegate()->yieldWhenRequested(envRealtime);89}9091/**92* TODO: this is temporary as a way to avoid duplication of (badly written) code in MemorySubSpaceMetronome::allocate.93* We will specifically fix this allocate method in a separate design.94*/95void *96MM_MemorySubSpaceMetronome::allocateMixedObjectOrArraylet(MM_EnvironmentBase *env, MM_AllocateDescription *allocDescription, AllocateType allocType)97{98MM_EnvironmentRealtime *envRealtime = MM_EnvironmentRealtime::getEnvironment(env);99void *result;100101allocDescription->setObjectFlags(getObjectFlags());102103result = allocate(envRealtime, allocDescription, allocType);104if (NULL != result) {105return result;106}107108/* We failed to allocate the object so do a synchronous GC. This may complete the current GC */109collectOnOOM(envRealtime, MM_GCCode(J9MMCONSTANT_IMPLICIT_GC_DEFAULT), allocDescription);110111/* We completed a GC so try the allocate again */112result = allocate(envRealtime, allocDescription, allocType);113if (NULL != result) {114return result;115}116117/* Still failed to allocate so try another synchronous GC */118collectOnOOM(envRealtime, MM_GCCode(J9MMCONSTANT_IMPLICIT_GC_DEFAULT), allocDescription);119120/* We completed a GC so try the allocate again */121result = allocate(envRealtime, allocDescription, allocType);122if (NULL != result) {123return result;124}125126/* Still failed to allocate so try an aggressive synchronous GC */127collectOnOOM(envRealtime, MM_GCCode(J9MMCONSTANT_IMPLICIT_GC_AGGRESSIVE), allocDescription);128129result = allocate(envRealtime, allocDescription, allocType);130if (NULL != result) {131return result;132}133134return NULL;135}136137/**138* On a request for systemGC metronome will initiate a GC,139* but doesn't wait for it to complete.140*/141void142MM_MemorySubSpaceMetronome::systemGarbageCollect(MM_EnvironmentBase *env, U_32 gcCode) {143MM_EnvironmentRealtime *envRealtime = MM_EnvironmentRealtime::getEnvironment(env);144MM_Scheduler *sched = (MM_Scheduler *)envRealtime->getExtensions()->dispatcher;145146if (sched->isInitialized()) {147MM_GCExtensionsBase *ext = env->getExtensions();148ext->realtimeGC->setFixHeapForWalk(true);149sched->startGC(envRealtime);150sched->setGCCode(MM_GCCode(gcCode));151/* if we were triggered by rasdump, then the caller has already acquired exclusive VM access */152sched->continueGC(envRealtime, SYSTEM_GC_TRIGGER, 0, envRealtime->getOmrVMThread(), J9MMCONSTANT_EXPLICIT_GC_RASDUMP_COMPACT != gcCode);153/* TODO CRGTMP remove this call since continueGC blocks */154ext->realtimeGC->getRealtimeDelegate()->yieldWhenRequested(envRealtime);155}156}157158/**159* @todo Provide class documentation160* @ingroup GC_Metronome methodGroup161*/162void163MM_MemorySubSpaceMetronome::collect(MM_EnvironmentBase *env, MM_GCCode gcCode)164{165_collector->garbageCollect(env, this, NULL, gcCode.getCode(), NULL, NULL, NULL);166}167168/**169* Initialization.170* @todo Provide class documentation171*/172MM_MemorySubSpaceMetronome *173MM_MemorySubSpaceMetronome::newInstance(174MM_EnvironmentBase *env, MM_PhysicalSubArena *physicalSubArena, MM_MemoryPool *memoryPool,175bool usesGlobalCollector, UDATA minimumSize, UDATA initialSize, UDATA maximumSize)176{177MM_MemorySubSpaceMetronome *memorySubSpace;178179memorySubSpace = (MM_MemorySubSpaceMetronome *)env->getForge()->allocate(sizeof(MM_MemorySubSpaceMetronome), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());180if (NULL != memorySubSpace) {181new(memorySubSpace) MM_MemorySubSpaceMetronome(env, physicalSubArena, memoryPool, usesGlobalCollector, minimumSize, initialSize, maximumSize);182if (!memorySubSpace->initialize(env)) {183memorySubSpace->kill(env);184memorySubSpace = NULL;185}186}187return memorySubSpace;188}189190/**191* Initialization.192* @todo Provide class documentation193*/194bool195MM_MemorySubSpaceMetronome::initialize(MM_EnvironmentBase *env)196{197if(!MM_MemorySubSpaceSegregated::initialize(env)) {198return false;199}200201/* TODO: Not valid for multiple memory spaces */202MM_RealtimeGC *realtimeGC = (MM_RealtimeGC *)_collector;203realtimeGC->setMemoryPool(_memoryPoolSegregated);204realtimeGC->setMemorySubSpace(this);205206return true;207}208209210