Path: blob/master/runtime/gc_modron_startup/mminit.cpp
5986 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/**23* @file24* @ingroup GC_Modron_Startup25*/2627#if defined (J9VM_GC_VLHGC)28#include <math.h>29#endif /* J9VM_GC_VLHGC */30#include <string.h>3132#include "gcmspace.h"33#include "gcutils.h"34#include "j2sever.h"35#include "j9.h"36#include "j9cfg.h"37#include "j9comp.h"38#include "j9consts.h"39#include "j9modron.h"40#include "j9port.h"41#include "j9protos.h"42#include "jni.h"43#include "jvminit.h"44#include "mminit.h"45#include "mminitcore.h"46#include "mmparse.h"47#include "modronnls.h"48#include "omr.h"49#if defined(J9VM_GC_MODRON_TRACE) && !defined(J9VM_GC_REALTIME)50#include "Tgc.hpp"51#endif /* J9VM_GC_MODRON_TRACE && !defined(J9VM_GC_REALTIME) */5253#if defined (J9VM_GC_HEAP_CARD_TABLE)54#include "CardTable.hpp"55#endif /* defined (J9VM_GC_HEAP_CARD_TABLE) */56#include "CollectorLanguageInterfaceImpl.hpp"57#if defined(OMR_GC_MODRON_CONCURRENT_MARK)58#include "ConcurrentCardTable.hpp"59#include "ConcurrentGC.hpp"60#endif /* OMR_GC_MODRON_CONCURRENT_MARK */61#include "Configuration.hpp"62#if defined(J9VM_GC_MODRON_STANDARD)63#include "ConfigurationFlat.hpp"64#include "ConfigurationGenerational.hpp"65#endif /* J9VM_GC_MODRON_STANDARD */66#if defined(J9VM_GC_VLHGC)67#include "ConfigurationIncrementalGenerational.hpp"68#endif /* J9VM_GC_VLHGC */69#if defined(J9VM_GC_REALTIME)70#include "ConfigurationRealtime.hpp"71#endif /* J9VM_GC_REALTIME */72#include "ClassLoaderManager.hpp"73#include "Debug.hpp"74#include "EnvironmentBase.hpp"75#if defined(J9VM_GC_FINALIZATION)76#include "FinalizeListManager.hpp"77#endif /* J9VM_GC_FINALIZATION */78#include "GCExtensions.hpp"79#include "GlobalAllocationManager.hpp"80#include "GlobalCollector.hpp"81#include "HeapRegionDescriptor.hpp"82#include "HeapRegionManager.hpp"83#include "LargeObjectAllocateStats.hpp"84#include "Math.hpp"85#include "MemorySpace.hpp"86#include "MemorySubSpace.hpp"87#include "ModronAssertions.h"88#include "ObjectAccessBarrier.hpp"89#include "ObjectAllocationInterface.hpp"90#include "OMRVMInterface.hpp"91#include "OMRVMThreadInterface.hpp"92#include "ParallelDispatcher.hpp"93#if defined(J9VM_GC_VLHGC)94#include "RememberedSetCardList.hpp"95#endif /* J9VM_GC_VLHGC */96#if defined(J9VM_GC_SEGRGATED_HEAP)97#include "ObjectHeapIteratorSegregated.hpp"98#include "SizeClasses.hpp"99#endif /* J9VM_GC_SEGRGATED_HEAP */100#if defined(J9VM_GC_REALTIME)101#include "RememberedSetSATB.hpp"102#endif /* J9VM_GC_REALTIME */103#include "Scavenger.hpp"104#include "StringTable.hpp"105#include "Validator.hpp"106#if defined(OMR_GC_IDLE_HEAP_MANAGER)107#include "IdleGCManager.hpp"108#endif109110/**111* If we fail to allocate heap structures with the default Xmx value,112* we will try again with a smaller value. These parameters define113* the percentage by which to reduce the Xmx value.114*/115#define DEFAULT_XMX_REDUCTION_NUMERATOR 4116#define DEFAULT_XMX_REDUCTION_DENOMINATOR 5117118#define NONE ((UDATA) 0x0)119#define XMS ((UDATA) 0x1)120#define XMOS ((UDATA) 0x2)121#define XMNS ((UDATA) 0x4)122#define XMDX ((UDATA) 0x8)123124#define XMS_XMOS ((UDATA) XMS | XMOS)125#define XMOS_XMNS ((UDATA) XMOS | XMNS)126#define XMDX_XMS ((UDATA) XMDX | XMS)127128#define ROUND_TO(granularity, number) (((UDATA)(number) + (granularity) - 1) & ~((UDATA)(granularity) - 1))129130extern "C" {131extern J9MemoryManagerFunctions MemoryManagerFunctions;132extern void initializeVerboseFunctionTableWithDummies(J9MemoryManagerVerboseInterface *table);133134static void hookValidatorVMThreadCrash(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData);135static bool gcInitializeVMHooks(MM_GCExtensionsBase *extensions);136static void gcCleanupVMHooks(MM_GCExtensionsBase *extensions);137138static const char * displayXmxOrMaxRAMPercentage(IDATA* memoryParameters);139static const char * displayXmsOrInitialRAMPercentage(IDATA* memoryParameters);140141/**142* Initialize the threads mutator information (RS pointers, reference list pointers etc) for GC/MM purposes.143*144* @note vmThread MAY NOT be initialized completely from an execution model perspective.145* @return 0 if OK, or non 0 if error146*/147IDATA148initializeMutatorModelJava(J9VMThread* vmThread)149{150if (0 != initializeMutatorModel(vmThread->omrVMThread)) {151return -1;152}153154MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(vmThread);155vmThread->gcExtensions = vmThread->omrVMThread->_gcOmrVMThreadExtensions;156157if (extensions->isStandardGC()) {158if (extensions->isConcurrentScavengerEnabled()) {159/* Ensure that newly created threads invoke VM access using slow path, so that the associated hook is invoked.160* GC will register to the hook to enable local thread resources if a thread happens to be created in a middle of Concurrent Scavenge */161setEventFlag(vmThread, J9_PUBLIC_FLAGS_DISABLE_INLINE_VM_ACCESS);162}163164#if defined(J9VM_GC_GENERATIONAL)165vmThread->gcRememberedSet.fragmentCurrent = NULL;166vmThread->gcRememberedSet.fragmentTop = NULL;167vmThread->gcRememberedSet.fragmentSize = OMR_SCV_REMSET_FRAGMENT_SIZE;168#endif /* J9VM_GC_GENERATIONAL */169170void *lowAddress = extensions->heapBaseForBarrierRange0;171void *highAddress = (void *)((UDATA)extensions->heapBaseForBarrierRange0 + extensions->heapSizeForBarrierRange0);172173// todo: dagar lowTenureAddress, highTenureAddress, heapBaseForBarrierRange0, heapSizeForBarrierRange0 are duplicated174vmThread->lowTenureAddress = lowAddress;175vmThread->highTenureAddress = highAddress;176177/* replacement values for lowTenureAddress and highTenureAddress */178// todo: dagar remove duplicate fields179vmThread->heapBaseForBarrierRange0 = extensions->heapBaseForBarrierRange0;180vmThread->heapSizeForBarrierRange0 = extensions->heapSizeForBarrierRange0;181#if defined (J9VM_GC_HEAP_CARD_TABLE)182if (NULL != extensions->cardTable) {183vmThread->activeCardTableBase = extensions->cardTable->getCardTableStart();184}185#endif /* J9VM_GC_HEAP_CARD_TABLE */186} else if(extensions->isVLHGC()) {187MM_Heap *heap = extensions->getHeap();188void *heapBase = heap->getHeapBase();189void *heapTop = heap->getHeapTop();190191/* replacement values for lowTenureAddress and highTenureAddress */192vmThread->heapBaseForBarrierRange0 = heapBase;193vmThread->heapSizeForBarrierRange0 = (UDATA)heapTop - (UDATA)heapBase;194195/* lowTenureAddress and highTenureAddress are actually supposed to be the low and high addresses of the heap for which card196* dirtying is required (the JIT uses this as a range check to determine if it needs to dirty a card when writing into an197* object). Setting these for Tarok is just a work-around until a more generic solution is implemented198*/199vmThread->lowTenureAddress = heapBase;200vmThread->highTenureAddress = heapTop;201#if defined (J9VM_GC_HEAP_CARD_TABLE)202vmThread->activeCardTableBase = extensions->cardTable->getCardTableStart();203#endif /* J9VM_GC_HEAP_CARD_TABLE */204}205return 0;206}207208/**209* Cleanup Mutator specific resources (TLH, thread extension, etc) on shutdown.210*/211void212cleanupMutatorModelJava(J9VMThread* vmThread)213{214MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);215216if (NULL != env) {217J9JavaVM *vm = vmThread->javaVM;218J9VMDllLoadInfo *loadInfo = getGCDllLoadInfo(vm);219220/* cleanupMutatorModelJava is called as part of the main vmThread shutdown, which happens after221* gcCleanupHeapStructures has been called. We should therefore only flush allocation caches222* if there is still a heap.223*/224if (!IS_STAGE_COMPLETED(loadInfo->completedBits, HEAP_STRUCTURES_FREED)) {225/* this can only be called if the heap still exists since it will ask the TLH chunk to be abandoned with crashes if the heap is deallocated */226GC_OMRVMThreadInterface::flushCachesForGC(env);227}228}229230cleanupMutatorModel(vmThread->omrVMThread, 0);231232vmThread->gcExtensions = NULL;233}234235/**236* Triggers hook for deleting private heap.237* @param memorySpace pointer to the list (pool) of memory spaces238*/239static void240reportPrivateHeapDelete(J9JavaVM * javaVM, void * memorySpace)241{242MM_EnvironmentBase env(javaVM->omrVM);243244MM_MemorySpace *modronMemorySpace = (MM_MemorySpace *)memorySpace;245if (modronMemorySpace) {246if (!(javaVM->runtimeFlags & J9_RUNTIME_SHUTDOWN)) {247TRIGGER_J9HOOK_MM_PRIVATE_HEAP_DELETE(248MM_GCExtensions::getExtensions(javaVM)->privateHookInterface,249env.getOmrVMThread(),250modronMemorySpace);251}252}253}254255/**256* Cleanup passive heap structures257*/258void259gcCleanupHeapStructures(J9JavaVM * vm)260{261/* If shutdown occurs early (due to command line parsing errors, for example) there may not be262* a J9VMThread, so allocate a fake environment.263*/264MM_EnvironmentBase env(vm->omrVM);265MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);266267/* remove hooks installed by Validator */268gcCleanupVMHooks(extensions);269270/* Flush any allocation contexts so that their memory is returned to the memory spaces before we tear down the memory spaces */271MM_GlobalAllocationManager *gam = extensions->globalAllocationManager;272if (NULL != gam) {273gam->flushAllocationContextsForShutdown(&env);274}275276if (vm->memorySegments) {277vm->internalVMFunctions->freeMemorySegmentList(vm, vm->memorySegments);278}279if (vm->classMemorySegments) {280vm->internalVMFunctions->freeMemorySegmentList(vm, vm->classMemorySegments);281}282283#if defined(J9VM_GC_FINALIZATION)284if (extensions->finalizeListManager) {285extensions->finalizeListManager->kill(&env);286extensions->finalizeListManager = NULL;287}288#endif /* J9VM_GC_FINALIZATION */289290if (vm->mainThread && vm->mainThread->threadObject) {291/* main thread has not been deallocated yet, but heap has gone */292vm->mainThread->threadObject = NULL;293}294return;295}296297/**298* Initialized passive and active heap components299*/300IDATA301j9gc_initialize_heap(J9JavaVM *vm, IDATA *memoryParameterTable, UDATA heapBytesRequested)302{303MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);304MM_EnvironmentBase env(vm->omrVM);305MM_GlobalCollector *globalCollector;306PORT_ACCESS_FROM_JAVAVM(vm);307J9VMDllLoadInfo *loadInfo = getGCDllLoadInfo(vm);308309if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_PORTABLE_SHARED_CACHE)) {310extensions->shouldForceLowMemoryHeapCeilingShiftIfPossible = true;311}312313#if defined(J9VM_GC_BATCH_CLEAR_TLH)314/* Record batch clear state in VM so inline allocates can decide correct initialization procedure */315vm->initializeSlotsOnTLHAllocate = (extensions->batchClearTLH == 0) ? 1 : 0;316#endif /* J9VM_GC_BATCH_CLEAR_TLH */317318extensions->heap = extensions->configuration->createHeap(&env, heapBytesRequested);319320if (NULL == extensions->heap) {321const char *splitFailure = NULL;322323/* If error reason was not explicitly set use general error message */324if(MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_NO_ERROR == extensions->heapInitializationFailureReason) {325extensions->heapInitializationFailureReason = MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_HEAP;326}327328switch(extensions->heapInitializationFailureReason) {329330/* see if we set the split-heap specific error since we want to be more verbose in that case */331case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_SPLIT_HEAP_OLD_SPACE:332splitFailure = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_ALLOCATE_OLD_SPACE, "Failed to allocate old space");333break;334case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_SPLIT_HEAP_NEW_SPACE:335splitFailure = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_ALLOCATE_NEW_SPACE, "Failed to allocate new space");336break;337case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_SPLIT_HEAP_GEOMETRY:338splitFailure = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_SPLIT_HEAP_ENTEXTS_WRONG_ORDER, "Required split heap memory geometry could not be allocated");339break;340341/* failed an attempt to allocate low memory reserve */342case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_ALLOCATE_LOW_MEMORY_RESERVE:343{344/* Obtain the qualified size (e.g. 2k) */345UDATA size = extensions->suballocatorInitialSize;346const char* qualifier = NULL;347qualifiedSize(&size, &qualifier);348349char *format = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INSTANTIATE_LOW_MEMORY_RESERVE_SIZE_REQUESTED, "Failed to instantiate compressed references metadata. %zu%s requested");350UDATA formatLength = strlen(format) + 32; /* 2^64 is 20 digits, so have a few extra */351352loadInfo->fatalErrorStr = (char *)j9mem_allocate_memory(formatLength, OMRMEM_CATEGORY_MM);353if (loadInfo->fatalErrorStr) {354j9str_printf(PORTLIB, loadInfo->fatalErrorStr, formatLength, format, size, qualifier);355loadInfo->loadFlags |= FREE_ERROR_STRING; /* indicates that buffer should be freed later */356}357break;358}359360/* general error message - can not instantiate heap */361case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_HEAP:362{363/* Obtain the qualified size (e.g. 2k) */364UDATA size = heapBytesRequested;365const char* qualifier = NULL;366qualifiedSize(&size, &qualifier);367368char *format = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INSTANTIATE_HEAP_SIZE_REQUESTED, "Failed to instantiate heap. %zu%s requested");369UDATA formatLength = strlen(format) + 32; /* 2^64 is 20 digits, so have a few extra */370371loadInfo->fatalErrorStr = (char *)j9mem_allocate_memory(formatLength, OMRMEM_CATEGORY_MM);372if (loadInfo->fatalErrorStr) {373j9str_printf(PORTLIB, loadInfo->fatalErrorStr, formatLength, format, size, qualifier);374loadInfo->loadFlags |= FREE_ERROR_STRING; /* indicates that buffer should be freed later */375}376break;377}378379/* general error message - can not instantiate heap */380case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_SATISFY_REQUESTED_PAGE_SIZE:381{382/* Obtain the qualified size (e.g. 2k) */383UDATA heapSize = extensions->memoryMax;384const char* heapSizeQualifier = NULL;385qualifiedSize(&heapSize, &heapSizeQualifier);386387UDATA pageSize = extensions->requestedPageSize;388const char* pageSizeQualifier = NULL;389qualifiedSize(&pageSize, &pageSizeQualifier);390391char *format = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_OPTIONS_XLP_PAGE_NOT_AVAILABLE_STRICT, "Unable to satisfy heap size %zu%s with page size %zu%s. Heap size can be specified with -Xmx");392UDATA formatLength = strlen(format) + 32; /* 2^64 is 20 digits, so have a few extra */393394loadInfo->fatalErrorStr = (char *)j9mem_allocate_memory(formatLength, OMRMEM_CATEGORY_MM);395if (loadInfo->fatalErrorStr) {396j9str_printf(PORTLIB, loadInfo->fatalErrorStr, formatLength, format, heapSize, heapSizeQualifier, pageSize, pageSizeQualifier);397loadInfo->loadFlags |= FREE_ERROR_STRING; /* indicates that buffer should be freed later */398}399extensions->largePageFailedToSatisfy = true;400break;401}402403case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_NO_ERROR:404case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_METRONOME_DOES_NOT_SUPPORT_4BIT_SHIFT:405default:406Assert_MM_unreachable();407break;408}409410/* Handle split heap failures cases */411if (NULL != splitFailure) {412const char *format = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INSTANTIATE_SPLIT_HEAP, "Failed to instantiate split heap: %s (new size %zu%s, old size %zu%s)");413UDATA oldSpaceSize = extensions->oldSpaceSize;414const char* oldQualifier = NULL;415qualifiedSize(&oldSpaceSize, &oldQualifier);416UDATA newSpaceSize = extensions->newSpaceSize;417const char* newQualifier = NULL;418qualifiedSize(&newSpaceSize, &newQualifier);419UDATA formatLength = j9str_printf(PORTLIB, NULL, 0, format, splitFailure, newSpaceSize, newQualifier, oldSpaceSize, oldQualifier);420421loadInfo->fatalErrorStr = (char *)j9mem_allocate_memory(formatLength, OMRMEM_CATEGORY_MM);422if (loadInfo->fatalErrorStr) {423j9str_printf(PORTLIB, loadInfo->fatalErrorStr, formatLength, format, splitFailure, newSpaceSize, newQualifier, oldSpaceSize, oldQualifier);424loadInfo->loadFlags |= FREE_ERROR_STRING; /* indicates that buffer should be freed later */425}426}427428/* failed to generate error string - use default */429if(NULL == loadInfo->fatalErrorStr) {430loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INSTANTIATE_HEAP, "Failed to instantiate heap.");431}432433goto error_no_memory;434}435436extensions->dispatcher = extensions->configuration->createParallelDispatcher(&env, (omrsig_handler_fn)vm->internalVMFunctions->structuredSignalHandlerVM, vm, vm->defaultOSStackSize);437if (NULL == extensions->dispatcher) {438loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INSTANTIATE_TASK_DISPATCHER, "Failed to instantiate task dispatcher.");439goto error_no_memory;440}441442/* Initialize VM interface extensions */443GC_OMRVMInterface::initializeExtensions(extensions);444445/* Initialize the global collector */446globalCollector = extensions->configuration->createGlobalCollector(&env);447if (NULL == globalCollector) {448if(MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_METRONOME_DOES_NOT_SUPPORT_4BIT_SHIFT == extensions->heapInitializationFailureReason) {449j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTION_OVERFLOW, displayXmxOrMaxRAMPercentage(memoryParameterTable));450}451loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INSTANTIATE_GLOBAL_GARBAGE_COLLECTOR, "Failed to instantiate global garbage collector.");452goto error_no_memory;453}454/* Mark this collector as a global collector so that we will check for excessive gc after it collects */455globalCollector->setGlobalCollector(true);456extensions->setGlobalCollector(globalCollector);457458/* Create the environments pool */459extensions->environments = extensions->configuration->createEnvironmentPool(&env);460if (NULL == extensions->environments) {461goto error_no_memory;462}463464extensions->classLoaderManager = MM_ClassLoaderManager::newInstance(&env, globalCollector);465if (NULL == extensions->classLoaderManager) {466goto error_no_memory;467}468469extensions->stringTable = MM_StringTable::newInstance(&env, extensions->dispatcher->threadCountMaximum());470if (NULL == extensions->stringTable) {471goto error_no_memory;472}473474/* Initialize statistic locks */475if (omrthread_monitor_init_with_name(&extensions->gcStatsMutex, 0, "MM_GCExtensions::gcStats")) {476loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE_MUTEX, "Failed to initialize mutex for GC statistics.");477goto error_no_memory;478}479480#if defined(OMR_GC_IDLE_HEAP_MANAGER)481if (extensions->gcOnIdle) {482/* Enable idle tuning only for gencon policy */483if (gc_policy_gencon == extensions->configurationOptions._gcPolicy) {484extensions->idleGCManager = MM_IdleGCManager::newInstance(&env);485if (NULL == extensions->idleGCManager) {486goto error_no_memory;487}488}489}490#endif491492return JNI_OK;493494error_no_memory:495return JNI_ENOMEM;496}497498/**499* Creates and initialized VM owned structures related to the heap500* Calls low level heap initialization function501* @return J9VMDLLMAIN_OK or J9VMDLLMAIN_FAILED502*/503jint504gcInitializeHeapStructures(J9JavaVM *vm)505{506PORT_ACCESS_FROM_JAVAVM(vm);507MM_EnvironmentBase env(vm->omrVM);508509MM_MemorySpace *defaultMemorySpace;510MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);511J9VMDllLoadInfo *loadInfo = getGCDllLoadInfo(vm);512513/* For now, number of segments to default in pool */514if ((vm->memorySegments = vm->internalVMFunctions->allocateMemorySegmentList(vm, 10, OMRMEM_CATEGORY_VM)) == NULL) {515loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_ALLOCATE_VM_MEMORY_SEGMENTS, "Failed to allocate VM memory segments.");516goto error;517}518519/* For now, number of segments to default in pool */520if ((vm->classMemorySegments = vm->internalVMFunctions->allocateMemorySegmentListWithFlags(vm, 10, MEMORY_SEGMENT_LIST_FLAG_SORT, J9MEM_CATEGORY_CLASSES)) == NULL) {521loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_ALLOCATE_VM_CLASS_MEMORY_SEGMENTS, "Failed to allocate VM class memory segments.");522goto error;523}524525/* j9gc_initialize_heap is now called from gcInitializeDefaults */526527/* Create and initialize the default memory space */528defaultMemorySpace = internalAllocateMemorySpaceWithMaximum(vm, extensions->initialMemorySize, extensions->minNewSpaceSize, extensions->newSpaceSize, extensions->maxNewSpaceSize, extensions->minOldSpaceSize, extensions->oldSpaceSize, extensions->maxOldSpaceSize, extensions->maxSizeDefaultMemorySpace, 0, MEMORY_TYPE_DISCARDABLE);529if (defaultMemorySpace == NULL) {530loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_ALLOCATE_DEFAULT_MEMORY_SPACE, "Failed to allocate default memory space.");531goto error;532}533534extensions->configuration->defaultMemorySpaceAllocated(extensions, defaultMemorySpace);535536#if defined(J9VM_GC_FINALIZATION)537if(!(extensions->finalizeListManager = GC_FinalizeListManager::newInstance(&env))) {538loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE_FINALIZER_MANAGEMENT, "Failed to initialize finalizer management.");539goto error;540}541#endif /* J9VM_GC_FINALIZATION */542543/* install hooks for the Validator */544if (!gcInitializeVMHooks(extensions)) {545goto error;546}547548vm->defaultMemorySpace = defaultMemorySpace;549550return J9VMDLLMAIN_OK;551552error:553return J9VMDLLMAIN_FAILED;554}555556/**557* Starts the Finalizer and the Heap management components558* @return 0 if OK, non zero if error559*/560int561gcStartupHeapManagement(J9JavaVM *javaVM)562{563MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);564int result = 0;565566#if defined(J9VM_GC_FINALIZATION)567#if JAVA_SPEC_VERSION >= 18568if (J9_ARE_ANY_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_DISABLE_FINALIZATION)) {569/* Finalization is disabled */570} else571#endif /* JAVA_SPEC_VERSION >= 18 */572{573result = j9gc_finalizer_startup(javaVM);574if (JNI_OK != result) {575PORT_ACCESS_FROM_JAVAVM(javaVM);576j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_FAILED_TO_INITIALIZE_FINALIZE_SUPPORT);577return result;578}579}580#endif /* J9VM_GC_FINALIZATION */581582/* Kickoff secondary initialization for the global collector */583if (!extensions->getGlobalCollector()->collectorStartup(extensions)) {584result = JNI_ENOMEM;585}586587if (!extensions->dispatcher->startUpThreads()) {588extensions->dispatcher->shutDownThreads();589result = JNI_ENOMEM;590}591592if (JNI_OK != result) {593PORT_ACCESS_FROM_JAVAVM(javaVM);594extensions->getGlobalCollector()->collectorShutdown(extensions);595j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_FAILED_TO_STARTUP_GARBAGE_COLLECTOR);596return result;597}598599return result;600}601602void j9gc_jvmPhaseChange(J9VMThread *currentThread, UDATA phase)603{604J9JavaVM *vm = currentThread->javaVM;605MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);606MM_EnvironmentBase env(currentThread->omrVMThread);607if (J9VM_PHASE_NOT_STARTUP == phase) {608609if ((NULL != vm->sharedClassConfig) && extensions->useGCStartupHints) {610if (extensions->isStandardGC()) {611/* read old values from SC */612uintptr_t hintDefaultOld = 0;613uintptr_t hintTenureOld = 0;614vm->sharedClassConfig->findGCHints(currentThread, &hintDefaultOld, &hintTenureOld);615/* Nothing to do if read fails, we'll just assume the old values are 0 */616617/* Get the current heap size values.618* Default/Tenure MemorySubSpace is of type Generic (which is MemoryPool owner, while the parents are of type Flat/SemiSpace).619* For SemiSpace the latter (parent) ones are what we want to deal with (expand), since it's what includes both Allocate And Survivor children.620* For Flat it would probably make no difference if we used parent or child, but let's be consistent and use parent, too.621*/622MM_MemorySubSpace *defaultMemorySubSpace = extensions->heap->getDefaultMemorySpace()->getDefaultMemorySubSpace()->getParent();623MM_MemorySubSpace *tenureMemorySubspace = extensions->heap->getDefaultMemorySpace()->getTenureMemorySubSpace()->getParent();624625uintptr_t hintDefault = defaultMemorySubSpace->getActiveMemorySize();626uintptr_t hintTenure = 0;627628/* Standard GCs always have Default MSS (which is equal to Tenure for flat heap configuration).629* So the simplest is always fetch Default, regardless if's generational haep configuration or not.630* We fetch Tenure only if only not equal to Default (which implies it's generational) */631if (defaultMemorySubSpace != tenureMemorySubspace) {632hintTenure = tenureMemorySubspace->getActiveMemorySize();633}634635/* Gradually learn, by averaging new values with old values - it may take a few restarts before hint converge to stable values */636hintDefault = (uintptr_t)MM_Math::weightedAverage((float)hintDefaultOld, (float)hintDefault, (1.0f - extensions->heapSizeStartupHintWeightNewValue));637hintTenure = (uintptr_t)MM_Math::weightedAverage((float)hintTenureOld, (float)hintTenure, (1.0f - extensions->heapSizeStartupHintWeightNewValue));638639vm->sharedClassConfig->storeGCHints(currentThread, hintDefault, hintTenure, true);640/* Nothing to do if store fails, storeGCHints already issues a trace point */641}642}643}644}645646647void648gcExpandHeapOnStartup(J9JavaVM *javaVM)649{650J9SharedClassConfig *sharedClassConfig = javaVM->sharedClassConfig;651MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);652J9VMThread *currentThread = javaVM->internalVMFunctions->currentVMThread(javaVM);653MM_EnvironmentBase env(currentThread->omrVMThread);654655if ((NULL != sharedClassConfig) && extensions->useGCStartupHints) {656if (extensions->isStandardGC()) {657uintptr_t hintDefault = 0;658uintptr_t hintTenure = 0;659660if (0 == sharedClassConfig->findGCHints(currentThread, &hintDefault, &hintTenure)) {661662/* Default/Tenure MemorySubSpace is of type Generic (which is MemoryPool owner, while the parents are of type Flat/SemiSpace).663* For SemiSpace the latter (parent) ones are what we want to deal with (expand), since it's what includes both Allocate And Survivor children.664* For Flat it would probably make no difference if we used parent or child, but let's be consistent and use parent, too.665*/666MM_MemorySubSpace *defaultMemorySubSpace = extensions->heap->getDefaultMemorySpace()->getDefaultMemorySubSpace()->getParent();667MM_MemorySubSpace *tenureMemorySubspace = extensions->heap->getDefaultMemorySpace()->getTenureMemorySubSpace()->getParent();668669670/* Standard GCs always have Default MSS (which is equal to Tenure for flat heap configuration).671* So the simplest is always deal with Default, regardless if's generational heap configuration or not.672* We deal with Tenure only if only not equal to Default (which implies it's generational)673* We are a bit conservative and aim for slightly lower values that historically recorded by hints.674*/675uintptr_t hintDefaultAdjusted = (uintptr_t)(hintDefault * extensions->heapSizeStartupHintConservativeFactor);676uintptr_t defaultCurrent = defaultMemorySubSpace->getActiveMemorySize();677678if (hintDefaultAdjusted > defaultCurrent) {679extensions->heap->getResizeStats()->setLastExpandReason(HINT_PREVIOUS_RUNS);680defaultMemorySubSpace->expand(&env, hintDefaultAdjusted - defaultCurrent);681}682683if (defaultMemorySubSpace != tenureMemorySubspace) {684uintptr_t hintTenureAdjusted = (uintptr_t)(hintTenure * extensions->heapSizeStartupHintConservativeFactor);685uintptr_t tenureCurrent = tenureMemorySubspace->getActiveMemorySize();686687if (hintTenureAdjusted > tenureCurrent) {688extensions->heap->getResizeStats()->setLastExpandReason(HINT_PREVIOUS_RUNS);689tenureMemorySubspace->expand(&env, hintTenureAdjusted - tenureCurrent);690}691}692693}694/* Nothing to do if findGCHints failed. It already issues a trace point - no need to duplicate it here */695}696/* todo: Balanced GC */697}698}699700701/**702* Cleanup Finalizer and Heap components703*/704void705gcShutdownHeapManagement(J9JavaVM *javaVM)706{707MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);708MM_Collector *globalCollector = extensions->getGlobalCollector();709710#if defined(J9VM_GC_FINALIZATION)711/* wait for finalizer shutdown */712j9gc_finalizer_shutdown(javaVM);713#endif /* J9VM_GC_FINALIZATION */714715/* Kickoff shutdown of global collector */716if (NULL != globalCollector) {717globalCollector->collectorShutdown(extensions);718}719720if (extensions->dispatcher) {721extensions->dispatcher->shutDownThreads();722}723}724725/**726* Free any resources allocated by gcInitializeWithDefaultValues727*/728void729gcCleanupInitializeDefaults(OMR_VM* omrVM)730{731MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVM);732MM_EnvironmentBase env(omrVM);733J9JavaVM *vm = (J9JavaVM*) omrVM->_language_vm;734735if (NULL == extensions) {736return;737}738739if (vm->defaultMemorySpace) {740reportPrivateHeapDelete(vm, vm->defaultMemorySpace);741}742743/* defaultMemorySpace is cleared as part of configuration tear down */744if (NULL != extensions->configuration) {745extensions->configuration->kill(&env);746}747748extensions->kill(&env);749750omrVM->_gcOmrVMExtensions = NULL;751((J9JavaVM*)omrVM->_language_vm)->gcExtensions = NULL;752}753754static UDATA755normalizeParameter(UDATA parameter, UDATA numerator, UDATA denominator, UDATA max, UDATA min, UDATA roundTo)756{757UDATA value = (parameter / denominator) * numerator;758759value = MM_Math::roundToCeiling(roundTo, value);760value = (value > max) ? max : value;761value = (value < min) ? min : value;762763return value;764}765766/**767* Calculate the memory parameter value.768* Calculate and store memory parameters in destinationStruct based on the data found in sourceStruct769* @param parameterInfo pointer to parameter info structure770* @param memoryParameters array of parameter values771*/772static void773gcCalculateAndStoreMemoryParameter(MM_GCExtensions *destinationStruct, MM_GCExtensions *sourceStruct, const J9GcMemoryParameter *parameterInfo, IDATA *memoryParameters)774{775if (-1 == memoryParameters[parameterInfo->optionName]) {776/* Only parameters not specified by the user may be massaged based on other values. */777destinationStruct->*(parameterInfo->fieldOffset) =778normalizeParameter(sourceStruct->*(parameterInfo->valueBaseOffset),779parameterInfo->scaleNumerator,780parameterInfo->scaleDenominator,781parameterInfo->valueMax,782parameterInfo->valueMin,783parameterInfo->valueRound);784}785}786787/**788* Calculate memory parameter values.789* Only parameters not specified by the user may be massaged based on other values.790* @param memoryParameters array of parameter values791*/792static jint793gcInitializeCalculatedValues(J9JavaVM *javaVM, IDATA* memoryParameters)794{795MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);796jint result = JNI_OK;797798/* Set initial Xms value: 8M799*800* Note: Will need to verify Xms/Xmos/Xmns fit in user provided values of Xmx.801* This used to be for free, calculations based on Xmx, now it is a manual check802* in setConfigurationSpecificMemoryParameters803*/804UDATA initialXmsValueMax = 8 * 1024 * 1024;805UDATA initialXmsValueMin = 8 * 1024 * 1024;806if (extensions->isSegregatedHeap() || extensions->isMetronomeGC()) {807/* TODO aryoung: eventually segregated heaps will allow heap expansion, although metronome808* itself will still require a fully expanded heap on startup809*/810initialXmsValueMax = J9_MEMORY_MAX;811initialXmsValueMin = UDATA_MAX;812} else if (J9_ARE_ANY_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_TUNE_THROUGHPUT)) {813/* For -Xtune:throughput we want to set Xms=Xmx */814initialXmsValueMax = extensions->memoryMax;815initialXmsValueMin = extensions->memoryMax;816}817818/**819* GC memory parameters to be store in GCExtensions820* opt_Xms will be set to initialXmsValue due to valueMax and valueMin being set821* opt_Xmns will be 50% of Xms822* opt_Xmos will be 50% of Xms823*824* Note: MM_GCExtensions::newSpaceSize should be set here based on opt_Xmns option825*/826const struct J9GcMemoryParameter GCExtensionsParameterTable [] = {827{ &MM_GCExtensions::initialMemorySize, opt_Xms, initialXmsValueMax, initialXmsValueMin, &MM_GCExtensions::maxSizeDefaultMemorySpace, 1, 1, extensions->regionSize },828{ &MM_GCExtensions::minNewSpaceSize, opt_Xmns, (UDATA)-1, 2*MINIMUM_NEW_SPACE_SIZE, &MM_GCExtensions::initialMemorySize, 1, 4, 2*extensions->regionSize },829{ &MM_GCExtensions::newSpaceSize, opt_Xmns, (UDATA)-1, 2*MINIMUM_NEW_SPACE_SIZE, &MM_GCExtensions::initialMemorySize, 1, 4, 2*extensions->regionSize },830{ &MM_GCExtensions::maxNewSpaceSize, opt_Xmnx, (UDATA)-1, 2*MINIMUM_NEW_SPACE_SIZE, &MM_GCExtensions::maxSizeDefaultMemorySpace, 1, 4, 2*extensions->regionSize },831{ &MM_GCExtensions::minOldSpaceSize, opt_Xmos, initialXmsValueMax, MINIMUM_OLD_SPACE_SIZE, &MM_GCExtensions::initialMemorySize, 3, 4, extensions->regionSize },832{ &MM_GCExtensions::oldSpaceSize, opt_Xmos, initialXmsValueMax, MINIMUM_OLD_SPACE_SIZE, &MM_GCExtensions::initialMemorySize, 3, 4, extensions->regionSize },833{ &MM_GCExtensions::maxOldSpaceSize, opt_Xmox, (UDATA)-1, MINIMUM_OLD_SPACE_SIZE, &MM_GCExtensions::maxSizeDefaultMemorySpace, 1, 1, extensions->regionSize },834{ &MM_GCExtensions::allocationIncrement, opt_Xmoi, J9_ALLOCATION_INCREMENT_MAX, J9_ALLOCATION_INCREMENT_MIN, &MM_GCExtensions::maxSizeDefaultMemorySpace, J9_ALLOCATION_INCREMENT_NUMERATOR, J9_ALLOCATION_INCREMENT_DENOMINATOR, extensions->regionSize },835{ &MM_GCExtensions::fixedAllocationIncrement, opt_none, J9_FIXED_SPACE_SIZE_MAX, J9_FIXED_SPACE_SIZE_MIN, &MM_GCExtensions::maxSizeDefaultMemorySpace, J9_FIXED_SPACE_SIZE_NUMERATOR, J9_FIXED_SPACE_SIZE_DENOMINATOR, extensions->regionSize },836};837838const IDATA GCExtensionsParameterTableSize = (sizeof(GCExtensionsParameterTable) / sizeof(struct J9GcMemoryParameter));839IDATA tableIndex;840841/* Set the values which live in the JavaVM since they can't use the common GCExtensions member pointer approach */842if (-1 == memoryParameters[opt_Xmca]) {843javaVM->ramClassAllocationIncrement = normalizeParameter(extensions->maxSizeDefaultMemorySpace, J9_RAM_CLASS_ALLOCATION_INCREMENT_NUMERATOR, J9_RAM_CLASS_ALLOCATION_INCREMENT_DENOMINATOR, J9_RAM_CLASS_ALLOCATION_INCREMENT_MAX, J9_RAM_CLASS_ALLOCATION_INCREMENT_MIN, J9_RAM_CLASS_ALLOCATION_INCREMENT_ROUND_TO);844}845if (-1 == memoryParameters[opt_Xmco]) {846javaVM->romClassAllocationIncrement = normalizeParameter(extensions->maxSizeDefaultMemorySpace, J9_ROM_CLASS_ALLOCATION_INCREMENT_NUMERATOR, J9_ROM_CLASS_ALLOCATION_INCREMENT_DENOMINATOR, J9_ROM_CLASS_ALLOCATION_INCREMENT_MAX, J9_ROM_CLASS_ALLOCATION_INCREMENT_MIN, J9_ROM_CLASS_ALLOCATION_INCREMENT_ROUND_TO);847}848849/* Walk the dependency table fixing unspecified parameters to calculated defaults (mapping GCExtensions values to other GCExtensions values) */850for(tableIndex=0; tableIndex < GCExtensionsParameterTableSize; tableIndex++) {851gcCalculateAndStoreMemoryParameter(extensions, extensions, &(GCExtensionsParameterTable[tableIndex]), memoryParameters);852}853854#if defined (J9VM_GC_VLHGC)855if (0 == extensions->tarokRememberedSetCardListSize) {856uintptr_t cardSize = MM_RememberedSetCard::cardSize(extensions->compressObjectReferences());857/* 4% of region size is allocated for region's RSCL memory */858extensions->tarokRememberedSetCardListSize = extensions->regionSize * 4 / 100 / cardSize;859}860861if (0 == extensions->tarokRememberedSetCardListMaxSize) {862/* Individual RSCL can grow up to 8x of its memory size */863extensions->tarokRememberedSetCardListMaxSize = 8 * extensions->tarokRememberedSetCardListSize;864}865866#endif /* defined (J9VM_GC_VLHGC) */867868/* Number of GC threads must be initialized at this point */869Assert_MM_true(0 < extensions->gcThreadCount);870871/* initialize the size of Local Object Buffer */872if (0 == extensions->objectListFragmentCount) {873extensions->objectListFragmentCount = (4 * extensions->gcThreadCount) + 4;874}875return result;876}877878/**879* Verify memory parameters.880*881* Some configurations do not honour all memory parameters provided by the user. Set these882* parameters to default values and make it appear the user did not specify any values for these883* parameters. A routine that thus checks for user provided input will not validate these884* parameters. Routines that modify configuration specific parameters will need to ensure885* they do not modify these same parameters.886*887* For a flat configuration -Xmn is ignored:888* -Xmn/-Xmns are set to 0889* -Xmnx is set to -Xmx890* memoryParameters structure is modified to make it look like the user did not specify these values.891*892* @param memoryParameters array of parameter values893* @return JNI_OK on success, JNI_ERR on failure894*/895jint896setConfigurationSpecificMemoryParameters(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)897{898MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);899bool opt_XmsSet = (-1 != memoryParameters[opt_Xms]);900bool opt_XmnsSet = (-1 != memoryParameters[opt_Xmns]);901bool opt_XmosSet = (-1 != memoryParameters[opt_Xmos]);902bool opt_XmnxSet = (-1 != memoryParameters[opt_Xmnx]);903904if (flatConfiguration) {905/* Xmns = 0, override fact user may have provided a value */906extensions->minNewSpaceSize = 0;907extensions->newSpaceSize = 0;908extensions->maxNewSpaceSize = 0;909memoryParameters[opt_Xmns] = memoryParameters[opt_Xmnx] = memoryParameters[opt_Xmn] = -1;910911extensions->absoluteMinimumOldSubSpaceSize = MINIMUM_VM_SIZE;912}913914/* Emulation of sovereign behaviour results in Xmx, and Xms being hardcoded. If a value smaller than915* the hardcoded minimum for Xmx is supplied, and this value is less than the hardcoded value of Xms916* then Xms, Xmns and Xmos need to be re-calculated.917*/918/* If Xms was set by the user, then initial guesses for Xmos and Xmns will919* be used in final calculations of those values (i.e. the current values920* are good enough).921*/922if (!opt_XmsSet) {923if (extensions->initialMemorySize > extensions->maxSizeDefaultMemorySpace) {924extensions->initialMemorySize = extensions->maxSizeDefaultMemorySpace;925926if (!opt_XmosSet) {927extensions->oldSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->initialMemorySize/2);928extensions->oldSpaceSize = MM_Math::roundToFloor(extensions->regionSize, extensions->oldSpaceSize);929extensions->oldSpaceSize = (extensions->oldSpaceSize >= extensions->absoluteMinimumOldSubSpaceSize) ? extensions->oldSpaceSize : extensions->absoluteMinimumOldSubSpaceSize;930extensions->minOldSpaceSize = extensions->oldSpaceSize;931}932933if (!flatConfiguration) {934if (!opt_XmnsSet) {935extensions->newSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->initialMemorySize/2);936extensions->newSpaceSize = MM_Math::roundToFloor(extensions->regionSize, extensions->newSpaceSize);937extensions->newSpaceSize = (extensions->newSpaceSize >= (2*extensions->absoluteMinimumNewSubSpaceSize)) ? extensions->newSpaceSize : (2*extensions->absoluteMinimumNewSubSpaceSize);938extensions->minNewSpaceSize = extensions->newSpaceSize;939}940}941}942}943944if (!flatConfiguration && !opt_XmnxSet) {945/* If Xmnx is not set by the user, limit it to the 1/4 of the maximum heap size */946extensions->maxNewSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment * 2,extensions->memoryMax / 4);947extensions->maxNewSpaceSize = MM_Math::roundToFloor(extensions->regionSize * 2, extensions->maxNewSpaceSize);948}949return JNI_OK;950}951952/**953* Verify memory parameters.954*955* Determine which memory parameter to display to the user in the event of an error.956* @param memoryParameters array of parameter values957* @return pointer to "-Xmx" or "-XX:MaxRAMPercentage"958*/959static const char *960displayXmxOrMaxRAMPercentage(IDATA* memoryParameters)961{962if ((-1 != memoryParameters[opt_maxRAMPercent])963&& (memoryParameters[opt_Xmx] == memoryParameters[opt_maxRAMPercent])964) {965return "-Xmx (as set by -XX:MaxRAMPercentage)";966} else {967return "-Xmx";968}969}970971/**972* Verify memory parameters.973*974* Determine which memory parameter to display to the user in the event of an error.975* @param memoryParameters array of parameter values976* @return pointer to "-Xms" or "-XX:InitialRAMPercentage"977*/978static const char *979displayXmsOrInitialRAMPercentage(IDATA* memoryParameters)980{981if ((-1 != memoryParameters[opt_initialRAMPercent])982&& (memoryParameters[opt_Xms] == memoryParameters[opt_initialRAMPercent])983) {984return "-Xms (as set by -XX:InitialRAMPercentage)";985} else {986return "-Xms";987}988}989990/**991* Verify memory parameters.992*993* Determine which memory parameter to display to the user in the event of an error.994* @param memoryParameters array of parameter values995* @return pointer to "-Xmn" or "-Xmns"996*/997const char *998displayXmnOrXmns(IDATA* memoryParameters)999{1000return (memoryParameters[opt_Xmn] == memoryParameters[opt_Xmns]) ? "-Xmn" : "-Xmns";1001}10021003/**1004* Verify memory parameters.1005*1006* Determine which memory parameter to display to the user in the event of an error.1007* @param memoryParameters array of parameter values1008* @return pointer to "-Xmn" or "-Xmnx" *1009*/1010const char *1011displayXmnOrXmnx(IDATA* memoryParameters)1012{1013return (memoryParameters[opt_Xmn] == memoryParameters[opt_Xmnx]) ? "-Xmn" : "-Xmnx";1014}10151016/**1017* Verify memory parameters.1018*1019* Determine which memory parameter to display to the user in the event of an error.1020* @param memoryParameters array of parameter values1021* @return pointer to "-Xmo" or "-Xmos" *1022*/1023const char *1024displayXmoOrXmos(IDATA* memoryParameters)1025{1026return (memoryParameters[opt_Xmo] == memoryParameters[opt_Xmos]) ? "-Xmo" : "-Xmos";1027}10281029/**1030* Verify memory parameters.1031*1032* Determine which memory parameter to display to the user in the event of an error.1033* @param memoryParameters array of parameter values1034* @return pointer to "-Xmo" or "-Xmox"1035*/1036const char *1037displayXmoOrXmox(IDATA* memoryParameters)1038{1039return (memoryParameters[opt_Xmo] == memoryParameters[opt_Xmox]) ? "-Xmo" : "-Xmox";1040}1041/**1042* Verify memory parameters.1043*1044* Ensure that Xmx is larger than the minimum size.1045* Ensure that Xmdx is larger than the minimum size, less than Xmx.1046*1047* The following is guaranteed after this method1048*1049* 1/ minimumConfigurationSize <= Xmx1050* 2/ minimumConfigurationSize <= Xmdx <= Xmx1051*1052* @param javaVM The javaVM1053* @param memoryParameters Memory options provided by user1054* @param flatConfiguration True if running without scavenger1055* @param minimumSize The size for lower bound testing1056* @param memoryOption1 If non NULL then this and memoryOption2 are used in error messages as a sum (e.g. sum of memoryOption1 and memoryOption2 is ...)1057* @param memoryOption2 See memoryOption11058*1059* @return JNI_OK on success, JNI_ERR on failure.1060* @note error message is printed out indicating type of failure1061*/1062static jint1063gcInitializeXmxXmdxVerification(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration, UDATA minimumSizeValue, const char *memoryOption1, const char *memoryOption2)1064{1065MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);10661067/* Error reporting */1068const char *subSpaceTooLargeOption;10691070bool opt_XmxSet = (-1 != memoryParameters[opt_Xmx]);1071bool opt_XmdxSet = (-1 != memoryParameters[opt_Xmdx]);1072PORT_ACCESS_FROM_JAVAVM(javaVM);10731074/* Align both Xmx and Xmdx */1075extensions->memoryMax = MM_Math::roundToFloor(extensions->heapAlignment, extensions->memoryMax);1076extensions->maxSizeDefaultMemorySpace = MM_Math::roundToFloor(extensions->heapAlignment, extensions->maxSizeDefaultMemorySpace);1077extensions->memoryMax = MM_Math::roundToFloor(extensions->regionSize, extensions->memoryMax);1078extensions->maxSizeDefaultMemorySpace = MM_Math::roundToFloor(extensions->regionSize, extensions->maxSizeDefaultMemorySpace);10791080#if defined (OMR_GC_COMPRESSED_POINTERS)1081if (extensions->compressObjectReferences()) {1082if (extensions->shouldAllowShiftingCompression) {1083if (extensions->shouldForceSpecifiedShiftingCompression) {1084extensions->heapCeiling = NON_SCALING_LOW_MEMORY_HEAP_CEILING << extensions->forcedShiftingCompressionAmount;1085} else {1086extensions->heapCeiling = LOW_MEMORY_HEAP_CEILING;1087}1088} else {1089extensions->heapCeiling = NON_SCALING_LOW_MEMORY_HEAP_CEILING;1090}10911092#if defined(J9ZOS39064)1093{1094/*1095* In order to support Compressed References ZOS should support one of:1096* - 2_TO_64 to support heaps allocation below 64GB1097* - 2_TO_32 to support heaps allocation below 32GB1098*/1099U_64 maxHeapForCR = zosGetMaxHeapSizeForCR();1100if (0 == maxHeapForCR) {1101/* Redirector should not allow to run Compressed References JVM if options are not available */1102Assert_MM_unreachable();1103/* Fail to initialize if assertions are off */1104return JNI_ERR;1105}11061107/* Adjust heap ceiling value if it is necessary */1108if (extensions->heapCeiling > maxHeapForCR) {1109extensions->heapCeiling = maxHeapForCR;1110}1111}1112#endif /* defined(J9ZOS39064) */11131114if (extensions->memoryMax > (extensions->heapCeiling - J9GC_COMPRESSED_POINTER_NULL_REGION_SIZE)) {1115j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTION_OVERFLOW, displayXmxOrMaxRAMPercentage(memoryParameters));1116return JNI_ERR;1117}1118}1119#endif /* defined (OMR_GC_COMPRESSED_POINTERS) */11201121/* Verify Xmx is too small */1122if (extensions->memoryMax < minimumSizeValue) {1123if (NULL == memoryOption1) {1124memoryOption1 = displayXmxOrMaxRAMPercentage(memoryParameters);1125memoryOption2 = NULL;1126goto _subSpaceTooSmallForValue;1127} else {1128if (opt_XmxSet) {1129subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);1130goto _subSpaceTooLarge;1131}1132goto _subSpaceTooLargeForHeap;1133}1134}11351136#if defined(J9ZTPF)1137/* Only if Xmx is specified, verify the value doesn't go over usable memory. */1138if (opt_XmxSet) {1139if (extensions->memoryMax > extensions->usablePhysicalMemory) {1140memoryOption1 = "-Xmx";1141memoryOption2 = NULL;1142goto _subSpaceTooLargeForHeap;1143}1144}1145#endif /* defined(J9ZTPF) */11461147/* Verify Xmdx is not too small, or too big */1148if (opt_XmdxSet) {1149if (extensions->maxSizeDefaultMemorySpace < minimumSizeValue) {1150if (NULL == memoryOption1) {1151memoryOption1 = "-Xmdx";1152memoryOption2 = NULL;1153goto _subSpaceTooSmallForValue;1154} else {1155subSpaceTooLargeOption = "-Xmdx";1156goto _subSpaceTooLarge;1157}1158}11591160if (extensions->maxSizeDefaultMemorySpace > extensions->memoryMax) {1161memoryOption1 = "-Xmdx";1162memoryOption2 = NULL;1163if (opt_XmxSet) {1164subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);1165goto _subSpaceTooLarge;1166}1167goto _subSpaceTooLargeForHeap;1168}1169} else {1170/* Special case for Xmdx. The Xmdx value is calculated as a fraction of Xmx.1171* It is possible for small enough values of Xmx that Xmdx will be less than1172* the size of a subSpace. Ensure Xmdx is at least as large as the configuration1173* size in this case. Xmx is already known to be larger than that size.1174*/1175if (extensions->maxSizeDefaultMemorySpace < minimumSizeValue) {1176extensions->maxSizeDefaultMemorySpace = minimumSizeValue;1177}1178}11791180/* Still need to verify the minimum size of Xmx/Xmdx is not less than the required1181* minimum subSpace size (oldSpace/NewSpace). Do this verification after those minimum1182* values are verified.1183*/1184return JNI_OK;11851186_subSpaceTooSmallForValue:1187{1188const char *qualifier = NULL;1189qualifiedSize(&minimumSizeValue, &qualifier);1190j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_SMALL_FOR_VALUE, memoryOption1, minimumSizeValue, qualifier);1191return JNI_ERR;1192}11931194_subSpaceTooLarge:1195if (NULL == memoryOption2) {1196j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE, memoryOption1, subSpaceTooLargeOption);1197} else {1198j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE, memoryOption1, memoryOption2, subSpaceTooLargeOption);1199}1200return JNI_ERR;12011202_subSpaceTooLargeForHeap:1203if (NULL == memoryOption2) {1204j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE_FOR_HEAP, memoryOption1);1205} else {1206j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE_FOR_HEAP, memoryOption1, memoryOption2);1207}1208return JNI_ERR;1209}12101211/**1212* Verify memory parameters.1213*1214* For each memory parameter specified by the user verify the following conditions independent1215* of any other memory parameter: alignment, minimum size, maximum size.1216*1217* Maximum size is compared against either Xmx, Xmdx or Xms. The largest of these values1218* that is set by the user is used where applicable.1219*1220* For all user provided memory parameters, the following are guaranteed upon completion1221*1222* 1/ minimumConfigurationSize <= Xms <= Xmdx1223* 2/ absoluteMinimumOldSubSpaceSize <= Xmos <= Xmox <= Xms|Xmdx|Xmx1224* 3/ absoluteMinimumNewSubSpaceSize <= Xmns <= Xmnx <= Xms|Xmdx|Xmx1225*1226* @return JNI_OK on success, JNI_ERR on failure.1227* @note error message is printed out indicating type of failure1228*/1229jint1230independentMemoryParameterVerification(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)1231{1232PORT_ACCESS_FROM_JAVAVM(javaVM);1233MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);12341235UDATA minimumSizeValue; /* For displaying error message */1236const char *memoryOption = NULL;1237const char *memoryOption2 = NULL;1238const char *subSpaceTooLargeOption;12391240/* Maximum size for Xmdx, Xmox, Xmnx */1241UDATA maximumXmdxValue = extensions->memoryMax;1242const char *maximumXmdxValueParameter = NULL;12431244/* Maximum size for Xms, Xmos, Xmns */1245UDATA maximumXmsValue = extensions->memoryMax;1246const char *maximumXmsValueParameter = NULL;1247UDATA XmsMinimumValue = 0;12481249bool opt_XmxSet = (-1 != memoryParameters[opt_Xmx]);1250bool opt_XmdxSet = (-1 != memoryParameters[opt_Xmdx]);1251bool opt_XmsSet = (-1 != memoryParameters[opt_Xms]);1252bool opt_XmnsSet = (-1 != memoryParameters[opt_Xmns]);1253bool opt_XmnxSet = (-1 != memoryParameters[opt_Xmnx]);1254bool opt_XmosSet = (-1 != memoryParameters[opt_Xmos]);1255bool opt_XmoxSet = (-1 != memoryParameters[opt_Xmox]);1256bool opt_XsoftmxSet = (-1 != memoryParameters[opt_Xsoftmx]);12571258/* These values will be reset if Xmos/Xmns are user provided.1259* Initially minimum size to verify Xmos/Xmns input.1260*1261* Can't use extensions->minNewSpaceSize as that value is pre-calculated1262* to be a realistic value; a valid user input value may be less than this1263* calculated value, but it must be greater than the minimum value.1264*/1265UDATA oldSpaceSizeMinimum = extensions->absoluteMinimumOldSubSpaceSize;1266UDATA newSpaceSizeMinimum = 2*extensions->absoluteMinimumNewSubSpaceSize;12671268/* Xmx and Xmdx have already been verified1269* Need to set maximumXmdxValue and maximumXmsValue as per Xmdx settings1270* Can not verify minimum values until Xmns/Xmos have been verified.1271*/1272if (opt_XmxSet) {1273maximumXmdxValueParameter = displayXmxOrMaxRAMPercentage(memoryParameters);1274maximumXmsValueParameter = displayXmxOrMaxRAMPercentage(memoryParameters);1275}12761277if (opt_XmdxSet) {1278/* When comparing to maximum boundary use the Xmdx value */1279maximumXmdxValue = extensions->maxSizeDefaultMemorySpace;1280maximumXmdxValueParameter = "-Xmdx";12811282/* When comparing initialMemorySizes to maximum boundary, use the Xmdx value1283* Just need to reset the reported parameter, value is currently set to Xmdx1284*/1285maximumXmsValue = extensions->maxSizeDefaultMemorySpace;1286maximumXmsValueParameter = "-Xmdx";1287}12881289/* Align Xms, verify it is not too large */1290if (opt_XmsSet) {1291extensions->initialMemorySize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->initialMemorySize);1292extensions->initialMemorySize = MM_Math::roundToFloor(extensions->regionSize, extensions->initialMemorySize);12931294if (flatConfiguration) {1295/* Flat configuration Collector can start with one region */1296extensions->initialMemorySize = OMR_MAX(extensions->regionSize, extensions->initialMemorySize);1297} else {1298/* Gencon required at least three regions to start with (one for Tenure and two for Nursery - one for each half) */1299extensions->initialMemorySize = OMR_MAX(extensions->regionSize * 3, extensions->initialMemorySize);1300}13011302if (extensions->initialMemorySize > maximumXmsValue) {1303memoryOption = displayXmsOrInitialRAMPercentage(memoryParameters);1304if (maximumXmsValueParameter) {1305subSpaceTooLargeOption = maximumXmsValueParameter;1306goto _subSpaceTooLarge;1307}1308goto _subSpaceTooLargeForHeap;1309}13101311/* When comparing to maximum boundary use the Xms value */1312maximumXmsValue = extensions->initialMemorySize;1313maximumXmsValueParameter = displayXmsOrInitialRAMPercentage(memoryParameters);1314}13151316/* verify -Xsoftmx is set between -Xms and -Xmx */1317if (opt_XsoftmxSet) {1318extensions->softMx = MM_Math::roundToFloor(extensions->heapAlignment, extensions->softMx);1319extensions->softMx = MM_Math::roundToFloor(extensions->regionSize, extensions->softMx);13201321if (extensions->softMx > extensions->memoryMax) {1322memoryOption = "-Xsoftmx";1323goto _subSpaceTooLargeForHeap;1324}13251326if (extensions->softMx < extensions->initialMemorySize) {1327memoryOption = "-Xsoftmx";1328minimumSizeValue = extensions->initialMemorySize;1329goto _subSpaceTooSmallForValue;1330}1331}13321333/* Align Xmns, verify it is not too large or too small.1334* Defer checking that Xmns <= Xmnx as Xmnx has not been verified yet.1335* There are two semi-spaces1336*/1337if (opt_XmnsSet) {1338extensions->newSpaceSize = MM_Math::roundToFloor(2*extensions->heapAlignment, extensions->newSpaceSize);1339extensions->newSpaceSize = MM_Math::roundToFloor(2*extensions->regionSize, extensions->newSpaceSize);1340extensions->newSpaceSize = OMR_MAX(extensions->regionSize * 2, extensions->newSpaceSize);13411342if (extensions->newSpaceSize < newSpaceSizeMinimum) {1343memoryOption = displayXmnOrXmns(memoryParameters);1344minimumSizeValue = newSpaceSizeMinimum; /* display min size */1345goto _subSpaceTooSmallForValue;1346}13471348if (extensions->newSpaceSize > maximumXmsValue) {1349memoryOption = displayXmnOrXmns(memoryParameters);1350if (maximumXmsValueParameter) {1351subSpaceTooLargeOption = maximumXmsValueParameter; /* display correct parameter */1352goto _subSpaceTooLarge;1353}1354goto _subSpaceTooLargeForHeap;1355}13561357/* Update newSpaceSizeMinimum */1358newSpaceSizeMinimum = extensions->newSpaceSize;1359extensions->minNewSpaceSize = extensions->newSpaceSize;1360}13611362/* Align Xmnx, verify it is not too large or too small.1363* There are two semi-spaces1364*/1365if (opt_XmnxSet) {1366extensions->maxNewSpaceSize = MM_Math::roundToFloor(2*extensions->heapAlignment, extensions->maxNewSpaceSize);1367extensions->maxNewSpaceSize = MM_Math::roundToFloor(2*extensions->regionSize, extensions->maxNewSpaceSize);13681369if (extensions->maxNewSpaceSize < newSpaceSizeMinimum) {1370memoryOption = displayXmnOrXmnx(memoryParameters);1371minimumSizeValue = newSpaceSizeMinimum; /* display min size */1372goto _subSpaceTooSmallForValue;1373}13741375if (extensions->maxNewSpaceSize > maximumXmdxValue) {1376memoryOption = displayXmnOrXmnx(memoryParameters);1377if (maximumXmdxValueParameter) {1378subSpaceTooLargeOption = maximumXmdxValueParameter;1379goto _subSpaceTooLarge;1380}1381goto _subSpaceTooLargeForHeap;1382}13831384if (opt_XmnsSet && (extensions->maxNewSpaceSize < extensions->newSpaceSize)) {1385memoryOption = displayXmnOrXmns(memoryParameters);1386subSpaceTooLargeOption = displayXmnOrXmnx(memoryParameters);1387goto _subSpaceTooLarge;1388}1389}139013911392/* Align Xmos, verify it is not too large or too small.1393* Defer checking that Xmos < Xmox as Xmox has not been verified yet.1394*/1395if (opt_XmosSet) {1396extensions->oldSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->oldSpaceSize);1397extensions->oldSpaceSize = MM_Math::roundToFloor(extensions->regionSize, extensions->oldSpaceSize);1398extensions->oldSpaceSize = OMR_MAX(extensions->regionSize, extensions->oldSpaceSize);13991400if (extensions->oldSpaceSize < oldSpaceSizeMinimum) {1401memoryOption = displayXmoOrXmos(memoryParameters);1402minimumSizeValue = oldSpaceSizeMinimum;1403goto _subSpaceTooSmallForValue;1404}14051406if (extensions->oldSpaceSize > maximumXmsValue) {1407memoryOption = displayXmoOrXmos(memoryParameters);1408if (maximumXmsValueParameter) {1409subSpaceTooLargeOption = maximumXmsValueParameter; /* display correct parameter */1410goto _subSpaceTooLarge;1411}1412goto _subSpaceTooLargeForHeap;1413}14141415/* Update local oldSpaceSizeMinimum */1416oldSpaceSizeMinimum = extensions->oldSpaceSize;1417extensions->minOldSpaceSize = extensions->oldSpaceSize;1418}14191420/* Align Xmox, verify it is not too large or too small. */1421if (opt_XmoxSet) {1422extensions->maxOldSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->maxOldSpaceSize);1423extensions->maxOldSpaceSize = MM_Math::roundToFloor(extensions->regionSize, extensions->maxOldSpaceSize);14241425if (extensions->maxOldSpaceSize < oldSpaceSizeMinimum) {1426/* Display minSubSpace size, or Xmos/Xmox value if both were set */1427if (opt_XmosSet) {1428subSpaceTooLargeOption = displayXmoOrXmox(memoryParameters);1429memoryOption = displayXmoOrXmos(memoryParameters);1430goto _subSpaceTooLarge;1431}1432memoryOption = displayXmoOrXmox(memoryParameters);1433minimumSizeValue = oldSpaceSizeMinimum;1434goto _subSpaceTooSmallForValue;1435}14361437if (extensions->maxOldSpaceSize > maximumXmdxValue) {1438memoryOption = displayXmoOrXmox(memoryParameters);1439if (maximumXmdxValueParameter) {1440subSpaceTooLargeOption = maximumXmdxValueParameter;1441goto _subSpaceTooLarge;1442}1443goto _subSpaceTooLargeForHeap;1444}14451446if (opt_XmosSet && (extensions->maxOldSpaceSize < extensions->oldSpaceSize)) {1447memoryOption = displayXmoOrXmos(memoryParameters);1448subSpaceTooLargeOption = displayXmoOrXmox(memoryParameters);1449goto _subSpaceTooLarge;1450}14511452}14531454/* Verify Xmx,Xmdx,Xms are not too small based on minimum oldSpace and newSpace values */1455XmsMinimumValue = oldSpaceSizeMinimum;14561457if (!flatConfiguration) {1458XmsMinimumValue += newSpaceSizeMinimum;1459}14601461/* Before verifying Xmx/Xmdx is large enough for user provided values of Xmos/Xmns, create an1462* output buffer so the error messages can be displayed in relation to specified memory parameters,1463* rather than a random number (the sume of Xmos/Xmns for example). This buffer may never1464* be displayed if all values are good.1465*1466* If the user did not specify either Xmos or Xmns then this buffer will be null, and a number1467* will be displayed if Xmx/Xmdx was specified too small.1468*/1469if (opt_XmosSet) {1470if (opt_XmnsSet) {1471memoryOption = displayXmoOrXmos(memoryParameters);1472memoryOption2 = displayXmnOrXmns(memoryParameters);1473} else {1474memoryOption = displayXmoOrXmos(memoryParameters);1475}1476} else {1477if (opt_XmnsSet) {1478memoryOption = displayXmnOrXmns(memoryParameters);1479}1480}14811482/* Will display error message with size error. For example if the combination of Xmos/Xmns is greater1483* than the specified Xmdx value, says Xmdx is too small, must be at least xxx bytes, rather than1484* the Sum of Xmos + Xmns is too large for Xmdx. It is correct, just possibly confusing1485*/1486if (gcInitializeXmxXmdxVerification(javaVM, memoryParameters, flatConfiguration, XmsMinimumValue, memoryOption, memoryOption2) != JNI_OK) {1487return JNI_ERR;1488}14891490if (opt_XmsSet && (extensions->initialMemorySize < XmsMinimumValue)) {1491if (NULL == memoryOption) {1492memoryOption = displayXmsOrInitialRAMPercentage(memoryParameters);1493minimumSizeValue = XmsMinimumValue; /* display min size */1494goto _subSpaceTooSmallForValue;1495} else {1496subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);1497goto _subSpaceTooLarge;1498}1499}15001501/* Align Xmoi if set by the user */1502if (extensions->allocationIncrementSetByUser) {1503extensions->allocationIncrement = MM_Math::roundToCeiling(extensions->heapAlignment, extensions->allocationIncrement);1504extensions->allocationIncrement = MM_Math::roundToCeiling(extensions->regionSize, extensions->allocationIncrement);1505}15061507#if defined(OMR_GC_COMPRESSED_POINTERS)1508if (J9JAVAVM_COMPRESS_OBJECT_REFERENCES(javaVM)) {1509/* Align the Xmcrs if necessary */1510extensions->suballocatorInitialSize = MM_Math::roundToCeiling(SUBALLOCATOR_ALIGNMENT, extensions->suballocatorInitialSize);1511}1512#endif /* defined(OMR_GC_COMPRESSED_POINTERS) */15131514return JNI_OK;15151516_subSpaceTooSmallForValue:1517{1518const char *qualifier = NULL;1519qualifiedSize(&minimumSizeValue, &qualifier);1520j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_SMALL_FOR_VALUE, memoryOption, minimumSizeValue, qualifier);1521return JNI_ERR;1522}15231524_subSpaceTooLarge:1525if (NULL == memoryOption2) {1526j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE, memoryOption, subSpaceTooLargeOption);1527} else {1528j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE, memoryOption, memoryOption2, subSpaceTooLargeOption);1529}1530return JNI_ERR;15311532_subSpaceTooLargeForHeap:1533if (NULL == memoryOption2) {1534j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE_FOR_HEAP, memoryOption);1535} else {1536j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE_FOR_HEAP, memoryOption, memoryOption2);1537}1538return JNI_ERR;15391540}15411542/**1543* Compares a potentially specified parameter value against a given limit value1544* @param toTest[in] The parameter to test1545* @param maximum[in] The maximum against which toTest must be compared1546* @return true if the given parameter toTest is either unspecified or not greater than the given fixed maximum1547*/1548static bool1549isLessThanEqualOrUnspecifiedAgainstFixed(MM_UserSpecifiedParameterUDATA *toTest, UDATA maximum)1550{1551bool isSafe = true;1552if (toTest->_wasSpecified) {1553isSafe = (toTest->_valueSpecified <= maximum);1554}1555return isSafe;1556}15571558/**1559* Compares two potentially specified parameter values against to ensure that they have the permitted relative values1560* @param minimum[in] The parameter which, if specified, must be no greater than maximum1561* @param maximum[in] The parameter which, if specified, must be no less than maximum1562* @return true if not both of the parameters are specified or minimum is no greater than maximum1563*/1564static bool1565isLessThanEqualOrUnspecifiedAgainstOption(MM_UserSpecifiedParameterUDATA *minimum, MM_UserSpecifiedParameterUDATA *maximum)1566{1567bool isSafe = true;1568if (minimum->_wasSpecified && maximum->_wasSpecified) {1569isSafe = (minimum->_valueSpecified <= maximum->_valueSpecified);1570}1571return isSafe;1572}15731574/**1575* Verify memory parameters.1576*1577* For all user set values verify that the provided values are valid for all configurations.1578* Since individual verification has already occurred, need only verify that combinations are1579* correct. For example if Xmns + Xmos = Xms.1580*1581* Recalculate non user specified values if required.1582*1583* @return JNI_OK on success, JNI_ERR on failure.1584* @note error message is printed out indicating type of failure1585*/1586jint1587combinationMemoryParameterVerification(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)1588{1589MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);15901591/* For displaying error messages */1592const char *memoryOption = NULL;1593const char *memoryOption2 = NULL;1594const char *subSpaceTooLargeOption = NULL;1595const char *subSpaceTooSmallOption = NULL;1596const char *memoryOptionMinimumDifference = NULL;1597float minValue, maxValue;1598UDATA minimumSizeValue;15991600/* The absolute maximum value that Xms can take, and what memory parameter set it (Xmx/Xmdx/Xms) */1601UDATA maximumXmsValue;1602const char *maximumXmsValueParameter = NULL;16031604/* Bitmap of memory parameters set by the user */1605UDATA setMemoryParameters;1606bool opt_XmxSet = (-1 != memoryParameters[opt_Xmx]);1607bool opt_XmdxSet = (-1 != memoryParameters[opt_Xmdx]);1608bool opt_XmsSet = (-1 != memoryParameters[opt_Xms]);1609bool opt_XmnsSet = (-1 != memoryParameters[opt_Xmns]);1610bool opt_XmnxSet = (-1 != memoryParameters[opt_Xmnx]);1611bool opt_XmosSet = (-1 != memoryParameters[opt_Xmos]);1612bool opt_XmoxSet = (-1 != memoryParameters[opt_Xmox]);1613bool opt_XsoftmxSet = (-1 != memoryParameters[opt_Xsoftmx]);1614bool opt_XmcrsSet = (-1 != memoryParameters[opt_Xmcrs]);16151616PORT_ACCESS_FROM_JAVAVM(javaVM);16171618/* User specified combinations of Xmdx and Xms */1619setMemoryParameters = NONE;1620if (opt_XmdxSet) {1621setMemoryParameters |= XMDX;1622}1623if (opt_XmsSet) {1624setMemoryParameters |= XMS;1625}16261627/* Determine maximumXmsValue.1628* Verify Xmdx >= Xms where applicable1629*/1630switch (setMemoryParameters) {1631case XMDX_XMS:1632/* Xmdx, Xms - already verified1633*/1634assume0(extensions->maxSizeDefaultMemorySpace <= extensions->memoryMax);1635assume0(extensions->initialMemorySize <= extensions->maxSizeDefaultMemorySpace);16361637maximumXmsValue = extensions->initialMemorySize;1638maximumXmsValueParameter = displayXmsOrInitialRAMPercentage(memoryParameters);1639break;16401641case XMDX:1642/* Xmdx, ^Xms - verification required1643* adjust Xms if necessary1644*/1645if (extensions->initialMemorySize > extensions->maxSizeDefaultMemorySpace) {1646extensions->initialMemorySize = extensions->maxSizeDefaultMemorySpace;1647}16481649maximumXmsValue = extensions->maxSizeDefaultMemorySpace;1650maximumXmsValueParameter = "-Xmdx";1651break;16521653case XMS:1654/* ^Xmdx, Xms - verification required1655* adjust Xmdx if necessary1656*/1657if (extensions->initialMemorySize > extensions->maxSizeDefaultMemorySpace) {1658extensions->maxSizeDefaultMemorySpace = extensions->initialMemorySize;1659}16601661maximumXmsValue = extensions->initialMemorySize;1662maximumXmsValueParameter = displayXmsOrInitialRAMPercentage(memoryParameters);1663break;16641665case NONE:1666/* ^Xmdx, ^Xms - both calculated, verification not required1667*/1668assume0(extensions->maxSizeDefaultMemorySpace <= extensions->memoryMax);1669assume0(extensions->initialMemorySize <= extensions->maxSizeDefaultMemorySpace);16701671maximumXmsValue = extensions->memoryMax;1672if (opt_XmxSet) {1673maximumXmsValueParameter = displayXmxOrMaxRAMPercentage(memoryParameters);1674}1675break;16761677default:1678j9tty_printf(PORTLIB, "Internal GC error %p\n", setMemoryParameters); /* No NLS */1679assume0(0); /* should never get here */1680return JNI_ERR;1681break;1682}16831684/* It is now known that for all Xms <= Xmdx <= Xmx for all scenarios (user set or not)1685* It is also known what the absolute maximum value for Xmos + Xmns (maximumXmsValue).1686* Further it is known which user set parameter that maximum value is dictated by (maximumXmsValueParameter).1687*1688* First deal with the flat configuration. In this configuration Xmos = Xms, unless the1689* user has specified values. Xmns is 0.1690*/1691if (flatConfiguration) {1692/* User specified combinations of Xms and Xmos1693*/1694setMemoryParameters = NONE;1695if (opt_XmsSet) {1696setMemoryParameters |= XMS;1697}1698if (opt_XmosSet) {1699setMemoryParameters |= XMOS;1700}17011702/* Following the switch statement memory parameters not set by the user1703* will be reset as required1704*/1705switch (setMemoryParameters) {1706case XMS_XMOS:1707/* Previously verified that1708* 1/ Xms <= Xmx1709* 2/ Xms <= Xmdx, if Xmdx was specified1710* 3/ Xmos <= Xms1711* 4/ Xmos <= Xmnx, if Xmnx was specified1712*1713* Enforce Xms = Xmos1714*/1715if (extensions->oldSpaceSize != extensions->initialMemorySize) {1716memoryOption = displayXmoOrXmos(memoryParameters);1717memoryOption2 = displayXmsOrInitialRAMPercentage(memoryParameters);1718goto _subSpaceNotEqualError;1719}1720break;17211722case XMS:1723/* Previously verified1724* 1/ Xms <= Xmx1725* 2/ Xms <= Xmdx, if Xmdx was specified1726*1727* Set Xmos = Xms, (Enforce Xms = Xmos)1728* Ensure Xmos <= Xmox, if Xmox was specified1729*/1730if (extensions->isSegregatedHeap() || extensions->isMetronomeGC()) {1731/* TODO aryoung: eventually segregated heaps will allow heap expansion, although metronome1732* itself will still require a fully expanded heap on startup */1733#if defined(J9VM_GC_REALTIME) || defined(J9VM_GC_SEGREGATED_HEAP)1734if (extensions->initialMemorySize != extensions->memoryMax) {1735/* Ignore the specified -Xms value.1736* Override it too, so that verbose:sizes displays correctly the actual value.1737*/1738extensions->initialMemorySize = extensions->memoryMax;1739/* Sometime in future, we may want to give a hard error, instead.1740memoryOption = "-Xms";1741memoryOption2 = "-Xmx";1742goto _subSpaceNotEqualError;1743*/1744}1745#endif /* defined(J9VM_GC_REALTIME) || defined(J9VM_GC_SEGREGATED_HEAP) */1746}17471748extensions->oldSpaceSize = extensions->initialMemorySize;1749extensions->minOldSpaceSize = extensions->initialMemorySize;17501751if (opt_XmoxSet && (extensions->oldSpaceSize > extensions->maxOldSpaceSize)) {1752memoryOption = displayXmoOrXmox(memoryParameters);1753subSpaceTooSmallOption = displayXmsOrInitialRAMPercentage(memoryParameters);1754goto _subSpaceTooSmall;1755}1756break;17571758case XMOS:1759/* Previously verified1760* 1/ Xmos <= Xmx1761* 2/ Xmos <= Xmdx, if Xmdx was specified1762* 3/ Xmos <= Xmnx, if Xmnx was specified1763*1764* Nothing left to do1765*/17661767break;17681769case NONE:1770/* Previously ensured that Xms is <= Xmdx <= Xmx1771* Set Xmo = Xms for sovereign compliance1772*/1773extensions->oldSpaceSize = extensions->initialMemorySize;1774extensions->minOldSpaceSize = extensions->initialMemorySize;1775break;17761777default:1778j9tty_printf(PORTLIB, "Internal GC error %p\n", setMemoryParameters); /* No NLS */1779assume0(0); /* should never get here */1780return JNI_ERR;1781break;1782}17831784/* Reset Xmdx if necessary */1785if (!opt_XmdxSet && (extensions->maxSizeDefaultMemorySpace < extensions->oldSpaceSize)) {1786extensions->maxSizeDefaultMemorySpace = extensions->oldSpaceSize;1787}17881789/* Reset Xmox if not user provided */1790if (!opt_XmoxSet) {1791extensions->maxOldSpaceSize = extensions->maxSizeDefaultMemorySpace;1792}17931794/* Reset Xms if not user provided */1795if (!opt_XmsSet) {1796extensions->initialMemorySize = extensions->oldSpaceSize;1797}17981799/* Reset minimum values if necessary */1800if (extensions->minOldSpaceSize > extensions->oldSpaceSize) {1801extensions->minOldSpaceSize = extensions->oldSpaceSize;1802}1803} else {1804/* Non flat configurations1805* User specified combinations of Xmos and Xmns1806*/1807setMemoryParameters = NONE;1808if (opt_XmosSet) {1809setMemoryParameters |= XMOS;1810}1811if (opt_XmnsSet) {1812setMemoryParameters |= XMNS;1813}18141815/* Calculate Xmns/Xmos where required.1816* Following the switch statement memory parameters not set by the user1817* will be reset as required1818*/1819UDATA combinedXmosXmnsSize;1820UDATA candidateXmosValue;1821UDATA candidateXmnsValue;1822UDATA newSpaceSizeMinimum = opt_XmnsSet ? extensions->minNewSpaceSize : 2*extensions->absoluteMinimumNewSubSpaceSize;1823UDATA oldSpaceSizeMinimum = opt_XmosSet ? extensions->minOldSpaceSize : extensions->absoluteMinimumOldSubSpaceSize;18241825switch (setMemoryParameters) {1826case XMOS_XMNS:1827/* Previously verified1828* 1/ Xmos <= Xms|Xmdx|Xmx1829* 2/ Xmns <= Xms|Xmdx|Xmx1830* 3/ Xmos <= Xmox, if Xmox specified1831* 4/ Xmns <= Xmnx, if Xmnx specified1832*1833* Ensure the combined value will fit in the Xms value. It does not matter if Xms was set1834* by the user for this test.1835*/1836if ((extensions->oldSpaceSize + extensions->newSpaceSize) > maximumXmsValue) {1837memoryOption = displayXmoOrXmos(memoryParameters);1838memoryOption2 = displayXmnOrXmns(memoryParameters);1839if (maximumXmsValueParameter) {1840subSpaceTooLargeOption = maximumXmsValueParameter;1841goto _subSpaceCombinationTooLarge;1842}1843goto _subSpaceCombinationTooLargeForHeap;1844}18451846assume0(extensions->newSpaceSize = extensions->minNewSpaceSize);1847assume0(extensions->oldSpaceSize = extensions->minOldSpaceSize);18481849/* Enforce Xms = Xmns + Xmos */1850if (opt_XmsSet && ((extensions->oldSpaceSize + extensions->newSpaceSize) != extensions->initialMemorySize)) {1851memoryOption = displayXmoOrXmos(memoryParameters);1852memoryOption2 = displayXmnOrXmns(memoryParameters);1853subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);1854goto _subSpaceCombinationNotEqual;1855}1856break;18571858case XMOS:1859/* Previously verified1860* 1/ Xmos <= Xms|Xmdx|Xmx1861* 2/ Xmos <= Xmox, if Xmox specified1862*1863* If Xms is set, then Xmns = Xms - Xmos, else use the previously calculated Xmns value1864* Verify calculated value is not too small or too large.1865*1866* The same algorithm applies to the XMNS case1867*/1868assume0(extensions->oldSpaceSize = extensions->minOldSpaceSize);1869if(opt_XmsSet) {1870/* Live with user input */1871candidateXmnsValue = extensions->initialMemorySize - extensions->oldSpaceSize;18721873/* Verify not too small */1874if (candidateXmnsValue < newSpaceSizeMinimum) {1875memoryOption = displayXmoOrXmos(memoryParameters);1876subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);1877goto _subSpaceTooLarge;1878}18791880/* Ensure Xmns <= Xmnx */1881if (opt_XmnxSet && (candidateXmnsValue > extensions->maxNewSpaceSize)) {1882memoryOption = displayXmnOrXmnx(memoryParameters);1883subSpaceTooSmallOption = displayXmsOrInitialRAMPercentage(memoryParameters);1884goto _subSpaceTooSmall;1885}18861887/* Enforce Xms = Xmns + Xmos */1888if ((extensions->oldSpaceSize + candidateXmnsValue) != extensions->initialMemorySize) {1889memoryOption = displayXmoOrXmos(memoryParameters);1890subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);1891goto _subSpaceTooLarge;1892}1893} else {1894if (extensions->oldSpaceSize < (6 * extensions->regionSize)) {1895/*1896* Minimum initial heap size to provide 75/25 split is 8 regions, six for Tenure and two for Nursery.1897* If Tenure Initial size is smaller then six regions it is not large enough to provide 75/25 proportion1898* So set initial Nursery size to minimum (two regions) and use reminder for Tenure1899*/1900candidateXmnsValue = extensions->regionSize * 2;1901} else {1902/* Make Xmns 1/4 of the Xms value, i.e. 1/3 of Xmos. Xms will be reset */1903candidateXmnsValue = MM_Math::roundToFloor(extensions->heapAlignment * 2, extensions->oldSpaceSize / 3);1904candidateXmnsValue = MM_Math::roundToFloor(extensions->regionSize * 2, candidateXmnsValue);1905}19061907/* Ensure Xmos + Xmns < MaxXms */1908if ((extensions->oldSpaceSize + candidateXmnsValue) > maximumXmsValue) {1909candidateXmnsValue = maximumXmsValue - extensions->oldSpaceSize;1910if (candidateXmnsValue < newSpaceSizeMinimum) {1911memoryOption = displayXmoOrXmos(memoryParameters);1912if (maximumXmsValueParameter) {1913subSpaceTooLargeOption = maximumXmsValueParameter;1914goto _subSpaceTooLarge;1915}1916goto _subSpaceTooLargeForHeap;1917}1918}19191920/* Ensure Xmns <= Xmnx */1921if (opt_XmnxSet && (candidateXmnsValue > extensions->maxNewSpaceSize)) {1922candidateXmnsValue = extensions->maxNewSpaceSize;1923}1924}19251926/* Assign Xmns */1927extensions->newSpaceSize = candidateXmnsValue;1928extensions->minNewSpaceSize = candidateXmnsValue;1929break;19301931case XMNS:1932/* Previously verified1933* 1/ Xmns <= Xms|Xmdx|Xmx1934* 2/ Xmns <= Xmnx, if Xmnx specified1935*1936* If Xms is set, then Xmos = Xms - Xmns, else use the previously calculated Xmos value1937* Verify calculated value is not too small or too large.1938*1939* The same algorithm applies to the XMOS case1940*/1941assume0(extensions->newSpaceSize = extensions->minNewSpaceSize);1942if(opt_XmsSet) {1943/* Live with user input */1944candidateXmosValue = extensions->initialMemorySize - extensions->newSpaceSize;19451946/* Verify not too small */1947if (candidateXmosValue < oldSpaceSizeMinimum) {1948memoryOption = displayXmnOrXmns(memoryParameters);1949subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);1950goto _subSpaceTooLarge;1951}19521953/* Ensure Xmos <= Xmox */1954if (opt_XmoxSet && (candidateXmosValue > extensions->maxOldSpaceSize)) {1955memoryOption = displayXmoOrXmox(memoryParameters);1956subSpaceTooSmallOption = displayXmsOrInitialRAMPercentage(memoryParameters);1957goto _subSpaceTooSmall;1958}19591960/* Enforce Xms = Xmns + Xmos */1961if ((candidateXmosValue + extensions->newSpaceSize) != extensions->initialMemorySize) {1962memoryOption = displayXmnOrXmns(memoryParameters);1963subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);1964goto _subSpaceTooLarge;1965}1966} else {1967/* Keep the default value. Xms will be reset */1968candidateXmosValue = extensions->oldSpaceSize;19691970/* Ensure Xmos + Xmns < MaxXms */1971if ((candidateXmosValue + extensions->newSpaceSize) > maximumXmsValue) {1972candidateXmosValue = maximumXmsValue - extensions->newSpaceSize;1973if (candidateXmosValue < oldSpaceSizeMinimum) {1974memoryOption = displayXmnOrXmns(memoryParameters);1975if (maximumXmsValueParameter) {1976subSpaceTooLargeOption = maximumXmsValueParameter;1977goto _subSpaceTooLarge;1978}1979goto _subSpaceTooLargeForHeap;1980}1981}19821983/* Ensure Xmos <= Xmox */1984if (opt_XmoxSet && (candidateXmosValue > extensions->maxOldSpaceSize)) {1985candidateXmosValue = extensions->maxOldSpaceSize;1986}1987}19881989/* Assign Xmos */1990extensions->oldSpaceSize = candidateXmosValue;1991extensions->minOldSpaceSize = candidateXmosValue;1992break;19931994case NONE:1995/* Know that Xms <= Xmdx <= Xmx1996* If Xms is set, split the space 75/25 between Xmos and Xmns1997* If Xms not set, try calculated values1998* Honour Xmox and Xmnx1999*/2000if (opt_XmsSet) {2001if (extensions->initialMemorySize < (8 * extensions->regionSize)) {2002/*2003* Minimum initial size to provide 75/25 split is 8 regions:2004* (minimum Nursery size is 2 regions and it is 25%)2005* If Initial size is smaller then 8 regions it is not large enough to provide 75/25 proportion2006* So set initial Nursery size to minimum (two regions)2007*/2008candidateXmnsValue = extensions->regionSize * 2;2009} else {2010/* Split the available space 75/25 */2011candidateXmnsValue = MM_Math::roundToFloor(extensions->heapAlignment * 2, extensions->initialMemorySize * 1 / 4);2012candidateXmnsValue = MM_Math::roundToFloor(extensions->regionSize * 2, candidateXmnsValue);2013}2014/* Reminder goes to Tenure */2015candidateXmosValue = extensions->initialMemorySize - candidateXmnsValue;2016} else {2017candidateXmnsValue = extensions->newSpaceSize;2018candidateXmosValue = extensions->oldSpaceSize;2019}20202021/* Enforce Xmox */2022if (opt_XmoxSet && (candidateXmosValue > extensions->maxOldSpaceSize)) {2023candidateXmosValue = extensions->maxOldSpaceSize;2024if (opt_XmsSet) {2025candidateXmnsValue = extensions->initialMemorySize - candidateXmosValue;2026}2027}20282029/* Enforce Xmnx */2030if (opt_XmnxSet && (candidateXmnsValue > extensions->maxNewSpaceSize)) {2031candidateXmnsValue = extensions->maxNewSpaceSize;20322033/* Since Xmnx just restricted Xmns, the Xmos value must be adjusted.2034* It is possible that Xmos will be adjusted above Xmox. This would mean that Xms > Xmox + Xmnx.2035* Only adjust Xmos if Xmox is not set, or Xmos will be less than Xmox.2036* Otherwise report the error in the check below.2037*2038* This check is also order dependant with the "Enforce Xmox" if block above.2039*/2040if ((opt_XmsSet)2041&& (!opt_XmoxSet2042|| ((extensions->initialMemorySize - candidateXmnsValue) <= extensions->maxOldSpaceSize)))2043{2044/* If Xmox is not set it will be the maximum size of the heap. This means that the new Xmos value2045* could not possibly exceed the Xmox value, and there is no need to adjust the Xmox value.2046*/2047candidateXmosValue = extensions->initialMemorySize - candidateXmnsValue;2048}2049}20502051/* Xmns and Xmos are now set, honouring Xmnx and Xmox.2052* Enforce Xms = Xmos + Xmns2053*/2054if (opt_XmsSet) {2055if ((candidateXmosValue + candidateXmnsValue) != extensions->initialMemorySize) {2056/* The user specified values for Xmox/Xmnx and Xms prevent us from2057* enforcing Xmos + Xmns = Xms2058*/2059memoryOption = "-Xmox";2060memoryOption2 = "-Xmnx";2061subSpaceTooSmallOption = displayXmsOrInitialRAMPercentage(memoryParameters);2062goto _subSpaceCombinationTooSmall;2063}2064} else {2065/* Know maximumXmsValue is at least minimum configuration size. Give maximum2066* space to Xmos2067*/2068if ((candidateXmosValue + candidateXmnsValue) > maximumXmsValue) {2069candidateXmnsValue = OMR_MAX(newSpaceSizeMinimum, maximumXmsValue - candidateXmosValue);2070candidateXmosValue = maximumXmsValue - candidateXmnsValue;20712072/* Verify not too large */2073if (opt_XmoxSet && (candidateXmosValue > extensions->maxOldSpaceSize)) {2074UDATA delta = extensions->maxOldSpaceSize - candidateXmosValue;2075candidateXmosValue -= delta;2076candidateXmnsValue += delta;2077}20782079if (opt_XmnxSet && (candidateXmnsValue > extensions->maxNewSpaceSize)) {2080/* The user specified values for Xmox/Xmnx prevent us from succeeding */2081memoryOption = "-Xmox";2082memoryOption2 = "-Xmnx";2083if (maximumXmsValueParameter) {2084subSpaceTooLargeOption = maximumXmsValueParameter;2085goto _subSpaceCombinationTooLarge;2086}2087goto _subSpaceCombinationTooLargeForHeap;2088}2089}2090}20912092/* Assign Xmos and Xmns values */2093extensions->oldSpaceSize = candidateXmosValue;2094extensions->minOldSpaceSize = candidateXmosValue;2095extensions->newSpaceSize = candidateXmnsValue;2096extensions->minNewSpaceSize = candidateXmnsValue;2097break;20982099default:2100j9tty_printf(PORTLIB, "Internal GC error %p\n", setMemoryParameters); /* No NLS */2101assume0(0); /* should never get here */2102return JNI_ERR;2103break;2104}21052106/* The Xmos + Xmns value */2107combinedXmosXmnsSize = extensions->oldSpaceSize + extensions->newSpaceSize;21082109/* Reset Xmdx if applicable */2110if (extensions->maxSizeDefaultMemorySpace < combinedXmosXmnsSize) {2111if (!opt_XmdxSet) {2112extensions->maxSizeDefaultMemorySpace = combinedXmosXmnsSize;2113} else {2114assume0(0); /* Previous stage checked Xmdx > minConfiguration */2115memoryOption = "-Xmdx";2116minimumSizeValue = extensions->absoluteMinimumOldSubSpaceSize + (2*extensions->absoluteMinimumNewSubSpaceSize); /* smallest configuration */2117goto _subSpaceTooSmallForValue;2118}2119}21202121/* Reset Xms if applicable */2122if (extensions->initialMemorySize != combinedXmosXmnsSize) {2123if (!opt_XmsSet) {2124extensions->initialMemorySize = combinedXmosXmnsSize;2125} else {2126assume0(0); /* Previous stage checked Xms > minConfiguration */2127memoryOption = displayXmsOrInitialRAMPercentage(memoryParameters);2128minimumSizeValue = extensions->absoluteMinimumOldSubSpaceSize + (2*extensions->absoluteMinimumNewSubSpaceSize); /* smallest configuration */2129goto _subSpaceTooSmallForValue;2130}2131}21322133/* Reset Xmox if applicable */2134if (!opt_XmoxSet) {2135/* We know initial Nursery size now so adjust maximum Tenure size */2136extensions->maxOldSpaceSize = extensions->memoryMax - extensions->newSpaceSize;2137if (extensions->oldSpaceSize > extensions->maxOldSpaceSize) {2138extensions->maxOldSpaceSize = extensions->oldSpaceSize;2139}2140}21412142/* Reset Xmnx if applicable */2143if (extensions->newSpaceSize > extensions->maxNewSpaceSize) {2144if (!opt_XmnxSet) {2145extensions->maxNewSpaceSize = extensions->newSpaceSize;2146} else {2147/* Should have already been verified */2148assume0(0);2149}2150}21512152/* Reset minimum values if necessary */2153if (extensions->minOldSpaceSize > extensions->oldSpaceSize) {2154extensions->minOldSpaceSize = extensions->oldSpaceSize;2155}21562157if (extensions->minNewSpaceSize > extensions->newSpaceSize) {2158extensions->minNewSpaceSize = extensions->newSpaceSize;2159}21602161/* Verify Xmox + Xmnx combination */2162if (opt_XmoxSet && opt_XmnxSet) {2163if ((extensions->maxOldSpaceSize + extensions->maxNewSpaceSize) > extensions->maxSizeDefaultMemorySpace) {2164memoryOption = displayXmoOrXmox(memoryParameters);2165memoryOption2 = displayXmnOrXmnx(memoryParameters);2166if (opt_XmdxSet) {2167subSpaceTooLargeOption = "-Xmdx";2168goto _subSpaceCombinationTooLarge;2169}2170if (opt_XmxSet) {2171subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);2172goto _subSpaceCombinationTooLarge;2173}2174goto _subSpaceCombinationTooLargeForHeap;2175}2176}2177} /* of Non flat configurations */21782179/* Verify that -Xminf is at least 0.05 less than -Xmaxf */2180if (extensions->heapFreeMinimumRatioMultiplier + 5 > extensions->heapFreeMaximumRatioMultiplier) {2181memoryOption = "-Xminf";2182minValue = (float)extensions->heapFreeMinimumRatioMultiplier / 100;2183memoryOption2 = "-Xmaxf";2184maxValue = (float)extensions->heapFreeMaximumRatioMultiplier / 100;2185memoryOptionMinimumDifference = "0.05";2186goto _subSpaceCombinationTooClose;2187}21882189#if defined(J9VM_GC_TILTED_NEW_SPACE)2190/* Verify that -Xgc:scvTiltRatioMin is no larger than -Xgc:scvTiltRatioMax */2191/* NOTE: (stored min) == (100 - specified max) */2192if (extensions->survivorSpaceMinimumSizeRatio > extensions->survivorSpaceMaximumSizeRatio) {2193memoryOption = "scvTiltRatioMin=";2194memoryOption2 = "scvTiltRatioMax=";2195goto _combinationLargerThan;2196}2197#endif /* J9VM_GC_TILTED_NEW_SPACE */21982199#if defined(J9VM_GC_LARGE_OBJECT_AREA)2200/* Verify that -Xloainitial is not less than -Xloaminimum */2201if (extensions->largeObjectAreaInitialRatio < extensions->largeObjectAreaMinimumRatio) {2202memoryOption = "-Xloainitial";2203subSpaceTooSmallOption = "-Xloaminimum";2204goto _subSpaceTooSmall;2205}22062207/* Verify that -Xloainitial is less than -Xloamaximum */2208if (extensions->largeObjectAreaInitialRatio > extensions->largeObjectAreaMaximumRatio) {2209memoryOption = "-Xloamaximum";2210subSpaceTooSmallOption = "-Xloainitial";2211goto _subSpaceTooSmall;2212}2213#endif /* J9VM_GC_LARGE_OBJECT_AREA */22142215#if defined(J9VM_GC_GENERATIONAL)2216/* if the user asked for split heaps, apply our additional constraints here */2217if (extensions->enableSplitHeap) {2218if (opt_XmoxSet) {2219if (!opt_XmnxSet) {2220/* strong-arm the Xmnx to fit against this Xmox */2221extensions->maxNewSpaceSize = extensions->memoryMax - extensions->maxOldSpaceSize;2222}2223} else {2224if (opt_XmnxSet) {2225/* strong-arm the Xmox to fit against this Xmnx */2226extensions->maxOldSpaceSize = extensions->memoryMax - extensions->maxNewSpaceSize;2227} else {2228/* neither were set so just correct the old space size since it will be set too big for us to use correctly */2229extensions->maxOldSpaceSize = extensions->memoryMax - extensions->maxNewSpaceSize;2230}2231}2232/* Force the immediate expansion to maximum memory */2233extensions->initialMemorySize = extensions->memoryMax;2234/* Force all the new space sizes to be "locked-in" */2235extensions->minNewSpaceSize = extensions->maxNewSpaceSize;2236extensions->newSpaceSize = extensions->maxNewSpaceSize;2237/* Force all the old space sizes to be "locked-in" */2238extensions->minOldSpaceSize = extensions->maxOldSpaceSize;2239extensions->oldSpaceSize = extensions->maxOldSpaceSize;22402241UDATA total = extensions->maxNewSpaceSize + extensions->maxOldSpaceSize;2242if (extensions->memoryMax > total) {2243goto _subSpaceCombinationTooSmall;2244} else if (extensions->memoryMax < total) {2245goto _subSpaceCombinationTooLarge;2246}2247}2248#endif /* defined(J9VM_GC_GENERATIONAL) */22492250#if defined (J9VM_GC_VLHGC)2251{2252/* calculate our eden size boundaries based on -Xmn inputs */2253UDATA mx = extensions->memoryMax;2254UDATA ms = extensions->initialMemorySize;2255/* first, the error checking */2256if (!isLessThanEqualOrUnspecifiedAgainstFixed(&extensions->userSpecifiedParameters._Xmn, mx)) {2257memoryOption = "-Xmn";2258subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);2259goto _subSpaceTooLarge;2260}2261if (!isLessThanEqualOrUnspecifiedAgainstFixed(&extensions->userSpecifiedParameters._Xmns, mx)) {2262memoryOption = "-Xmns";2263subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);2264goto _subSpaceTooLarge;2265}2266if (!isLessThanEqualOrUnspecifiedAgainstFixed(&extensions->userSpecifiedParameters._Xmnx, mx)) {2267memoryOption = "-Xmnx";2268subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);2269goto _subSpaceTooLarge;2270}2271if (!isLessThanEqualOrUnspecifiedAgainstOption(&extensions->userSpecifiedParameters._Xmns, &extensions->userSpecifiedParameters._Xmnx)) {2272memoryOption = "-Xmnx";2273subSpaceTooLargeOption = "-Xmns";2274goto _subSpaceTooLarge;2275}2276if (!isLessThanEqualOrUnspecifiedAgainstFixed(&extensions->userSpecifiedParameters._Xmns, ms)) {2277if (!opt_XmsSet) {2278ms = extensions->userSpecifiedParameters._Xmns._valueSpecified;2279extensions->initialMemorySize = ms;2280extensions->oldSpaceSize = extensions->initialMemorySize;2281} else {2282memoryOption = "-Xmn";2283subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);2284goto _subSpaceTooLarge;2285}2286}2287/* now interpret the values */2288UDATA idealEdenMin = 0;2289UDATA idealEdenMax = 0;2290/*----------------------------------------------------------------2291Arguments specified | initial Eden | maxEden2292----------------------------------------------------------------2293XmnA | OMR_MIN(A,ms) | A2294XmnsB | B | B2295XmnxC | OMR_MIN(C,ms) | C2296XmnsB XmnxC | B | C2297(none) | OMR_MIN(mx/4,ms) | mx*3/42298----------------------------------------------------------------*/2299if (extensions->userSpecifiedParameters._Xmn._wasSpecified) {2300/* earlier error checking would have ensured that we didn't specify -Xmns or -Xmnx with -Xmn */2301UDATA mn = extensions->userSpecifiedParameters._Xmn._valueSpecified;2302idealEdenMin = OMR_MIN(mn, ms);2303idealEdenMax = mn;2304} else if (extensions->userSpecifiedParameters._Xmns._wasSpecified) {2305UDATA mns = extensions->userSpecifiedParameters._Xmns._valueSpecified;2306if (extensions->userSpecifiedParameters._Xmnx._wasSpecified) {2307UDATA mnx = extensions->userSpecifiedParameters._Xmnx._valueSpecified;2308idealEdenMin = mns;2309idealEdenMax = mnx;2310} else {2311idealEdenMin = mns;2312idealEdenMax = mns;2313}2314} else if (extensions->userSpecifiedParameters._Xmnx._wasSpecified) {2315UDATA mnx = extensions->userSpecifiedParameters._Xmnx._valueSpecified;2316idealEdenMin = OMR_MIN(mnx, ms);2317idealEdenMax = mnx;2318} else {2319UDATA quarterMax = mx/4;2320UDATA threeQuarterMax = quarterMax * 3;23212322idealEdenMin = OMR_MIN(quarterMax, ms);2323idealEdenMax = threeQuarterMax;2324}23252326/* eden size has to be aligned with region size */2327idealEdenMin = MM_Math::roundToFloor(extensions->regionSize, idealEdenMin);2328idealEdenMax = MM_Math::roundToFloor(extensions->regionSize, idealEdenMax);23292330/* eden size can not be smaller than 2 * region size23311, during initialization for first collection, it needs 2 regions23322, if eden size is smaller than 2 times of region size, it would cause wrong calculating taxationThreshold for GMP and PGC(the PGC after GMP) */2333UDATA minSizeForMinEden = extensions->regionSize * 2;2334if (minSizeForMinEden > idealEdenMin) {2335idealEdenMin = minSizeForMinEden;2336}23372338UDATA numaNodes = extensions->_numaManager.getAffinityLeaderCount() + 1;23392340/* minimum 2 regions for each numa node */2341UDATA minSizeForMaxEden = extensions->regionSize * 2 * numaNodes;2342if (minSizeForMaxEden > idealEdenMax) {2343idealEdenMax = minSizeForMaxEden;2344}23452346/* since our current implementation of Eden sizing only uses these values for end-points in our sizing interpolation, they don't need to be rounded */2347extensions->tarokIdealEdenMinimumBytes = idealEdenMin;2348extensions->tarokIdealEdenMaximumBytes = idealEdenMax;2349}2350#endif /* J9VM_GC_VLHGC */23512352if (opt_XmcrsSet) {2353/* Silently handle a size mismatch; don't report an error about undocumented options2354* if the user has specified the official one. */2355if (extensions->suballocatorCommitSize > extensions->suballocatorInitialSize) {2356extensions->suballocatorCommitSize = extensions->suballocatorInitialSize;2357}2358} else {2359if (extensions->suballocatorCommitSize > extensions->suballocatorInitialSize) {2360memoryOption = "-Xgc:suballocatorCommitSize=";2361memoryOption2 = "-Xgc:suballocatorInitialSize=";2362goto _combinationLargerThan;2363}2364}23652366/* verify -Xsoftmx is set between -Xms and -Xmx */2367if (opt_XsoftmxSet) {2368if (extensions->softMx > extensions->memoryMax) {2369memoryOption = "-Xsoftmx";2370goto _subSpaceTooLargeForHeap;2371}23722373if (extensions->softMx < extensions->initialMemorySize) {2374memoryOption = "-Xsoftmx";2375minimumSizeValue = extensions->initialMemorySize;2376goto _subSpaceTooSmallForValue;2377}2378}23792380return JNI_OK;23812382_subSpaceCombinationTooLarge:2383j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE, memoryOption, memoryOption2, subSpaceTooLargeOption);2384return JNI_ERR;23852386_subSpaceCombinationTooLargeForHeap:2387j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE_FOR_HEAP, memoryOption, memoryOption2);2388return JNI_ERR;23892390_subSpaceCombinationNotEqual:2391j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_NOT_EQUAL, memoryOption, memoryOption2, subSpaceTooLargeOption);2392return JNI_ERR;23932394_subSpaceCombinationTooSmall:2395j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_SMALL, memoryOption, memoryOption2, subSpaceTooSmallOption);2396return JNI_ERR;23972398_subSpaceNotEqualError:2399j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_NOT_EQUAL_ERROR, memoryOption, memoryOption2);2400return JNI_ERR;24012402_subSpaceTooSmallForValue:2403{2404const char *qualifier = NULL;2405qualifiedSize(&minimumSizeValue, &qualifier);2406j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_SMALL_FOR_VALUE, memoryOption, minimumSizeValue, qualifier);2407return JNI_ERR;2408}24092410_subSpaceTooSmall:2411j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_SMALL, memoryOption, subSpaceTooSmallOption);2412return JNI_ERR;24132414_subSpaceTooLarge:2415j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE, memoryOption, subSpaceTooLargeOption);2416return JNI_ERR;24172418_subSpaceTooLargeForHeap:2419j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE_FOR_HEAP, memoryOption);2420return JNI_ERR;24212422_subSpaceCombinationTooClose:2423j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_OPTION_MINIMUM_DIFFERENCE, memoryOption, minValue, memoryOptionMinimumDifference, memoryOption2, maxValue);2424return JNI_ERR;24252426_combinationLargerThan:2427j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_OPTIONS_MUST_BE_NO_GREATER_THAN, memoryOption, memoryOption2);2428return JNI_ERR;2429}24302431/**2432* Recalculate Xms, Xmn, Xmo values based on user input.2433* @param memoryParameters array of parameter values2434* @param flatConfiguration with or without New memory space2435* @return JNI_OK if OK2436*/2437jint2438gcCalculateMemoryParameters(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)2439{2440MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);2441jint result;24422443/* Handle any configuration specific details. For example in the flat configuration2444* the -Xmns/-Xmnx values have no meaning2445*/2446result = setConfigurationSpecificMemoryParameters(javaVM, memoryParameters, flatConfiguration);2447if (JNI_OK != result) {2448return result;2449}24502451/* Verify all memory parameters provided by the user are larger than the minimum size2452* and smaller than the value of Xmx. Only verify individual parameters, not combinations2453*/2454result = independentMemoryParameterVerification(javaVM, memoryParameters, flatConfiguration);2455if (JNI_OK != result) {2456return result;2457}24582459/* Verify the combinations of memory parameters are valid. For example ensure that2460* Xms >= Xmns + Xmos for non flat configurations.2461*/2462result = combinationMemoryParameterVerification(javaVM, memoryParameters, flatConfiguration);2463if (JNI_OK != result) {2464return result;2465}24662467assume0(extensions->minOldSpaceSize >= OMR_MAX(extensions->absoluteMinimumOldSubSpaceSize, extensions->heapAlignment));2468#if defined(DEBUG)2469if (!flatConfiguration) {2470assume0(extensions->minNewSpaceSize >= 2*OMR_MAX(extensions->absoluteMinimumNewSubSpaceSize, extensions->heapAlignment));2471}2472#endif /* DEBUG */24732474assume0(extensions->oldSpaceSize >= extensions->minOldSpaceSize);2475assume0(extensions->oldSpaceSize <= extensions->maxOldSpaceSize);24762477#if defined(DEBUG)2478if (!flatConfiguration) {2479assume0(extensions->newSpaceSize >= extensions->minNewSpaceSize);2480assume0(extensions->newSpaceSize <= extensions->maxNewSpaceSize);2481}2482#endif /* DEBUG */24832484assume0(extensions->initialMemorySize = (extensions->oldSpaceSize + extensions->newSpaceSize));2485assume0(extensions->initialMemorySize <= extensions->maxSizeDefaultMemorySpace);24862487assume0(extensions->maxSizeDefaultMemorySpace <= extensions->memoryMax);2488assume0(extensions->maxSizeDefaultMemorySpace >= extensions->maxOldSpaceSize);2489assume0(extensions->maxSizeDefaultMemorySpace >= extensions->maxNewSpaceSize);24902491/* initialize the dynamicMaxSoftReferenceAge to the maxSoftReferenceAge since the first GC starts with reference age at its maximum */2492extensions->dynamicMaxSoftReferenceAge = extensions->maxSoftReferenceAge;24932494return result;2495}24962497/**2498* Ensure all values are correct.2499* Values input by the user can not be changed, values that have been calculated2500* may be updated if required.2501* @param memoryParameters array of parameter values2502* @param flatConfiguration with or without New memory space2503* @return JNI_OK if OK2504*/2505jint2506gcInitializeVerification(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)2507{2508#if defined(J9VM_GC_THREAD_LOCAL_HEAP) || defined(J9VM_GC_MODRON_SCAVENGER)2509MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);2510#endif /* J9VM_GC_THREAD_LOCAL_HEAP || J9VM_GC_MODRON_SCAVENGER */2511jint result;25122513#if defined(J9VM_GC_THREAD_LOCAL_HEAP)2514/* Make sure TLH sizes are appropriately rounded */2515extensions->tlhMinimumSize = MM_Math::roundToSizeofUDATA(extensions->tlhMinimumSize);2516extensions->tlhIncrementSize = MM_Math::roundToSizeofUDATA(extensions->tlhIncrementSize);2517extensions->tlhInitialSize = MM_Math::roundToCeiling(extensions->tlhIncrementSize, extensions->tlhInitialSize);2518extensions->tlhMaximumSize = MM_Math::roundToCeiling(extensions->tlhIncrementSize, extensions->tlhMaximumSize);2519extensions->tlhSurvivorDiscardThreshold = MM_Math::roundToSizeofUDATA(extensions->tlhSurvivorDiscardThreshold);2520extensions->tlhTenureDiscardThreshold = MM_Math::roundToSizeofUDATA(extensions->tlhTenureDiscardThreshold);2521#endif /* J9VM_GC_THREAD_LOCAL_HEAP */25222523#if defined(J9VM_GC_MODRON_SCAVENGER)2524if (extensions->scavengerScanCacheMaximumSize < extensions->scavengerScanCacheMinimumSize) {2525PORT_ACCESS_FROM_JAVAVM(javaVM);2526j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_OPTIONS_MUST_BE_NO_GREATER_THAN, "-XXgc:scanCacheMinimumSize", "-XXgc:scanCacheMaximumSize");2527return JNI_ERR;2528}2529/* make sure scavengerScanCacheMinimumSize and scavengerScanCacheMaximumSize are properly aligned */2530extensions->scavengerScanCacheMaximumSize = MM_Math::roundToCeiling(extensions->tlhMinimumSize, extensions->scavengerScanCacheMaximumSize);2531extensions->scavengerScanCacheMinimumSize = MM_Math::roundToCeiling(extensions->tlhMinimumSize, extensions->scavengerScanCacheMinimumSize);2532#endif /* J9VM_GC_MODRON_SCAVENGER */25332534/* Recalculate memory parameters based on user input (Xms, Xmo, Xmn) */2535result = gcCalculateMemoryParameters(javaVM, memoryParameters, flatConfiguration);2536if (JNI_OK != result) {2537return result;2538}25392540return JNI_OK;2541}25422543/**2544* If appropriate, lower the Xmx value before re-attempting to allocate basic heap structures.2545* Called after we have failed to allocate basic heap structures, this function2546* may resize the Xmx value so we can try again with a smaller Xmx value.2547*2548* @param memoryParameterTable the table containing user-specified memory parameters2549* @param memoryMinimum the minimum allowable Xmx value2550*2551* @note This function assumes that all memory parameters have been verified, and2552* will be re-verified based on the new Xmx value2553*2554* @return true - if the Xmx value was resized, and we should try again2555* @return false - otherwise2556*/2557bool2558reduceXmxValueForHeapInitialization(J9JavaVM *javaVM, IDATA *memoryParameterTable, UDATA memoryMinimum)2559{2560MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);2561bool optXmxSet = (-1 != memoryParameterTable[opt_Xmx]);2562bool optXmdxSet = (-1 != memoryParameterTable[opt_Xmdx]);25632564if (optXmxSet) {2565/* -Xmx was set by the user, so just fail */2566return false;2567} else if (extensions->memoryMax <= memoryMinimum) {2568/* We can't reduce the Xmx value any more -- fail */2569return false;2570}25712572extensions->memoryMax = (extensions->memoryMax / DEFAULT_XMX_REDUCTION_DENOMINATOR) * DEFAULT_XMX_REDUCTION_NUMERATOR;2573extensions->memoryMax = MM_Math::roundToFloor(extensions->heapAlignment, extensions->memoryMax);2574extensions->memoryMax = MM_Math::roundToFloor(extensions->regionSize, extensions->memoryMax);25752576/* Don't shrink below the minimum value */2577if (extensions->memoryMax < memoryMinimum) {2578extensions->memoryMax = memoryMinimum;2579}25802581/* If Xmdx is now > Xmx, and the Xmdx value was not set by the user, change Xmdx also */2582if ((!optXmdxSet) && (extensions->memoryMax < extensions->maxSizeDefaultMemorySpace)) {2583extensions->maxSizeDefaultMemorySpace = extensions->memoryMax;2584}25852586return true;2587}25882589/**2590* If the requested page size does not match the actual page size, and the2591* user specified -Xlp:objectheap:warn, output a warning message.2592*2593* @param extensions the instance of GCExtensions2594* @param loadInfo The loadInfo object to store the error message2595*/2596void2597warnIfPageSizeNotSatisfied(J9JavaVM* vm, MM_GCExtensions *extensions) {2598PORT_ACCESS_FROM_JAVAVM(vm);25992600if(extensions == NULL || extensions->heap == NULL) {2601return;2602}26032604if((extensions->heap->getPageSize() != extensions->requestedPageSize) && extensions->largePageWarnOnError) {2605/* Obtain the qualified sizes (e.g. 2k) */2606UDATA requestedSize = extensions->requestedPageSize;2607const char* requestedSizeQualifier = NULL;2608qualifiedSize(&requestedSize, &requestedSizeQualifier);26092610UDATA actualSize = extensions->heap->getPageSize();2611const char* actualSizeQualifier = NULL;2612qualifiedSize(&actualSize, &actualSizeQualifier);26132614j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_XLP_PAGE_NOT_AVAILABLE_WARN, requestedSize, requestedSizeQualifier, actualSize, actualSizeQualifier);2615}2616}26172618/**2619* Set default configuration options for SE2620* @param extensions GCExtensions2621* @param scavenge value to set extensions->scavengerEnabled except it is already forced2622* @param concurrentMark value to set extensions->concurrentMark except it is already forced2623* @param concurrentSweep value to set extensions->concurrentSweep except it is already forced2624* @param largeObjectArea value to set extensions->largeObjectArea except it is already forced2625*/2626void2627setDefaultConfigOptions(MM_GCExtensions *extensions, bool scavenge, bool concurrentMark, bool concurrentSweep, bool largeObjectArea)2628{2629#if defined(J9VM_GC_MODRON_SCAVENGER)2630if(!extensions->configurationOptions._forceOptionScavenge) {2631extensions->scavengerEnabled = scavenge;2632}2633#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */2634#if defined (OMR_GC_MODRON_CONCURRENT_MARK)2635if(!extensions->configurationOptions._forceOptionConcurrentMark) {2636extensions->concurrentMark = concurrentMark;2637}2638#endif /* defined (OMR_GC_MODRON_CONCURRENT_MARK) */2639#if defined(J9VM_GC_CONCURRENT_SWEEP)2640if(!extensions->configurationOptions._forceOptionConcurrentSweep) {2641extensions->concurrentSweep = concurrentSweep;2642}2643#endif /* defined(J9VM_GC_CONCURRENT_SWEEP) */2644#if defined(J9VM_GC_LARGE_OBJECT_AREA)2645if(!extensions->configurationOptions._forceOptionLargeObjectArea) {2646extensions->largeObjectArea = largeObjectArea;2647}2648#endif /* defined(J9VM_GC_LARGE_OBJECT_AREA) */2649}26502651void2652setConfigOptionsForNoGc(MM_GCExtensions *extensions)2653{2654/* noScavenger noConcurrentMark noConcurrentSweep, noLOA */2655#if defined(J9VM_GC_MODRON_SCAVENGER)2656extensions->configurationOptions._forceOptionScavenge = true;2657extensions->scavengerEnabled = false;2658#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */2659#if defined (OMR_GC_MODRON_CONCURRENT_MARK)2660extensions->configurationOptions._forceOptionConcurrentMark = true;2661extensions->concurrentMark = false;2662#endif /* defined (OMR_GC_MODRON_CONCURRENT_MARK) */2663#if defined(J9VM_GC_CONCURRENT_SWEEP)2664extensions->configurationOptions._forceOptionConcurrentSweep = true;2665extensions->concurrentSweep = false;2666#endif /* defined(J9VM_GC_CONCURRENT_SWEEP) */2667#if defined(J9VM_GC_LARGE_OBJECT_AREA)2668extensions->configurationOptions._forceOptionLargeObjectArea = true;2669extensions->largeObjectArea = false;2670#endif /* defined(J9VM_GC_LARGE_OBJECT_AREA) */2671/* 1 gcThread */2672extensions->gcThreadCountForced = true;2673extensions->gcThreadCount = 1;26742675extensions->splitFreeListSplitAmount = 1;2676extensions->objectListFragmentCount = 1;26772678/* disable excessiveGC */2679extensions->excessiveGCEnabled._wasSpecified = true;2680extensions->excessiveGCEnabled._valueSpecified = false;2681/* disable estimate fragmentation */2682extensions->estimateFragmentation = 0;2683extensions->processLargeAllocateStats = false;2684/* disable system gc */2685extensions->disableExplicitGC = true;2686}26872688/**2689* Create proper configuration for SE based on options2690* @param env pointer to Environment2691* @return pointer to created configuration or NULL if failed2692*/2693MM_Configuration *2694configurateGCWithPolicyAndOptionsStandard(MM_EnvironmentBase *env)2695{2696MM_Configuration *result = NULL;2697MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(env->getOmrVM());26982699#if defined(J9VM_GC_MODRON_SCAVENGER)2700if (extensions->scavengerEnabled) {2701#if defined(J9VM_GC_CONCURRENT_SWEEP)2702/* Scavenger does not support concurrent sweep */2703if (!extensions->concurrentSweep) {2704#endif /* defined(J9VM_GC_CONCURRENT_SWEEP) */27052706/*2707* Set region size based on section size of Concurrent Scavenger Page2708* - get an estimation of maximum Nursery size based at -Xmn, -Xmnx, -Xmns or -Xmx / 42709* (this is fast check without full parameters analysis for Concurrent Scavenger prototype, it is recommended to provide -Xmn explicitly)2710* - select Concurrent Scavenger Page size based at estimated Nursery size: if should be rounded up to next power of 2 but not smaller then 32M2711* - select region size as a Concurrent Scavenger Page Section size2712*/2713if (extensions->isConcurrentScavengerHWSupported()) {2714OMRPORT_ACCESS_FROM_ENVIRONMENT(env);2715/* Default maximum Nursery size estimation in case of none of -Xmn* options is specified */2716uintptr_t nurserySize = extensions->memoryMax / 4;27172718/*2719* correctness of -Xmn* values will be analyzed later on with initialization error in case of bad combination2720* so assume here all of them are correct, just check none of them is larger then entire heap size2721*/2722if (extensions->userSpecifiedParameters._Xmn._wasSpecified) {2723/* maximum Nursery size was set in -Xmn */2724if (extensions->userSpecifiedParameters._Xmn._valueSpecified < extensions->memoryMax) {2725nurserySize = extensions->userSpecifiedParameters._Xmn._valueSpecified;2726}2727} else if (extensions->userSpecifiedParameters._Xmnx._wasSpecified) {2728/* maximum Nursery size was set in -Xmnx */2729if (extensions->userSpecifiedParameters._Xmnx._valueSpecified < extensions->memoryMax) {2730nurserySize = extensions->userSpecifiedParameters._Xmnx._valueSpecified;2731}2732} else if (extensions->userSpecifiedParameters._Xmns._wasSpecified) {2733/* maximum Nursery size was set in -Xmns, it is related in case if it is larger then default maximum Nursery size */2734if (extensions->userSpecifiedParameters._Xmns._valueSpecified < extensions->memoryMax) {2735if (extensions->userSpecifiedParameters._Xmns._valueSpecified > nurserySize) {2736nurserySize = extensions->userSpecifiedParameters._Xmns._valueSpecified;2737}2738}2739}27402741/* Calculate Concurrent Scavenger Page parameters based at maximum Nursery size estimation */2742extensions->calculateConcurrentScavengerPageParameters(nurserySize);27432744if (extensions->isDebugConcurrentScavengerPageAlignment()) {2745omrtty_printf("Nursery size early projection 0x%zx, Concurrent Scavenger Page size 0x%zx, Section size for heap alignment 0x%zx\n",2746nurserySize, extensions->getConcurrentScavengerPageSectionSize() * CONCURRENT_SCAVENGER_PAGE_SECTIONS, extensions->getConcurrentScavengerPageSectionSize());2747}2748}27492750result = MM_ConfigurationGenerational::newInstance(env);27512752#if defined(J9VM_GC_CONCURRENT_SWEEP)2753}2754#endif /* defined(J9VM_GC_CONCURRENT_SWEEP) */2755} else2756#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */2757{2758result = MM_ConfigurationFlat::newInstance(env);2759}27602761return result;2762}27632764/**2765* Create configuration based on GC policy2766* @param vm pointer to JavaVM2767* @return pointer to created configuration or NULL if failed2768*/2769MM_Configuration *2770configurateGCWithPolicyAndOptions(OMR_VM* omrVM)2771{2772MM_Configuration *result = NULL;2773MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVM);2774MM_EnvironmentBase env(omrVM);27752776switch(extensions->configurationOptions._gcPolicy) {2777case gc_policy_optthruput:2778extensions->gcModeString = "-Xgcpolicy:optthruput";2779omrVM->gcPolicy = J9_GC_POLICY_OPTTHRUPUT;2780/* noScavenge, noConcurrentMark, noConcurrentSweep, loa */2781setDefaultConfigOptions(extensions, false, false, false, true);2782result = configurateGCWithPolicyAndOptionsStandard(&env);2783break;27842785case gc_policy_optavgpause:2786extensions->gcModeString = "-Xgcpolicy:optavgpause";2787omrVM->gcPolicy = J9_GC_POLICY_OPTAVGPAUSE;2788/* noScavenge, concurrentMark, concurrentSweep, loa */2789setDefaultConfigOptions(extensions, false, true, true, true);2790result = configurateGCWithPolicyAndOptionsStandard(&env);2791break;27922793case gc_policy_gencon:2794extensions->gcModeString = "-Xgcpolicy:gencon";2795omrVM->gcPolicy = J9_GC_POLICY_GENCON;2796/* scavenge, concurrentMark, noConcurrentSweep, loa */2797setDefaultConfigOptions(extensions, true, true, false, true);2798result = configurateGCWithPolicyAndOptionsStandard(&env);2799break;28002801case gc_policy_metronome:2802extensions->gcModeString = "-Xgcpolicy:metronome";2803omrVM->gcPolicy = J9_GC_POLICY_METRONOME;2804result = MM_ConfigurationRealtime::newInstance(&env);2805break;28062807case gc_policy_balanced:2808extensions->gcModeString = "-Xgcpolicy:balanced";2809omrVM->gcPolicy = J9_GC_POLICY_BALANCED;2810result = MM_ConfigurationIncrementalGenerational::newInstance(&env);2811break;28122813case gc_policy_nogc:2814extensions->gcModeString = "-Xgcpolicy:nogc";2815omrVM->gcPolicy = J9_GC_POLICY_NOGC;2816/* noScavenge, noConcurrentMark, noConcurrentSweep, noLOA */2817setConfigOptionsForNoGc(extensions);2818result = configurateGCWithPolicyAndOptionsStandard(&env);2819break;28202821case gc_policy_undefined:2822default:2823/* Undefined or unknown GC policy */2824Assert_MM_unreachable();2825break;2826}28272828return result;2829}28302831/**2832* Initialize GC parameters.2833* Initialize GC parameters with default values, parse the command line, massage values2834* as required and finally verify values.2835* @return J9VMDLLMAIN_OK or J9VMDLLMAIN_FAILED2836*/2837jint2838gcInitializeDefaults(J9JavaVM* vm)2839{2840J9VMDllLoadInfo *loadInfo = getGCDllLoadInfo(vm);2841UDATA tableSize = (opt_none + 1) * sizeof(IDATA);2842UDATA realtimeSizeClassesAllocationSize = ROUND_TO(sizeof(UDATA), sizeof(J9VMGCSizeClasses));2843IDATA *memoryParameterTable;2844UDATA minimumVMSize;2845bool flatConfiguration = true;2846MM_GCExtensions *extensions;2847MM_EnvironmentBase env(vm->omrVM);2848PORT_ACCESS_FROM_JAVAVM(vm);28492850minimumVMSize = MINIMUM_VM_SIZE;28512852memoryParameterTable = (IDATA *)j9mem_allocate_memory(tableSize, OMRMEM_CATEGORY_MM);2853if (!memoryParameterTable) {2854loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE_OUT_OF_MEMORY, "Failed to initialize, out of memory.");2855goto error;2856}2857memset(memoryParameterTable, -1, tableSize);28582859vm->memoryManagerFunctions = ((J9MemoryManagerFunctions *)GLOBAL_TABLE(MemoryManagerFunctions));28602861// todo: dagar centralize language init2862//gcOmrInitializeDefaults(vm->omrVM);2863extensions = MM_GCExtensions::newInstance(&env);2864if (NULL == extensions) {2865loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE_OUT_OF_MEMORY, "Failed to initialize, out of memory.");2866goto error;2867}2868extensions->setOmrVM(vm->omrVM);2869vm->omrVM->_gcOmrVMExtensions = (void *)extensions;2870vm->gcExtensions = vm->omrVM->_gcOmrVMExtensions;28712872/* enable estimateFragmentation for all GCs as default for java, but not the estimated result would not affect concurrentgc kickoff by default */2873extensions->estimateFragmentation = (GLOBALGC_ESTIMATE_FRAGMENTATION | LOCALGC_ESTIMATE_FRAGMENTATION);2874extensions->processLargeAllocateStats = true;2875extensions->concurrentSlackFragmentationAdjustmentWeight = 0;28762877/* allocate and set the collector language interface to Java */2878extensions->collectorLanguageInterface = MM_CollectorLanguageInterfaceImpl::newInstance(&env);2879if (NULL == extensions->collectorLanguageInterface) {2880goto error;2881}28822883initializeVerboseFunctionTableWithDummies(&extensions->verboseFunctionTable);28842885if (JNI_OK != gcParseCommandLineAndInitializeWithValues(vm, memoryParameterTable)) {2886loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE_PARSING_COMMAND_LINE, "Failed to initialize, parsing command line.");2887goto error;2888}28892890if ((-1 == memoryParameterTable[opt_Xms]) && (-1 != memoryParameterTable[opt_initialRAMPercent])) {2891extensions->initialMemorySize = (uintptr_t)(((double)extensions->usablePhysicalMemory / 100.0) * extensions->initialRAMPercent);2892/* Update memory parameter table to appear that -Xms was specified */2893memoryParameterTable[opt_Xms] = memoryParameterTable[opt_initialRAMPercent];2894}2895if ((-1 == memoryParameterTable[opt_Xmx]) && (-1 != memoryParameterTable[opt_maxRAMPercent])) {2896extensions->memoryMax = (uintptr_t)(((double)extensions->usablePhysicalMemory / 100.0) * extensions->maxRAMPercent);2897/* Update memory parameter table to appear that -Xmx was specified */2898memoryParameterTable[opt_Xmx] = memoryParameterTable[opt_maxRAMPercent];2899}29002901if (gc_policy_metronome == extensions->configurationOptions._gcPolicy) {2902/* Heap is segregated; take into account segregatedAllocationCache. */2903vm->segregatedAllocationCacheSize = (J9VMGC_SIZECLASSES_NUM_SMALL + 1)*sizeof(J9VMGCSegregatedAllocationCacheEntry);29042905vm->realtimeSizeClasses = (J9VMGCSizeClasses *)j9mem_allocate_memory(realtimeSizeClassesAllocationSize, OMRMEM_CATEGORY_VM);2906if (NULL == vm->realtimeSizeClasses) {2907loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE_OUT_OF_MEMORY, "Failed to initialize, out of memory.");2908goto error;2909}2910}2911vm->vmThreadSize = J9_VMTHREAD_SEGREGATED_ALLOCATION_CACHE_OFFSET + vm->segregatedAllocationCacheSize + sizeof(OMR_VMThread);29122913#if defined(OMR_GC_CONCURRENT_SCAVENGER)2914if (gc_policy_gencon == extensions->configurationOptions._gcPolicy) {2915/* after we parsed cmd line options, check if we can obey the request to run CS (valid for Gencon only) */2916if (extensions->concurrentScavengerForced) {2917#if defined(J9VM_ARCH_X86) || defined(J9VM_ARCH_POWER) || defined(J9VM_ARCH_AARCH64)2918/*2919* x86, POWER and AArch64 do not respect -XXgc:softwareRangeCheckReadBarrier and have it set to true always.2920*2921* Z is the only consumer that actually uses -XXgc:softwareRangeCheckReadBarrier2922* to overwrite HW concurrent scavenge.2923*/2924extensions->softwareRangeCheckReadBarrier = true;2925#endif /* J9VM_ARCH_X86 || J9VM_ARCH_POWER || J9VM_ARCH_AARCH64 */2926if (LOADED == (FIND_DLL_TABLE_ENTRY(J9_JIT_DLL_NAME)->loadFlags & LOADED)) {2927/* If running jitted, it must be on supported h/w */2928J9ProcessorDesc processorDesc;2929j9sysinfo_get_processor_description(&processorDesc);2930bool hwSupported = j9sysinfo_processor_has_feature(&processorDesc, J9PORT_S390_FEATURE_GUARDED_STORAGE) &&2931j9sysinfo_processor_has_feature(&processorDesc, J9PORT_S390_FEATURE_SIDE_EFFECT_ACCESS);29322933if (hwSupported) {2934/* Software Barrier request overwrites HW usage on supported HW */2935extensions->concurrentScavengerHWSupport = hwSupported2936&& !extensions->softwareRangeCheckReadBarrier2937#if defined(J9VM_OPT_CRIU_SUPPORT)2938&& !vm->internalVMFunctions->isCRIUSupportEnabled(vm->internalVMFunctions->currentVMThread(vm))2939#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */2940&& !J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_PORTABLE_SHARED_CACHE);2941extensions->concurrentScavenger = hwSupported || extensions->softwareRangeCheckReadBarrier;2942} else {2943extensions->concurrentScavengerHWSupport = false;2944#if defined(J9VM_ARCH_X86) || defined(J9VM_ARCH_POWER) || defined(J9VM_ARCH_AARCH64) || defined(J9VM_ARCH_S390)2945extensions->concurrentScavenger = true;2946#endif /*J9VM_ARCH_X86 || J9VM_ARCH_POWER || J9VM_ARCH_AARCH64 || J9VM_ARCH_S390 */2947}2948} else {2949/* running interpreted is ok on any h/w */2950extensions->concurrentScavenger = true;2951}2952}2953}2954#endif /* OMR_GC_CONCURRENT_SCAVENGER */29552956extensions->configuration = configurateGCWithPolicyAndOptions(vm->omrVM);29572958/* omrVM->gcPolicy is set by configurateGCWithPolicyAndOptions */2959((J9JavaVM*)env.getLanguageVM())->gcPolicy = vm->omrVM->gcPolicy;29602961if (NULL == extensions->configuration) {2962loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE, "Failed to initialize.");2963goto error;2964}29652966extensions->trackMutatorThreadCategory = J9_ARE_NO_BITS_SET(vm->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_REDUCE_CPU_MONITOR_OVERHEAD);29672968if (!gcParseTGCCommandLine(vm)) {2969loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE_PARSING_COMMAND_LINE, "Failed to initialize, parsing command line.");2970goto error;2971}29722973#if defined(J9VM_GC_MODRON_SCAVENGER)2974if (extensions->scavengerEnabled) {2975flatConfiguration = false;2976}2977#endif /* J9VM_GC_MODRON_SCAVENGER */29782979while (true) {2980/* Verify Xmx and Xmdx before using the Xmdx value to calculate further values */2981if (JNI_OK != gcInitializeXmxXmdxVerification(vm, memoryParameterTable, flatConfiguration, minimumVMSize, NULL, NULL)) {2982loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE, "Failed to initialize.");2983goto error;2984}29852986/* Calculate memory parameters based on Xmx/Xmdx */2987if (JNI_OK != gcInitializeCalculatedValues(vm, memoryParameterTable)) {2988loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE, "Failed to initialize.");2989goto error;2990}29912992/* Verify all memory parameters */2993if (JNI_OK != gcInitializeVerification(vm, memoryParameterTable, flatConfiguration)) {2994loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE, "Failed to initialize.");2995goto error;2996}29972998/* Try to initialize basic heap structures with the memory parameters we currently have */2999if (JNI_OK == j9gc_initialize_heap(vm, memoryParameterTable, extensions->memoryMax)) {3000break;3001}30023003if(extensions->largePageFailedToSatisfy) {3004/* We were unable to satisfy the user's request for a strict page size. */3005goto error;3006}30073008if (!reduceXmxValueForHeapInitialization(vm, memoryParameterTable, minimumVMSize)) {3009/* Unable to reduce the Xmx value -- fail */3010/* Error string is set by j9gc_initialize_heap */3011goto error;3012}30133014/* We are going to try again -- free any buffer we already have from j9gc_initialize_heap */3015if ((loadInfo->loadFlags & FREE_ERROR_STRING) && (NULL != loadInfo->fatalErrorStr)) {3016j9mem_free_memory(loadInfo->fatalErrorStr);3017loadInfo->loadFlags &= ~FREE_ERROR_STRING;3018}3019loadInfo->fatalErrorStr = NULL;3020}30213022/* initialize largeObjectAllocationProfilingVeryLargeObjectThreshold, largeObjectAllocationProfilingVeryLargeObjectSizeClass and freeMemoryProfileMaxSizeClasses for non segregated memoryPool case */3023if (gc_policy_metronome != extensions->configurationOptions._gcPolicy) {3024MM_LargeObjectAllocateStats::initializeFreeMemoryProfileMaxSizeClasses(&env, extensions->largeObjectAllocationProfilingVeryLargeObjectThreshold,3025(float)extensions->largeObjectAllocationProfilingSizeClassRatio / (float)100.0, extensions->heap->getMaximumMemorySize());3026}3027warnIfPageSizeNotSatisfied(vm,extensions);3028j9mem_free_memory(memoryParameterTable);3029return J9VMDLLMAIN_OK;30303031error:3032if (memoryParameterTable) {3033j9mem_free_memory(memoryParameterTable);3034}3035return J9VMDLLMAIN_FAILED;3036}30373038#if defined(OMR_GC_CONCURRENT_SCAVENGER)3039static void3040hookAcquireVMAccess(J9HookInterface** hook, UDATA eventNum, void* voidEventData, void* userData)3041{3042J9VMAcquireVMAccessEvent* eventData = (J9VMAcquireVMAccessEvent*)voidEventData;30433044J9VMThread *currentThread = eventData->currentThread;3045MM_EnvironmentStandard *env = MM_EnvironmentStandard::getEnvironment(currentThread->omrVMThread);3046MM_GCExtensions* ext = MM_GCExtensions::getExtensions(currentThread);30473048Assert_MM_true(ext->concurrentScavenger);30493050ext->scavenger->switchConcurrentForThread(env);3051}30523053static void3054hookReleaseVMAccess(J9HookInterface** hook, UDATA eventNum, void* voidEventData, void* userData)3055{3056J9VMReleaseVMAccessEvent* eventData = (J9VMReleaseVMAccessEvent*)voidEventData;30573058J9VMThread *currentThread = eventData->currentThread;3059MM_EnvironmentStandard *env = MM_EnvironmentStandard::getEnvironment(currentThread->omrVMThread);3060MM_GCExtensions* ext = MM_GCExtensions::getExtensions(currentThread);30613062if (ext->isConcurrentScavengerInProgress()) {3063/* Flush and final flags are false, which means that we will not release the copy caches to scan queue, but just make them inactive,3064* for someone else to release them if needed. More often, however, this thread will re-acquire VM access and re-active the caches3065*/3066ext->scavenger->threadReleaseCaches(env, env, false, false);3067}3068}30693070static void3071hookAcquiringExclusiveInNative(J9HookInterface** hook, UDATA eventNum, void* voidEventData, void* userData)3072{3073J9VMAcquringExclusiveInNativeEvent* eventData = (J9VMAcquringExclusiveInNativeEvent*)voidEventData;30743075J9VMThread *targetThread = eventData->targetThread;3076MM_EnvironmentStandard *env = MM_EnvironmentStandard::getEnvironment(targetThread->omrVMThread);3077MM_GCExtensions* ext = MM_GCExtensions::getExtensions(targetThread);30783079if (ext->isConcurrentScavengerInProgress()) {3080/* This call back occurs when Exclusive is being acquired. There are no reason for delaying final flush - do it now (Hence, the flags are true). */3081ext->scavenger->threadReleaseCaches(NULL, env, true, true);30823083}3084}30853086#endif /* OMR_GC_CONCURRENT_SCAVENGER */30873088/**3089* Report an event indicating that the GC is initialized3090*/3091jint3092triggerGCInitialized(J9VMThread* vmThread)3093{3094J9JavaVM* vm = vmThread->javaVM;3095PORT_ACCESS_FROM_JAVAVM(vm);3096MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);30973098UDATA beatMicro = 0;3099UDATA timeWindowMicro = 0;3100UDATA targetUtilizationPercentage = 0;3101UDATA gcInitialTrigger = 0;3102UDATA headRoom = 0;3103#if defined(J9VM_GC_REALTIME)3104beatMicro = extensions->beatMicro;3105timeWindowMicro = extensions->timeWindowMicro;3106targetUtilizationPercentage = extensions->targetUtilizationPercentage;3107gcInitialTrigger = extensions->gcInitialTrigger;3108headRoom = extensions->headRoom;3109#endif /* J9VM_GC_REALTIME */31103111UDATA numaNodes = extensions->_numaManager.getAffinityLeaderCount();31123113UDATA regionSize = extensions->getHeap()->getHeapRegionManager()->getRegionSize();3114UDATA regionCount = extensions->getHeap()->getHeapRegionManager()->getTableRegionCount();31153116UDATA arrayletLeafSize = 0;3117arrayletLeafSize = vm->arrayletLeafSize;31183119TRIGGER_J9HOOK_MM_OMR_INITIALIZED(3120extensions->omrHookInterface,3121vmThread->omrVMThread,3122j9time_hires_clock(),3123j9gc_get_gcmodestring(vm),31240, /* unused */3125j9gc_get_maximum_heap_size(vm),3126j9gc_get_initial_heap_size(vm),3127j9sysinfo_get_physical_memory(),3128j9sysinfo_get_number_CPUs_by_type(J9PORT_CPU_ONLINE),3129extensions->gcThreadCount,3130j9sysinfo_get_CPU_architecture(),3131j9sysinfo_get_OS_type(),3132j9sysinfo_get_OS_version(),3133extensions->accessBarrier->compressedPointersShift(),3134beatMicro,3135timeWindowMicro,3136targetUtilizationPercentage,3137gcInitialTrigger,3138headRoom,3139extensions->heap->getPageSize(),3140getPageTypeString(extensions->heap->getPageFlags()),3141extensions->requestedPageSize,3142getPageTypeString(extensions->requestedPageFlags),3143numaNodes,3144regionSize,3145regionCount,3146arrayletLeafSize);31473148return J9VMDLLMAIN_OK;3149}31503151static void3152hookValidatorVMThreadCrash(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)3153{3154J9VMThread *vmThread = ((J9VMThreadCrashEvent *)eventData)->currentThread;3155MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);3156if (NULL != env) {3157MM_Validator *activeValidator = env->_activeValidator;3158if (NULL != activeValidator) {3159env->_activeValidator = NULL; /* make absolutely sure we don't go recursive */3160activeValidator->threadCrash(env);3161}3162}3163}31643165static void3166hookVMRegistrationEvent(J9HookInterface** hook, UDATA eventNum, void* voidEventData, void* userData)3167{3168J9HookRegistrationEvent* eventData = (J9HookRegistrationEvent*)voidEventData;31693170switch (eventData->eventNum) {3171case J9HOOK_VM_OBJECT_ALLOCATE_WITHIN_THRESHOLD:3172case J9HOOK_VM_OBJECT_ALLOCATE_INSTRUMENTABLE: {3173J9JavaVM* vm = (J9JavaVM*)userData;3174J9VMThread * currentThread = vm->internalVMFunctions->currentVMThread(vm);3175if (currentThread != NULL) {3176j9gc_allocation_threshold_changed(currentThread);3177}3178}3179}3180}31813182static bool3183gcInitializeVMHooks(MM_GCExtensionsBase *extensions)3184{3185bool result = true;3186J9JavaVM* javaVM = (J9JavaVM *)extensions->getOmrVM()->_language_vm;31873188J9HookInterface **vmHookInterface = javaVM->internalVMFunctions->getVMHookInterface(javaVM);3189if (NULL == vmHookInterface) {3190result = false;3191} else if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_VM_THREAD_CRASH, hookValidatorVMThreadCrash, OMR_GET_CALLSITE(), NULL)) {3192result = false;3193} else if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_REGISTRATION_EVENT, hookVMRegistrationEvent, OMR_GET_CALLSITE(), javaVM)) {3194result = false;3195}3196#if defined(OMR_GC_CONCURRENT_SCAVENGER)3197else if (extensions->concurrentScavenger) {3198if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_VM_ACQUIREVMACCESS, hookAcquireVMAccess, OMR_GET_CALLSITE(), NULL)) {3199result = false;3200} else if (extensions->concurrentScavengeExhaustiveTermination) {3201/* Register these hooks only if Exhaustive Termination optimization is enabled */3202if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_VM_RELEASEVMACCESS, hookReleaseVMAccess, OMR_GET_CALLSITE(), NULL)) {3203result = false;3204} else if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_VM_ACQUIRING_EXCLUSIVE_IN_NATIVE, hookAcquiringExclusiveInNative, OMR_GET_CALLSITE(), NULL)) {3205result = false;3206}3207}3208}3209#endif /* OMR_GC_CONCURRENT_SCAVENGER */32103211return result;3212}32133214static void3215gcCleanupVMHooks(MM_GCExtensionsBase *extensions)3216{3217J9JavaVM* javaVM = (J9JavaVM *)extensions->getOmrVM()->_language_vm;3218J9HookInterface **vmHookInterface = javaVM->internalVMFunctions->getVMHookInterface(javaVM);3219if (NULL != vmHookInterface) {3220(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_VM_THREAD_CRASH, hookValidatorVMThreadCrash, NULL);3221(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_REGISTRATION_EVENT, hookVMRegistrationEvent, javaVM);3222#if defined(OMR_GC_CONCURRENT_SCAVENGER)3223if (extensions->concurrentScavenger) {3224(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_VM_ACQUIREVMACCESS, hookAcquireVMAccess, NULL);3225if (extensions->concurrentScavengeExhaustiveTermination) {3226(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_VM_RELEASEVMACCESS, hookReleaseVMAccess, NULL);3227(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_VM_ACQUIRING_EXCLUSIVE_IN_NATIVE, hookAcquiringExclusiveInNative, NULL);3228}3229}3230#endif /* OMR_GC_CONCURRENT_SCAVENGER */3231}3232}32333234} /* extern "C" */323532363237