Path: blob/master/runtime/gc_vlhgc/ConfigurationIncrementalGenerational.cpp
5986 views
1/*******************************************************************************2* Copyright (c) 1991, 2021 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/**24* @file25* @ingroup GC_Modron_Standard26*/2728#include "j9.h"29#include "j9cfg.h"3031#include "ConfigurationIncrementalGenerational.hpp"3233#include "ClassLoaderRememberedSet.hpp"34#include "CompressedCardTable.hpp"35#include "EnvironmentVLHGC.hpp"36#include "GCExtensions.hpp"37#include "GlobalAllocationManagerTarok.hpp"38#include "GlobalCollector.hpp"39#include "HeapRegionDescriptorVLHGC.hpp"40#include "HeapRegionManager.hpp"41#include "HeapRegionManagerVLHGC.hpp"42#if defined(OMR_GC_VLHGC_CONCURRENT_COPY_FORWARD)43#include "HeapRegionStateTable.hpp"44#endif /* defined(OMR_GC_VLHGC_CONCURRENT_COPY_FORWARD) */45#include "HeapVirtualMemory.hpp"46#include "MemorySpace.hpp"47#include "MemorySubSpaceTarok.hpp"48#include "IncrementalCardTable.hpp"49#include "IncrementalGenerationalGC.hpp"50#include "InterRegionRememberedSet.hpp"51#include "PhysicalArenaRegionBased.hpp"52#include "PhysicalSubArenaRegionBased.hpp"53#include "SweepPoolManagerAddressOrderedList.hpp"54#include "SweepPoolManagerVLHGC.hpp"5556#define TAROK_MINIMUM_REGION_SIZE_BYTES (512 * 1024)5758MM_Configuration *59MM_ConfigurationIncrementalGenerational::newInstance(MM_EnvironmentBase *env)60{61MM_ConfigurationIncrementalGenerational *configuration = (MM_ConfigurationIncrementalGenerational *) env->getForge()->allocate(sizeof(MM_ConfigurationIncrementalGenerational), MM_AllocationCategory::FIXED, J9_GET_CALLSITE());6263if(NULL != configuration) {64new(configuration) MM_ConfigurationIncrementalGenerational(env);65if(!configuration->initialize(env)) {66configuration->kill(env);67configuration = NULL;68}69}70return configuration;71}7273/**74* Create the global collector for a Tarok configuration75*/76MM_GlobalCollector *77MM_ConfigurationIncrementalGenerational::createGlobalCollector(MM_EnvironmentBase *envBase)78{79MM_GCExtensionsBase *extensions = envBase->getExtensions();80MM_EnvironmentVLHGC *env = MM_EnvironmentVLHGC::getEnvironment(envBase);81MM_HeapRegionManager *heapRegionManager = extensions->heapRegionManager;8283return MM_IncrementalGenerationalGC::newInstance(env, heapRegionManager);84}8586/**87* Create the heap for a region based configuration88*/89MM_Heap *90MM_ConfigurationIncrementalGenerational::createHeapWithManager(MM_EnvironmentBase *env, UDATA heapBytesRequested, MM_HeapRegionManager *regionManager)91{92MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);9394MM_Heap *heap = MM_HeapVirtualMemory::newInstance(env, extensions->heapAlignment, heapBytesRequested, regionManager);95if (NULL == heap) {96return NULL;97}9899#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)100/* Enable double mapping if glibc version 2.27 or newer is found. For double map to101* work we need a file descriptor, to get one we use shm_open(3) or memfd_create(2);102* shm_open(3) has 2 drawbacks: [I] shared memory is used; [II] does not support103* anonymous huge pages. [I] shared memory in Linux systems has a limit (half of104* physical memory). [II] if we create a file descriptor using shm_open(3) and then105* try to mmap with huge pages with the respective file descriptor the mmap call106* fails. It would only succeed if MAP_ANON flag was provided, but doing so ignores107* the file descriptor which is the opposite of what we want. In a newer glibc108* version (glibc 2.27 onwards) there’s a new function that does exactly what we109* want, and that's memfd_create(2); however that's only supported in glibc 2.27. We110* also need to check if region size is a bigger or equal to multiple of page size.111*112*/113if (extensions->isArrayletDoubleMapRequested && extensions->isArrayletDoubleMapAvailable) {114uintptr_t pagesize = heap->getPageSize();115if (!extensions->memoryManager->isLargePage(env, pagesize) || (pagesize <= extensions->getOmrVM()->_arrayletLeafSize)) {116extensions->indexableObjectModel.setEnableDoubleMapping(true);117}118}119#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */120121/* when we try to attach this heap to a region manager, we will need the card table since it needs to be NUMA-affinitized using the same logic as the heap so initialize it here */122extensions->cardTable = MM_IncrementalCardTable::newInstance(MM_EnvironmentVLHGC::getEnvironment(env), heap);123if (NULL == extensions->cardTable) {124heap->kill(env);125return NULL;126}127128if (extensions->tarokEnableCompressedCardTable) {129extensions->compressedCardTable = MM_CompressedCardTable::newInstance(MM_EnvironmentVLHGC::getEnvironment(env), heap);130if (NULL == extensions->compressedCardTable) {131extensions->cardTable->kill(env);132extensions->cardTable = NULL;133heap->kill(env);134return NULL;135}136}137138#if defined(OMR_GC_VLHGC_CONCURRENT_COPY_FORWARD)139if (extensions->isConcurrentCopyForwardEnabled()) {140uintptr_t heapBase = (uintptr_t) heap->getHeapBase();141uintptr_t regionShift = regionManager->getRegionShift();142uintptr_t regionCount = heap->getMaximumPhysicalRange() >> regionShift;143144extensions->heapRegionStateTable = OMR::GC::HeapRegionStateTable::newInstance(env->getForge(), heapBase, regionShift, regionCount);145if (NULL == extensions->heapRegionStateTable) {146extensions->compressedCardTable->kill(env);147extensions->compressedCardTable = NULL;148extensions->cardTable->kill(env);149extensions->cardTable = NULL;150heap->kill(env);151return NULL;152}153}154#endif /* defined(OMR_GC_VLHGC_CONCURRENT_COPY_FORWARD) */155156return heap;157}158159MM_EnvironmentBase *160MM_ConfigurationIncrementalGenerational::allocateNewEnvironment(MM_GCExtensionsBase *extensions, OMR_VMThread *omrVMThread)161{162return MM_EnvironmentVLHGC::newInstance(extensions, omrVMThread);163}164165J9Pool *166MM_ConfigurationIncrementalGenerational::createEnvironmentPool(MM_EnvironmentBase *env)167{168PORT_ACCESS_FROM_ENVIRONMENT(env);169170uintptr_t numberOfElements = getConfigurationDelegate()->getInitialNumberOfPooledEnvironments(env);171/* number of elements, pool flags = 0, 0 selects default pool configuration (at least 1 element, puddle size rounded to OS page size) */172return pool_new(sizeof(MM_EnvironmentVLHGC), numberOfElements, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_MM, POOL_FOR_PORT(PORTLIB));173}174175bool176MM_ConfigurationIncrementalGenerational::initializeEnvironment(MM_EnvironmentBase *env)177{178MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);179J9VMThread *vmThread = (J9VMThread *)env->getLanguageVMThread();180OMR_VM *omrVM = env->getOmrVM();181182if (!MM_Configuration::initializeEnvironment(env)) {183return false;184}185186/* acquire an ACT for this env */187if (!extensions->globalAllocationManager->acquireAllocationContext(env)) {188return false;189}190191vmThread->cardTableVirtualStart = (U_8 *)j9gc_incrementalUpdate_getCardTableVirtualStart(omrVM);192vmThread->cardTableShiftSize = j9gc_incrementalUpdate_getCardTableShiftValue(omrVM);193194return true;195}196197MM_MemorySpace *198MM_ConfigurationIncrementalGenerational::createDefaultMemorySpace(MM_EnvironmentBase *env, MM_Heap *heap, MM_InitializationParameters *parameters)199{200MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);201202MM_HeapRegionManager *regionManager = extensions->heapRegionManager;203Assert_MM_true(NULL != regionManager);204205/* Create Sweep Pool Manager for VLHGC */206extensions->sweepPoolManagerAddressOrderedList = (MM_SweepPoolManagerAddressOrderedList *) MM_SweepPoolManagerVLHGC::newInstance(env);207if (NULL == extensions->sweepPoolManagerAddressOrderedList) {208return NULL;209}210211/* allocate size: (region count) X (max GC thread count) X (size of Bucket) */212UDATA allocateSize = sizeof(MM_RememberedSetCardBucket);213allocateSize *= extensions->getHeap()->getHeapRegionManager()->getTableRegionCount();214allocateSize *= extensions->gcThreadCount;215216extensions->rememberedSetCardBucketPool = (MM_RememberedSetCardBucket *)extensions->getForge()->allocate(allocateSize, MM_AllocationCategory::REMEMBERED_SET, J9_GET_CALLSITE());217if (NULL == extensions->rememberedSetCardBucketPool) {218return NULL;219}220221/* this is as good a place as any to create the global allocation manager */222MM_GlobalAllocationManagerTarok *gamt = MM_GlobalAllocationManagerTarok::newInstance(env);223if (NULL == gamt) {224return NULL;225}226extensions->globalAllocationManager = gamt;227228MM_PhysicalSubArenaRegionBased *physicalSubArena = MM_PhysicalSubArenaRegionBased::newInstance(env, heap);229if(NULL == physicalSubArena) {230return NULL;231}232233bool usesGlobalCollector = true;234MM_MemorySubSpaceTarok *memorySubspaceTarok = MM_MemorySubSpaceTarok::newInstance(env, physicalSubArena, gamt, usesGlobalCollector, parameters->_minimumSpaceSize, parameters->_initialOldSpaceSize, parameters->_maximumSpaceSize, MEMORY_TYPE_OLD, 0);235if(NULL == memorySubspaceTarok) {236return NULL;237}238/* the subspace exists so now we can request that the allocation contexts are created (since they require the subspace) */239if (!gamt->initializeAllocationContexts(env, memorySubspaceTarok)) {240memorySubspaceTarok->kill(env);241return NULL;242}243/* now, configure the collector with this subspace */244((MM_IncrementalGenerationalGC *)extensions->getGlobalCollector())->setConfiguredSubspace(env, memorySubspaceTarok);245246247MM_PhysicalArenaRegionBased *physicalArena = MM_PhysicalArenaRegionBased::newInstance(env, heap);248if(NULL == physicalArena) {249memorySubspaceTarok->kill(env);250return NULL;251}252253return MM_MemorySpace::newInstance(env, heap, physicalArena, memorySubspaceTarok, parameters, MEMORY_SPACE_NAME_FLAT, MEMORY_SPACE_DESCRIPTION_FLAT);254}255256257void258MM_ConfigurationIncrementalGenerational::defaultMemorySpaceAllocated(MM_GCExtensionsBase *extensions, void* defaultMemorySpace)259{260MM_EnvironmentVLHGC env((J9JavaVM *)extensions->getOmrVM()->_language_vm);261MM_Configuration::defaultMemorySpaceAllocated(extensions, defaultMemorySpace);262/* initialize TaxationThreshold and RememberedSetCardBucketPool before first gc occurs and all of dependance has been set. */263((MM_IncrementalGenerationalGC *)extensions->getGlobalCollector())->initializeTaxationThreshold(&env);264extensions->interRegionRememberedSet->initializeRememberedSetCardBucketPool(&env);265}266267bool268MM_ConfigurationIncrementalGenerational::initialize(MM_EnvironmentBase *env)269{270MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);271272bool result = MM_Configuration::initialize(env);273274/* By default disable hot field depth copying */275env->disableHotFieldDepthCopy();276277if (result) {278if (MM_GCExtensions::OMR_GC_SCAVENGER_SCANORDERING_NONE == extensions->scavengerScanOrdering) {279extensions->scavengerScanOrdering = MM_GCExtensions::OMR_GC_SCAVENGER_SCANORDERING_DYNAMIC_BREADTH_FIRST;280}281extensions->setVLHGC(true);282}283284#define DEFAULT_MAX_AGE_FOR_PGC_COUNT_BASED 24285#define DEFAULT_MAX_NURSERY_AGE 1286#define DEFAULT_MAX_AGE_FOR_ALLOCATION_BASED 5287288/* set default region maximum age if it is not specified yet */289if (0 == extensions->tarokRegionMaxAge) {290if (extensions->tarokAllocationAgeEnabled) {291extensions->tarokRegionMaxAge = DEFAULT_MAX_AGE_FOR_ALLOCATION_BASED;292} else {293extensions->tarokRegionMaxAge = DEFAULT_MAX_AGE_FOR_PGC_COUNT_BASED;294}295}296297if (!extensions->tarokNurseryMaxAge._wasSpecified) {298/* set default nursery age */299extensions->tarokNurseryMaxAge._valueSpecified = DEFAULT_MAX_NURSERY_AGE;300} else {301/* specified nursery age is out of range - correct it to default */302if (extensions->tarokNurseryMaxAge._valueSpecified >= extensions->tarokRegionMaxAge) {303extensions->tarokNurseryMaxAge._valueSpecified = DEFAULT_MAX_NURSERY_AGE;304}305}306307if (!extensions->tarokMinimumGMPWorkTargetBytes._wasSpecified) {308/* default to a region size. No real reason for choosing this number other than that it is sized relative to the heap */309extensions->tarokMinimumGMPWorkTargetBytes._valueSpecified = extensions->regionSize;310}311312if (!extensions->dnssExpectedRatioMaximum._wasSpecified) {313extensions->dnssExpectedRatioMaximum._valueSpecified = 0.05;314}315316if (!extensions->dnssExpectedRatioMinimum._wasSpecified) {317extensions->dnssExpectedRatioMinimum._valueSpecified = 0.02;318}319320if (!extensions->heapExpansionGCRatioThreshold._wasSpecified) {321extensions->heapExpansionGCRatioThreshold._valueSpecified = 5;322}323324if (!extensions->heapContractionGCRatioThreshold._wasSpecified) {325extensions->heapContractionGCRatioThreshold._valueSpecified = 2;326}327328return result;329}330331void332MM_ConfigurationIncrementalGenerational::tearDown(MM_EnvironmentBase *env)333{334MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);335336if (NULL != extensions->sweepPoolManagerAddressOrderedList) {337extensions->sweepPoolManagerAddressOrderedList->kill(env);338extensions->sweepPoolManagerAddressOrderedList = NULL;339}340341if (NULL != extensions->cardTable) {342extensions->cardTable->kill(MM_EnvironmentVLHGC::getEnvironment(env));343extensions->cardTable = NULL;344}345346if (NULL != extensions->compressedCardTable) {347extensions->compressedCardTable->kill(env);348extensions->compressedCardTable = NULL;349}350351#if defined(OMR_GC_VLHGC_CONCURRENT_COPY_FORWARD)352if (NULL != extensions->heapRegionStateTable) {353extensions->heapRegionStateTable->kill(env->getForge());354extensions->heapRegionStateTable = NULL;355}356#endif /* defined(OMR_GC_VLHGC_CONCURRENT_COPY_FORWARD) */357358MM_Configuration::tearDown(env);359360// cleanup after extensions->heapRegionManager361if (NULL != extensions->rememberedSetCardBucketPool) {362extensions->getForge()->free(extensions->rememberedSetCardBucketPool);363extensions->rememberedSetCardBucketPool = NULL;364}365}366367MM_HeapRegionManager *368MM_ConfigurationIncrementalGenerational::createHeapRegionManager(MM_EnvironmentBase *env)369{370MM_GCExtensionsBase *extensions = env->getExtensions();371return MM_HeapRegionManagerVLHGC::newInstance(env, extensions->regionSize, sizeof(MM_HeapRegionDescriptorVLHGC), MM_HeapRegionDescriptorVLHGC::initializer, MM_HeapRegionDescriptorVLHGC::destructor);372}373374void375MM_ConfigurationIncrementalGenerational::cleanUpClassLoader(MM_EnvironmentBase *env, J9ClassLoader* classLoader)376{377MM_GCExtensionsBase *extensions = env->getExtensions();378MM_ClassLoaderRememberedSet *classLoaderRememberedSet = extensions->classLoaderRememberedSet;379if (MM_CycleState::CT_PARTIAL_GARBAGE_COLLECTION == env->_cycleState->_collectionType) {380/* during PGCs we should never unload a class loader which is remembered because it could have instances */381Assert_MM_false(classLoaderRememberedSet->isRemembered(env, classLoader));382}383classLoaderRememberedSet->killRememberedSet(env, classLoader);384}385386387void388MM_ConfigurationIncrementalGenerational::prepareParameters(OMR_VM *omrVM, UDATA minimumSpaceSize, UDATA minimumNewSpaceSize,389UDATA initialNewSpaceSize, UDATA maximumNewSpaceSize, UDATA minimumTenureSpaceSize, UDATA initialTenureSpaceSize,390UDATA maximumTenureSpaceSize, UDATA memoryMax, UDATA tenureFlags, MM_InitializationParameters *parameters)391{392MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVM);393UDATA contextCount = MM_GlobalAllocationManagerTarok::calculateIdealManagedContextCount(extensions);394395/* Each AC needs a region, so we adjust the calculated values as per generic formulas.396* Alternatively, we could leave min/initial size as is, but make early initialize fail (and thus fail to start VM),397* if specified sizes are lower than VLHGC specific values (regionSize*ACcount) */398minimumSpaceSize = OMR_MAX(minimumSpaceSize, extensions->regionSize * contextCount);399initialTenureSpaceSize = OMR_MAX(initialTenureSpaceSize, extensions->regionSize * contextCount);400401MM_Configuration::prepareParameters(omrVM, minimumSpaceSize, minimumNewSpaceSize, initialNewSpaceSize, maximumNewSpaceSize,402minimumTenureSpaceSize, initialTenureSpaceSize, maximumTenureSpaceSize,403memoryMax, tenureFlags, parameters);404}405406bool407MM_ConfigurationIncrementalGenerational::verifyRegionSize(MM_EnvironmentBase *env, UDATA regionSize)408{409return regionSize >= TAROK_MINIMUM_REGION_SIZE_BYTES;410}411412bool413MM_ConfigurationIncrementalGenerational::initializeNUMAManager(MM_EnvironmentBase *env)414{415MM_GCExtensionsBase *extensions = env->getExtensions();416bool disabledByForce = extensions->numaForced && !extensions->_numaManager.isPhysicalNUMAEnabled();417if (!disabledByForce) {418extensions->_numaManager.shouldEnablePhysicalNUMA(true);419}420bool result = MM_Configuration::initializeNUMAManager(env);421422if (result && !disabledByForce) {423/* shut off NUMA (even if enabled by force) if we are using too small a heap */424UDATA affinityLeaderCount = 0;425extensions->_numaManager.getAffinityLeaders(&affinityLeaderCount);426if ((1 + affinityLeaderCount) != MM_GlobalAllocationManagerTarok::calculateIdealManagedContextCount(extensions)) {427extensions->_numaManager.shouldEnablePhysicalNUMA(false);428result = extensions->_numaManager.recacheNUMASupport(static_cast<MM_EnvironmentBase *>(env));429/* startup can't fail if NUMAManager disabled */430Assert_MM_true(result);431}432}433434return result;435}436437438