Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_modron_startup/mminit.cpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2022 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
/**
24
* @file
25
* @ingroup GC_Modron_Startup
26
*/
27
28
#if defined (J9VM_GC_VLHGC)
29
#include <math.h>
30
#endif /* J9VM_GC_VLHGC */
31
#include <string.h>
32
33
#include "gcmspace.h"
34
#include "gcutils.h"
35
#include "j2sever.h"
36
#include "j9.h"
37
#include "j9cfg.h"
38
#include "j9comp.h"
39
#include "j9consts.h"
40
#include "j9modron.h"
41
#include "j9port.h"
42
#include "j9protos.h"
43
#include "jni.h"
44
#include "jvminit.h"
45
#include "mminit.h"
46
#include "mminitcore.h"
47
#include "mmparse.h"
48
#include "modronnls.h"
49
#include "omr.h"
50
#if defined(J9VM_GC_MODRON_TRACE) && !defined(J9VM_GC_REALTIME)
51
#include "Tgc.hpp"
52
#endif /* J9VM_GC_MODRON_TRACE && !defined(J9VM_GC_REALTIME) */
53
54
#if defined (J9VM_GC_HEAP_CARD_TABLE)
55
#include "CardTable.hpp"
56
#endif /* defined (J9VM_GC_HEAP_CARD_TABLE) */
57
#include "CollectorLanguageInterfaceImpl.hpp"
58
#if defined(OMR_GC_MODRON_CONCURRENT_MARK)
59
#include "ConcurrentCardTable.hpp"
60
#include "ConcurrentGC.hpp"
61
#endif /* OMR_GC_MODRON_CONCURRENT_MARK */
62
#include "Configuration.hpp"
63
#if defined(J9VM_GC_MODRON_STANDARD)
64
#include "ConfigurationFlat.hpp"
65
#include "ConfigurationGenerational.hpp"
66
#endif /* J9VM_GC_MODRON_STANDARD */
67
#if defined(J9VM_GC_VLHGC)
68
#include "ConfigurationIncrementalGenerational.hpp"
69
#endif /* J9VM_GC_VLHGC */
70
#if defined(J9VM_GC_REALTIME)
71
#include "ConfigurationRealtime.hpp"
72
#endif /* J9VM_GC_REALTIME */
73
#include "ClassLoaderManager.hpp"
74
#include "Debug.hpp"
75
#include "EnvironmentBase.hpp"
76
#if defined(J9VM_GC_FINALIZATION)
77
#include "FinalizeListManager.hpp"
78
#endif /* J9VM_GC_FINALIZATION */
79
#include "GCExtensions.hpp"
80
#include "GlobalAllocationManager.hpp"
81
#include "GlobalCollector.hpp"
82
#include "HeapRegionDescriptor.hpp"
83
#include "HeapRegionManager.hpp"
84
#include "LargeObjectAllocateStats.hpp"
85
#include "Math.hpp"
86
#include "MemorySpace.hpp"
87
#include "MemorySubSpace.hpp"
88
#include "ModronAssertions.h"
89
#include "ObjectAccessBarrier.hpp"
90
#include "ObjectAllocationInterface.hpp"
91
#include "OMRVMInterface.hpp"
92
#include "OMRVMThreadInterface.hpp"
93
#include "ParallelDispatcher.hpp"
94
#if defined(J9VM_GC_VLHGC)
95
#include "RememberedSetCardList.hpp"
96
#endif /* J9VM_GC_VLHGC */
97
#if defined(J9VM_GC_SEGRGATED_HEAP)
98
#include "ObjectHeapIteratorSegregated.hpp"
99
#include "SizeClasses.hpp"
100
#endif /* J9VM_GC_SEGRGATED_HEAP */
101
#if defined(J9VM_GC_REALTIME)
102
#include "RememberedSetSATB.hpp"
103
#endif /* J9VM_GC_REALTIME */
104
#include "Scavenger.hpp"
105
#include "StringTable.hpp"
106
#include "Validator.hpp"
107
#if defined(OMR_GC_IDLE_HEAP_MANAGER)
108
#include "IdleGCManager.hpp"
109
#endif
110
111
/**
112
* If we fail to allocate heap structures with the default Xmx value,
113
* we will try again with a smaller value. These parameters define
114
* the percentage by which to reduce the Xmx value.
115
*/
116
#define DEFAULT_XMX_REDUCTION_NUMERATOR 4
117
#define DEFAULT_XMX_REDUCTION_DENOMINATOR 5
118
119
#define NONE ((UDATA) 0x0)
120
#define XMS ((UDATA) 0x1)
121
#define XMOS ((UDATA) 0x2)
122
#define XMNS ((UDATA) 0x4)
123
#define XMDX ((UDATA) 0x8)
124
125
#define XMS_XMOS ((UDATA) XMS | XMOS)
126
#define XMOS_XMNS ((UDATA) XMOS | XMNS)
127
#define XMDX_XMS ((UDATA) XMDX | XMS)
128
129
#define ROUND_TO(granularity, number) (((UDATA)(number) + (granularity) - 1) & ~((UDATA)(granularity) - 1))
130
131
extern "C" {
132
extern J9MemoryManagerFunctions MemoryManagerFunctions;
133
extern void initializeVerboseFunctionTableWithDummies(J9MemoryManagerVerboseInterface *table);
134
135
static void hookValidatorVMThreadCrash(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData);
136
static bool gcInitializeVMHooks(MM_GCExtensionsBase *extensions);
137
static void gcCleanupVMHooks(MM_GCExtensionsBase *extensions);
138
139
static const char * displayXmxOrMaxRAMPercentage(IDATA* memoryParameters);
140
static const char * displayXmsOrInitialRAMPercentage(IDATA* memoryParameters);
141
142
/**
143
* Initialize the threads mutator information (RS pointers, reference list pointers etc) for GC/MM purposes.
144
*
145
* @note vmThread MAY NOT be initialized completely from an execution model perspective.
146
* @return 0 if OK, or non 0 if error
147
*/
148
IDATA
149
initializeMutatorModelJava(J9VMThread* vmThread)
150
{
151
if (0 != initializeMutatorModel(vmThread->omrVMThread)) {
152
return -1;
153
}
154
155
MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(vmThread);
156
vmThread->gcExtensions = vmThread->omrVMThread->_gcOmrVMThreadExtensions;
157
158
if (extensions->isStandardGC()) {
159
if (extensions->isConcurrentScavengerEnabled()) {
160
/* Ensure that newly created threads invoke VM access using slow path, so that the associated hook is invoked.
161
* GC will register to the hook to enable local thread resources if a thread happens to be created in a middle of Concurrent Scavenge */
162
setEventFlag(vmThread, J9_PUBLIC_FLAGS_DISABLE_INLINE_VM_ACCESS);
163
}
164
165
#if defined(J9VM_GC_GENERATIONAL)
166
vmThread->gcRememberedSet.fragmentCurrent = NULL;
167
vmThread->gcRememberedSet.fragmentTop = NULL;
168
vmThread->gcRememberedSet.fragmentSize = OMR_SCV_REMSET_FRAGMENT_SIZE;
169
#endif /* J9VM_GC_GENERATIONAL */
170
171
void *lowAddress = extensions->heapBaseForBarrierRange0;
172
void *highAddress = (void *)((UDATA)extensions->heapBaseForBarrierRange0 + extensions->heapSizeForBarrierRange0);
173
174
// todo: dagar lowTenureAddress, highTenureAddress, heapBaseForBarrierRange0, heapSizeForBarrierRange0 are duplicated
175
vmThread->lowTenureAddress = lowAddress;
176
vmThread->highTenureAddress = highAddress;
177
178
/* replacement values for lowTenureAddress and highTenureAddress */
179
// todo: dagar remove duplicate fields
180
vmThread->heapBaseForBarrierRange0 = extensions->heapBaseForBarrierRange0;
181
vmThread->heapSizeForBarrierRange0 = extensions->heapSizeForBarrierRange0;
182
#if defined (J9VM_GC_HEAP_CARD_TABLE)
183
if (NULL != extensions->cardTable) {
184
vmThread->activeCardTableBase = extensions->cardTable->getCardTableStart();
185
}
186
#endif /* J9VM_GC_HEAP_CARD_TABLE */
187
} else if(extensions->isVLHGC()) {
188
MM_Heap *heap = extensions->getHeap();
189
void *heapBase = heap->getHeapBase();
190
void *heapTop = heap->getHeapTop();
191
192
/* replacement values for lowTenureAddress and highTenureAddress */
193
vmThread->heapBaseForBarrierRange0 = heapBase;
194
vmThread->heapSizeForBarrierRange0 = (UDATA)heapTop - (UDATA)heapBase;
195
196
/* lowTenureAddress and highTenureAddress are actually supposed to be the low and high addresses of the heap for which card
197
* dirtying is required (the JIT uses this as a range check to determine if it needs to dirty a card when writing into an
198
* object). Setting these for Tarok is just a work-around until a more generic solution is implemented
199
*/
200
vmThread->lowTenureAddress = heapBase;
201
vmThread->highTenureAddress = heapTop;
202
#if defined (J9VM_GC_HEAP_CARD_TABLE)
203
vmThread->activeCardTableBase = extensions->cardTable->getCardTableStart();
204
#endif /* J9VM_GC_HEAP_CARD_TABLE */
205
}
206
return 0;
207
}
208
209
/**
210
* Cleanup Mutator specific resources (TLH, thread extension, etc) on shutdown.
211
*/
212
void
213
cleanupMutatorModelJava(J9VMThread* vmThread)
214
{
215
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);
216
217
if (NULL != env) {
218
J9JavaVM *vm = vmThread->javaVM;
219
J9VMDllLoadInfo *loadInfo = getGCDllLoadInfo(vm);
220
221
/* cleanupMutatorModelJava is called as part of the main vmThread shutdown, which happens after
222
* gcCleanupHeapStructures has been called. We should therefore only flush allocation caches
223
* if there is still a heap.
224
*/
225
if (!IS_STAGE_COMPLETED(loadInfo->completedBits, HEAP_STRUCTURES_FREED)) {
226
/* 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 */
227
GC_OMRVMThreadInterface::flushCachesForGC(env);
228
}
229
}
230
231
cleanupMutatorModel(vmThread->omrVMThread, 0);
232
233
vmThread->gcExtensions = NULL;
234
}
235
236
/**
237
* Triggers hook for deleting private heap.
238
* @param memorySpace pointer to the list (pool) of memory spaces
239
*/
240
static void
241
reportPrivateHeapDelete(J9JavaVM * javaVM, void * memorySpace)
242
{
243
MM_EnvironmentBase env(javaVM->omrVM);
244
245
MM_MemorySpace *modronMemorySpace = (MM_MemorySpace *)memorySpace;
246
if (modronMemorySpace) {
247
if (!(javaVM->runtimeFlags & J9_RUNTIME_SHUTDOWN)) {
248
TRIGGER_J9HOOK_MM_PRIVATE_HEAP_DELETE(
249
MM_GCExtensions::getExtensions(javaVM)->privateHookInterface,
250
env.getOmrVMThread(),
251
modronMemorySpace);
252
}
253
}
254
}
255
256
/**
257
* Cleanup passive heap structures
258
*/
259
void
260
gcCleanupHeapStructures(J9JavaVM * vm)
261
{
262
/* If shutdown occurs early (due to command line parsing errors, for example) there may not be
263
* a J9VMThread, so allocate a fake environment.
264
*/
265
MM_EnvironmentBase env(vm->omrVM);
266
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
267
268
/* remove hooks installed by Validator */
269
gcCleanupVMHooks(extensions);
270
271
/* Flush any allocation contexts so that their memory is returned to the memory spaces before we tear down the memory spaces */
272
MM_GlobalAllocationManager *gam = extensions->globalAllocationManager;
273
if (NULL != gam) {
274
gam->flushAllocationContextsForShutdown(&env);
275
}
276
277
if (vm->memorySegments) {
278
vm->internalVMFunctions->freeMemorySegmentList(vm, vm->memorySegments);
279
}
280
if (vm->classMemorySegments) {
281
vm->internalVMFunctions->freeMemorySegmentList(vm, vm->classMemorySegments);
282
}
283
284
#if defined(J9VM_GC_FINALIZATION)
285
if (extensions->finalizeListManager) {
286
extensions->finalizeListManager->kill(&env);
287
extensions->finalizeListManager = NULL;
288
}
289
#endif /* J9VM_GC_FINALIZATION */
290
291
if (vm->mainThread && vm->mainThread->threadObject) {
292
/* main thread has not been deallocated yet, but heap has gone */
293
vm->mainThread->threadObject = NULL;
294
}
295
return;
296
}
297
298
/**
299
* Initialized passive and active heap components
300
*/
301
IDATA
302
j9gc_initialize_heap(J9JavaVM *vm, IDATA *memoryParameterTable, UDATA heapBytesRequested)
303
{
304
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
305
MM_EnvironmentBase env(vm->omrVM);
306
MM_GlobalCollector *globalCollector;
307
PORT_ACCESS_FROM_JAVAVM(vm);
308
J9VMDllLoadInfo *loadInfo = getGCDllLoadInfo(vm);
309
310
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_PORTABLE_SHARED_CACHE)) {
311
extensions->shouldForceLowMemoryHeapCeilingShiftIfPossible = true;
312
}
313
314
#if defined(J9VM_GC_BATCH_CLEAR_TLH)
315
/* Record batch clear state in VM so inline allocates can decide correct initialization procedure */
316
vm->initializeSlotsOnTLHAllocate = (extensions->batchClearTLH == 0) ? 1 : 0;
317
#endif /* J9VM_GC_BATCH_CLEAR_TLH */
318
319
extensions->heap = extensions->configuration->createHeap(&env, heapBytesRequested);
320
321
if (NULL == extensions->heap) {
322
const char *splitFailure = NULL;
323
324
/* If error reason was not explicitly set use general error message */
325
if(MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_NO_ERROR == extensions->heapInitializationFailureReason) {
326
extensions->heapInitializationFailureReason = MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_HEAP;
327
}
328
329
switch(extensions->heapInitializationFailureReason) {
330
331
/* see if we set the split-heap specific error since we want to be more verbose in that case */
332
case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_SPLIT_HEAP_OLD_SPACE:
333
splitFailure = 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");
334
break;
335
case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_SPLIT_HEAP_NEW_SPACE:
336
splitFailure = 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");
337
break;
338
case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_SPLIT_HEAP_GEOMETRY:
339
splitFailure = 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");
340
break;
341
342
/* failed an attempt to allocate low memory reserve */
343
case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_ALLOCATE_LOW_MEMORY_RESERVE:
344
{
345
/* Obtain the qualified size (e.g. 2k) */
346
UDATA size = extensions->suballocatorInitialSize;
347
const char* qualifier = NULL;
348
qualifiedSize(&size, &qualifier);
349
350
char *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");
351
UDATA formatLength = strlen(format) + 32; /* 2^64 is 20 digits, so have a few extra */
352
353
loadInfo->fatalErrorStr = (char *)j9mem_allocate_memory(formatLength, OMRMEM_CATEGORY_MM);
354
if (loadInfo->fatalErrorStr) {
355
j9str_printf(PORTLIB, loadInfo->fatalErrorStr, formatLength, format, size, qualifier);
356
loadInfo->loadFlags |= FREE_ERROR_STRING; /* indicates that buffer should be freed later */
357
}
358
break;
359
}
360
361
/* general error message - can not instantiate heap */
362
case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_INSTANTIATE_HEAP:
363
{
364
/* Obtain the qualified size (e.g. 2k) */
365
UDATA size = heapBytesRequested;
366
const char* qualifier = NULL;
367
qualifiedSize(&size, &qualifier);
368
369
char *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");
370
UDATA formatLength = strlen(format) + 32; /* 2^64 is 20 digits, so have a few extra */
371
372
loadInfo->fatalErrorStr = (char *)j9mem_allocate_memory(formatLength, OMRMEM_CATEGORY_MM);
373
if (loadInfo->fatalErrorStr) {
374
j9str_printf(PORTLIB, loadInfo->fatalErrorStr, formatLength, format, size, qualifier);
375
loadInfo->loadFlags |= FREE_ERROR_STRING; /* indicates that buffer should be freed later */
376
}
377
break;
378
}
379
380
/* general error message - can not instantiate heap */
381
case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_CAN_NOT_SATISFY_REQUESTED_PAGE_SIZE:
382
{
383
/* Obtain the qualified size (e.g. 2k) */
384
UDATA heapSize = extensions->memoryMax;
385
const char* heapSizeQualifier = NULL;
386
qualifiedSize(&heapSize, &heapSizeQualifier);
387
388
UDATA pageSize = extensions->requestedPageSize;
389
const char* pageSizeQualifier = NULL;
390
qualifiedSize(&pageSize, &pageSizeQualifier);
391
392
char *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");
393
UDATA formatLength = strlen(format) + 32; /* 2^64 is 20 digits, so have a few extra */
394
395
loadInfo->fatalErrorStr = (char *)j9mem_allocate_memory(formatLength, OMRMEM_CATEGORY_MM);
396
if (loadInfo->fatalErrorStr) {
397
j9str_printf(PORTLIB, loadInfo->fatalErrorStr, formatLength, format, heapSize, heapSizeQualifier, pageSize, pageSizeQualifier);
398
loadInfo->loadFlags |= FREE_ERROR_STRING; /* indicates that buffer should be freed later */
399
}
400
extensions->largePageFailedToSatisfy = true;
401
break;
402
}
403
404
case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_NO_ERROR:
405
case MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_METRONOME_DOES_NOT_SUPPORT_4BIT_SHIFT:
406
default:
407
Assert_MM_unreachable();
408
break;
409
}
410
411
/* Handle split heap failures cases */
412
if (NULL != splitFailure) {
413
const 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)");
414
UDATA oldSpaceSize = extensions->oldSpaceSize;
415
const char* oldQualifier = NULL;
416
qualifiedSize(&oldSpaceSize, &oldQualifier);
417
UDATA newSpaceSize = extensions->newSpaceSize;
418
const char* newQualifier = NULL;
419
qualifiedSize(&newSpaceSize, &newQualifier);
420
UDATA formatLength = j9str_printf(PORTLIB, NULL, 0, format, splitFailure, newSpaceSize, newQualifier, oldSpaceSize, oldQualifier);
421
422
loadInfo->fatalErrorStr = (char *)j9mem_allocate_memory(formatLength, OMRMEM_CATEGORY_MM);
423
if (loadInfo->fatalErrorStr) {
424
j9str_printf(PORTLIB, loadInfo->fatalErrorStr, formatLength, format, splitFailure, newSpaceSize, newQualifier, oldSpaceSize, oldQualifier);
425
loadInfo->loadFlags |= FREE_ERROR_STRING; /* indicates that buffer should be freed later */
426
}
427
}
428
429
/* failed to generate error string - use default */
430
if(NULL == loadInfo->fatalErrorStr) {
431
loadInfo->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.");
432
}
433
434
goto error_no_memory;
435
}
436
437
extensions->dispatcher = extensions->configuration->createParallelDispatcher(&env, (omrsig_handler_fn)vm->internalVMFunctions->structuredSignalHandlerVM, vm, vm->defaultOSStackSize);
438
if (NULL == extensions->dispatcher) {
439
loadInfo->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.");
440
goto error_no_memory;
441
}
442
443
/* Initialize VM interface extensions */
444
GC_OMRVMInterface::initializeExtensions(extensions);
445
446
/* Initialize the global collector */
447
globalCollector = extensions->configuration->createGlobalCollector(&env);
448
if (NULL == globalCollector) {
449
if(MM_GCExtensionsBase::HEAP_INITIALIZATION_FAILURE_REASON_METRONOME_DOES_NOT_SUPPORT_4BIT_SHIFT == extensions->heapInitializationFailureReason) {
450
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTION_OVERFLOW, displayXmxOrMaxRAMPercentage(memoryParameterTable));
451
}
452
loadInfo->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.");
453
goto error_no_memory;
454
}
455
/* Mark this collector as a global collector so that we will check for excessive gc after it collects */
456
globalCollector->setGlobalCollector(true);
457
extensions->setGlobalCollector(globalCollector);
458
459
/* Create the environments pool */
460
extensions->environments = extensions->configuration->createEnvironmentPool(&env);
461
if (NULL == extensions->environments) {
462
goto error_no_memory;
463
}
464
465
extensions->classLoaderManager = MM_ClassLoaderManager::newInstance(&env, globalCollector);
466
if (NULL == extensions->classLoaderManager) {
467
goto error_no_memory;
468
}
469
470
extensions->stringTable = MM_StringTable::newInstance(&env, extensions->dispatcher->threadCountMaximum());
471
if (NULL == extensions->stringTable) {
472
goto error_no_memory;
473
}
474
475
/* Initialize statistic locks */
476
if (omrthread_monitor_init_with_name(&extensions->gcStatsMutex, 0, "MM_GCExtensions::gcStats")) {
477
loadInfo->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.");
478
goto error_no_memory;
479
}
480
481
#if defined(OMR_GC_IDLE_HEAP_MANAGER)
482
if (extensions->gcOnIdle) {
483
/* Enable idle tuning only for gencon policy */
484
if (gc_policy_gencon == extensions->configurationOptions._gcPolicy) {
485
extensions->idleGCManager = MM_IdleGCManager::newInstance(&env);
486
if (NULL == extensions->idleGCManager) {
487
goto error_no_memory;
488
}
489
}
490
}
491
#endif
492
493
return JNI_OK;
494
495
error_no_memory:
496
return JNI_ENOMEM;
497
}
498
499
/**
500
* Creates and initialized VM owned structures related to the heap
501
* Calls low level heap initialization function
502
* @return J9VMDLLMAIN_OK or J9VMDLLMAIN_FAILED
503
*/
504
jint
505
gcInitializeHeapStructures(J9JavaVM *vm)
506
{
507
PORT_ACCESS_FROM_JAVAVM(vm);
508
MM_EnvironmentBase env(vm->omrVM);
509
510
MM_MemorySpace *defaultMemorySpace;
511
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
512
J9VMDllLoadInfo *loadInfo = getGCDllLoadInfo(vm);
513
514
/* For now, number of segments to default in pool */
515
if ((vm->memorySegments = vm->internalVMFunctions->allocateMemorySegmentList(vm, 10, OMRMEM_CATEGORY_VM)) == NULL) {
516
loadInfo->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.");
517
goto error;
518
}
519
520
/* For now, number of segments to default in pool */
521
if ((vm->classMemorySegments = vm->internalVMFunctions->allocateMemorySegmentListWithFlags(vm, 10, MEMORY_SEGMENT_LIST_FLAG_SORT, J9MEM_CATEGORY_CLASSES)) == NULL) {
522
loadInfo->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.");
523
goto error;
524
}
525
526
/* j9gc_initialize_heap is now called from gcInitializeDefaults */
527
528
/* Create and initialize the default memory space */
529
defaultMemorySpace = internalAllocateMemorySpaceWithMaximum(vm, extensions->initialMemorySize, extensions->minNewSpaceSize, extensions->newSpaceSize, extensions->maxNewSpaceSize, extensions->minOldSpaceSize, extensions->oldSpaceSize, extensions->maxOldSpaceSize, extensions->maxSizeDefaultMemorySpace, 0, MEMORY_TYPE_DISCARDABLE);
530
if (defaultMemorySpace == NULL) {
531
loadInfo->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.");
532
goto error;
533
}
534
535
extensions->configuration->defaultMemorySpaceAllocated(extensions, defaultMemorySpace);
536
537
#if defined(J9VM_GC_FINALIZATION)
538
if(!(extensions->finalizeListManager = GC_FinalizeListManager::newInstance(&env))) {
539
loadInfo->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.");
540
goto error;
541
}
542
#endif /* J9VM_GC_FINALIZATION */
543
544
/* install hooks for the Validator */
545
if (!gcInitializeVMHooks(extensions)) {
546
goto error;
547
}
548
549
vm->defaultMemorySpace = defaultMemorySpace;
550
551
return J9VMDLLMAIN_OK;
552
553
error:
554
return J9VMDLLMAIN_FAILED;
555
}
556
557
/**
558
* Starts the Finalizer and the Heap management components
559
* @return 0 if OK, non zero if error
560
*/
561
int
562
gcStartupHeapManagement(J9JavaVM *javaVM)
563
{
564
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
565
int result = 0;
566
567
#if defined(J9VM_GC_FINALIZATION)
568
#if JAVA_SPEC_VERSION >= 18
569
if (J9_ARE_ANY_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_DISABLE_FINALIZATION)) {
570
/* Finalization is disabled */
571
} else
572
#endif /* JAVA_SPEC_VERSION >= 18 */
573
{
574
result = j9gc_finalizer_startup(javaVM);
575
if (JNI_OK != result) {
576
PORT_ACCESS_FROM_JAVAVM(javaVM);
577
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_FAILED_TO_INITIALIZE_FINALIZE_SUPPORT);
578
return result;
579
}
580
}
581
#endif /* J9VM_GC_FINALIZATION */
582
583
/* Kickoff secondary initialization for the global collector */
584
if (!extensions->getGlobalCollector()->collectorStartup(extensions)) {
585
result = JNI_ENOMEM;
586
}
587
588
if (!extensions->dispatcher->startUpThreads()) {
589
extensions->dispatcher->shutDownThreads();
590
result = JNI_ENOMEM;
591
}
592
593
if (JNI_OK != result) {
594
PORT_ACCESS_FROM_JAVAVM(javaVM);
595
extensions->getGlobalCollector()->collectorShutdown(extensions);
596
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_FAILED_TO_STARTUP_GARBAGE_COLLECTOR);
597
return result;
598
}
599
600
return result;
601
}
602
603
void j9gc_jvmPhaseChange(J9VMThread *currentThread, UDATA phase)
604
{
605
J9JavaVM *vm = currentThread->javaVM;
606
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
607
MM_EnvironmentBase env(currentThread->omrVMThread);
608
if (J9VM_PHASE_NOT_STARTUP == phase) {
609
610
if ((NULL != vm->sharedClassConfig) && extensions->useGCStartupHints) {
611
if (extensions->isStandardGC()) {
612
/* read old values from SC */
613
uintptr_t hintDefaultOld = 0;
614
uintptr_t hintTenureOld = 0;
615
vm->sharedClassConfig->findGCHints(currentThread, &hintDefaultOld, &hintTenureOld);
616
/* Nothing to do if read fails, we'll just assume the old values are 0 */
617
618
/* Get the current heap size values.
619
* Default/Tenure MemorySubSpace is of type Generic (which is MemoryPool owner, while the parents are of type Flat/SemiSpace).
620
* For SemiSpace the latter (parent) ones are what we want to deal with (expand), since it's what includes both Allocate And Survivor children.
621
* For Flat it would probably make no difference if we used parent or child, but let's be consistent and use parent, too.
622
*/
623
MM_MemorySubSpace *defaultMemorySubSpace = extensions->heap->getDefaultMemorySpace()->getDefaultMemorySubSpace()->getParent();
624
MM_MemorySubSpace *tenureMemorySubspace = extensions->heap->getDefaultMemorySpace()->getTenureMemorySubSpace()->getParent();
625
626
uintptr_t hintDefault = defaultMemorySubSpace->getActiveMemorySize();
627
uintptr_t hintTenure = 0;
628
629
/* Standard GCs always have Default MSS (which is equal to Tenure for flat heap configuration).
630
* So the simplest is always fetch Default, regardless if's generational haep configuration or not.
631
* We fetch Tenure only if only not equal to Default (which implies it's generational) */
632
if (defaultMemorySubSpace != tenureMemorySubspace) {
633
hintTenure = tenureMemorySubspace->getActiveMemorySize();
634
}
635
636
/* Gradually learn, by averaging new values with old values - it may take a few restarts before hint converge to stable values */
637
hintDefault = (uintptr_t)MM_Math::weightedAverage((float)hintDefaultOld, (float)hintDefault, (1.0f - extensions->heapSizeStartupHintWeightNewValue));
638
hintTenure = (uintptr_t)MM_Math::weightedAverage((float)hintTenureOld, (float)hintTenure, (1.0f - extensions->heapSizeStartupHintWeightNewValue));
639
640
vm->sharedClassConfig->storeGCHints(currentThread, hintDefault, hintTenure, true);
641
/* Nothing to do if store fails, storeGCHints already issues a trace point */
642
}
643
}
644
}
645
}
646
647
648
void
649
gcExpandHeapOnStartup(J9JavaVM *javaVM)
650
{
651
J9SharedClassConfig *sharedClassConfig = javaVM->sharedClassConfig;
652
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
653
J9VMThread *currentThread = javaVM->internalVMFunctions->currentVMThread(javaVM);
654
MM_EnvironmentBase env(currentThread->omrVMThread);
655
656
if ((NULL != sharedClassConfig) && extensions->useGCStartupHints) {
657
if (extensions->isStandardGC()) {
658
uintptr_t hintDefault = 0;
659
uintptr_t hintTenure = 0;
660
661
if (0 == sharedClassConfig->findGCHints(currentThread, &hintDefault, &hintTenure)) {
662
663
/* Default/Tenure MemorySubSpace is of type Generic (which is MemoryPool owner, while the parents are of type Flat/SemiSpace).
664
* For SemiSpace the latter (parent) ones are what we want to deal with (expand), since it's what includes both Allocate And Survivor children.
665
* For Flat it would probably make no difference if we used parent or child, but let's be consistent and use parent, too.
666
*/
667
MM_MemorySubSpace *defaultMemorySubSpace = extensions->heap->getDefaultMemorySpace()->getDefaultMemorySubSpace()->getParent();
668
MM_MemorySubSpace *tenureMemorySubspace = extensions->heap->getDefaultMemorySpace()->getTenureMemorySubSpace()->getParent();
669
670
671
/* Standard GCs always have Default MSS (which is equal to Tenure for flat heap configuration).
672
* So the simplest is always deal with Default, regardless if's generational heap configuration or not.
673
* We deal with Tenure only if only not equal to Default (which implies it's generational)
674
* We are a bit conservative and aim for slightly lower values that historically recorded by hints.
675
*/
676
uintptr_t hintDefaultAdjusted = (uintptr_t)(hintDefault * extensions->heapSizeStartupHintConservativeFactor);
677
uintptr_t defaultCurrent = defaultMemorySubSpace->getActiveMemorySize();
678
679
if (hintDefaultAdjusted > defaultCurrent) {
680
extensions->heap->getResizeStats()->setLastExpandReason(HINT_PREVIOUS_RUNS);
681
defaultMemorySubSpace->expand(&env, hintDefaultAdjusted - defaultCurrent);
682
}
683
684
if (defaultMemorySubSpace != tenureMemorySubspace) {
685
uintptr_t hintTenureAdjusted = (uintptr_t)(hintTenure * extensions->heapSizeStartupHintConservativeFactor);
686
uintptr_t tenureCurrent = tenureMemorySubspace->getActiveMemorySize();
687
688
if (hintTenureAdjusted > tenureCurrent) {
689
extensions->heap->getResizeStats()->setLastExpandReason(HINT_PREVIOUS_RUNS);
690
tenureMemorySubspace->expand(&env, hintTenureAdjusted - tenureCurrent);
691
}
692
}
693
694
}
695
/* Nothing to do if findGCHints failed. It already issues a trace point - no need to duplicate it here */
696
}
697
/* todo: Balanced GC */
698
}
699
}
700
701
702
/**
703
* Cleanup Finalizer and Heap components
704
*/
705
void
706
gcShutdownHeapManagement(J9JavaVM *javaVM)
707
{
708
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
709
MM_Collector *globalCollector = extensions->getGlobalCollector();
710
711
#if defined(J9VM_GC_FINALIZATION)
712
/* wait for finalizer shutdown */
713
j9gc_finalizer_shutdown(javaVM);
714
#endif /* J9VM_GC_FINALIZATION */
715
716
/* Kickoff shutdown of global collector */
717
if (NULL != globalCollector) {
718
globalCollector->collectorShutdown(extensions);
719
}
720
721
if (extensions->dispatcher) {
722
extensions->dispatcher->shutDownThreads();
723
}
724
}
725
726
/**
727
* Free any resources allocated by gcInitializeWithDefaultValues
728
*/
729
void
730
gcCleanupInitializeDefaults(OMR_VM* omrVM)
731
{
732
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVM);
733
MM_EnvironmentBase env(omrVM);
734
J9JavaVM *vm = (J9JavaVM*) omrVM->_language_vm;
735
736
if (NULL == extensions) {
737
return;
738
}
739
740
if (vm->defaultMemorySpace) {
741
reportPrivateHeapDelete(vm, vm->defaultMemorySpace);
742
}
743
744
/* defaultMemorySpace is cleared as part of configuration tear down */
745
if (NULL != extensions->configuration) {
746
extensions->configuration->kill(&env);
747
}
748
749
extensions->kill(&env);
750
751
omrVM->_gcOmrVMExtensions = NULL;
752
((J9JavaVM*)omrVM->_language_vm)->gcExtensions = NULL;
753
}
754
755
static UDATA
756
normalizeParameter(UDATA parameter, UDATA numerator, UDATA denominator, UDATA max, UDATA min, UDATA roundTo)
757
{
758
UDATA value = (parameter / denominator) * numerator;
759
760
value = MM_Math::roundToCeiling(roundTo, value);
761
value = (value > max) ? max : value;
762
value = (value < min) ? min : value;
763
764
return value;
765
}
766
767
/**
768
* Calculate the memory parameter value.
769
* Calculate and store memory parameters in destinationStruct based on the data found in sourceStruct
770
* @param parameterInfo pointer to parameter info structure
771
* @param memoryParameters array of parameter values
772
*/
773
static void
774
gcCalculateAndStoreMemoryParameter(MM_GCExtensions *destinationStruct, MM_GCExtensions *sourceStruct, const J9GcMemoryParameter *parameterInfo, IDATA *memoryParameters)
775
{
776
if (-1 == memoryParameters[parameterInfo->optionName]) {
777
/* Only parameters not specified by the user may be massaged based on other values. */
778
destinationStruct->*(parameterInfo->fieldOffset) =
779
normalizeParameter(sourceStruct->*(parameterInfo->valueBaseOffset),
780
parameterInfo->scaleNumerator,
781
parameterInfo->scaleDenominator,
782
parameterInfo->valueMax,
783
parameterInfo->valueMin,
784
parameterInfo->valueRound);
785
}
786
}
787
788
/**
789
* Calculate memory parameter values.
790
* Only parameters not specified by the user may be massaged based on other values.
791
* @param memoryParameters array of parameter values
792
*/
793
static jint
794
gcInitializeCalculatedValues(J9JavaVM *javaVM, IDATA* memoryParameters)
795
{
796
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
797
jint result = JNI_OK;
798
799
/* Set initial Xms value: 8M
800
*
801
* Note: Will need to verify Xms/Xmos/Xmns fit in user provided values of Xmx.
802
* This used to be for free, calculations based on Xmx, now it is a manual check
803
* in setConfigurationSpecificMemoryParameters
804
*/
805
UDATA initialXmsValueMax = 8 * 1024 * 1024;
806
UDATA initialXmsValueMin = 8 * 1024 * 1024;
807
if (extensions->isSegregatedHeap() || extensions->isMetronomeGC()) {
808
/* TODO aryoung: eventually segregated heaps will allow heap expansion, although metronome
809
* itself will still require a fully expanded heap on startup
810
*/
811
initialXmsValueMax = J9_MEMORY_MAX;
812
initialXmsValueMin = UDATA_MAX;
813
} else if (J9_ARE_ANY_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_TUNE_THROUGHPUT)) {
814
/* For -Xtune:throughput we want to set Xms=Xmx */
815
initialXmsValueMax = extensions->memoryMax;
816
initialXmsValueMin = extensions->memoryMax;
817
}
818
819
/**
820
* GC memory parameters to be store in GCExtensions
821
* opt_Xms will be set to initialXmsValue due to valueMax and valueMin being set
822
* opt_Xmns will be 50% of Xms
823
* opt_Xmos will be 50% of Xms
824
*
825
* Note: MM_GCExtensions::newSpaceSize should be set here based on opt_Xmns option
826
*/
827
const struct J9GcMemoryParameter GCExtensionsParameterTable [] = {
828
{ &MM_GCExtensions::initialMemorySize, opt_Xms, initialXmsValueMax, initialXmsValueMin, &MM_GCExtensions::maxSizeDefaultMemorySpace, 1, 1, extensions->regionSize },
829
{ &MM_GCExtensions::minNewSpaceSize, opt_Xmns, (UDATA)-1, 2*MINIMUM_NEW_SPACE_SIZE, &MM_GCExtensions::initialMemorySize, 1, 4, 2*extensions->regionSize },
830
{ &MM_GCExtensions::newSpaceSize, opt_Xmns, (UDATA)-1, 2*MINIMUM_NEW_SPACE_SIZE, &MM_GCExtensions::initialMemorySize, 1, 4, 2*extensions->regionSize },
831
{ &MM_GCExtensions::maxNewSpaceSize, opt_Xmnx, (UDATA)-1, 2*MINIMUM_NEW_SPACE_SIZE, &MM_GCExtensions::maxSizeDefaultMemorySpace, 1, 4, 2*extensions->regionSize },
832
{ &MM_GCExtensions::minOldSpaceSize, opt_Xmos, initialXmsValueMax, MINIMUM_OLD_SPACE_SIZE, &MM_GCExtensions::initialMemorySize, 3, 4, extensions->regionSize },
833
{ &MM_GCExtensions::oldSpaceSize, opt_Xmos, initialXmsValueMax, MINIMUM_OLD_SPACE_SIZE, &MM_GCExtensions::initialMemorySize, 3, 4, extensions->regionSize },
834
{ &MM_GCExtensions::maxOldSpaceSize, opt_Xmox, (UDATA)-1, MINIMUM_OLD_SPACE_SIZE, &MM_GCExtensions::maxSizeDefaultMemorySpace, 1, 1, extensions->regionSize },
835
{ &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 },
836
{ &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 },
837
};
838
839
const IDATA GCExtensionsParameterTableSize = (sizeof(GCExtensionsParameterTable) / sizeof(struct J9GcMemoryParameter));
840
IDATA tableIndex;
841
842
/* Set the values which live in the JavaVM since they can't use the common GCExtensions member pointer approach */
843
if (-1 == memoryParameters[opt_Xmca]) {
844
javaVM->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);
845
}
846
if (-1 == memoryParameters[opt_Xmco]) {
847
javaVM->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);
848
}
849
850
/* Walk the dependency table fixing unspecified parameters to calculated defaults (mapping GCExtensions values to other GCExtensions values) */
851
for(tableIndex=0; tableIndex < GCExtensionsParameterTableSize; tableIndex++) {
852
gcCalculateAndStoreMemoryParameter(extensions, extensions, &(GCExtensionsParameterTable[tableIndex]), memoryParameters);
853
}
854
855
#if defined (J9VM_GC_VLHGC)
856
if (0 == extensions->tarokRememberedSetCardListSize) {
857
uintptr_t cardSize = MM_RememberedSetCard::cardSize(extensions->compressObjectReferences());
858
/* 4% of region size is allocated for region's RSCL memory */
859
extensions->tarokRememberedSetCardListSize = extensions->regionSize * 4 / 100 / cardSize;
860
}
861
862
if (0 == extensions->tarokRememberedSetCardListMaxSize) {
863
/* Individual RSCL can grow up to 8x of its memory size */
864
extensions->tarokRememberedSetCardListMaxSize = 8 * extensions->tarokRememberedSetCardListSize;
865
}
866
867
#endif /* defined (J9VM_GC_VLHGC) */
868
869
/* Number of GC threads must be initialized at this point */
870
Assert_MM_true(0 < extensions->gcThreadCount);
871
872
/* initialize the size of Local Object Buffer */
873
if (0 == extensions->objectListFragmentCount) {
874
extensions->objectListFragmentCount = (4 * extensions->gcThreadCount) + 4;
875
}
876
return result;
877
}
878
879
/**
880
* Verify memory parameters.
881
*
882
* Some configurations do not honour all memory parameters provided by the user. Set these
883
* parameters to default values and make it appear the user did not specify any values for these
884
* parameters. A routine that thus checks for user provided input will not validate these
885
* parameters. Routines that modify configuration specific parameters will need to ensure
886
* they do not modify these same parameters.
887
*
888
* For a flat configuration -Xmn is ignored:
889
* -Xmn/-Xmns are set to 0
890
* -Xmnx is set to -Xmx
891
* memoryParameters structure is modified to make it look like the user did not specify these values.
892
*
893
* @param memoryParameters array of parameter values
894
* @return JNI_OK on success, JNI_ERR on failure
895
*/
896
jint
897
setConfigurationSpecificMemoryParameters(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)
898
{
899
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
900
bool opt_XmsSet = (-1 != memoryParameters[opt_Xms]);
901
bool opt_XmnsSet = (-1 != memoryParameters[opt_Xmns]);
902
bool opt_XmosSet = (-1 != memoryParameters[opt_Xmos]);
903
bool opt_XmnxSet = (-1 != memoryParameters[opt_Xmnx]);
904
905
if (flatConfiguration) {
906
/* Xmns = 0, override fact user may have provided a value */
907
extensions->minNewSpaceSize = 0;
908
extensions->newSpaceSize = 0;
909
extensions->maxNewSpaceSize = 0;
910
memoryParameters[opt_Xmns] = memoryParameters[opt_Xmnx] = memoryParameters[opt_Xmn] = -1;
911
912
extensions->absoluteMinimumOldSubSpaceSize = MINIMUM_VM_SIZE;
913
}
914
915
/* Emulation of sovereign behaviour results in Xmx, and Xms being hardcoded. If a value smaller than
916
* the hardcoded minimum for Xmx is supplied, and this value is less than the hardcoded value of Xms
917
* then Xms, Xmns and Xmos need to be re-calculated.
918
*/
919
/* If Xms was set by the user, then initial guesses for Xmos and Xmns will
920
* be used in final calculations of those values (i.e. the current values
921
* are good enough).
922
*/
923
if (!opt_XmsSet) {
924
if (extensions->initialMemorySize > extensions->maxSizeDefaultMemorySpace) {
925
extensions->initialMemorySize = extensions->maxSizeDefaultMemorySpace;
926
927
if (!opt_XmosSet) {
928
extensions->oldSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->initialMemorySize/2);
929
extensions->oldSpaceSize = MM_Math::roundToFloor(extensions->regionSize, extensions->oldSpaceSize);
930
extensions->oldSpaceSize = (extensions->oldSpaceSize >= extensions->absoluteMinimumOldSubSpaceSize) ? extensions->oldSpaceSize : extensions->absoluteMinimumOldSubSpaceSize;
931
extensions->minOldSpaceSize = extensions->oldSpaceSize;
932
}
933
934
if (!flatConfiguration) {
935
if (!opt_XmnsSet) {
936
extensions->newSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->initialMemorySize/2);
937
extensions->newSpaceSize = MM_Math::roundToFloor(extensions->regionSize, extensions->newSpaceSize);
938
extensions->newSpaceSize = (extensions->newSpaceSize >= (2*extensions->absoluteMinimumNewSubSpaceSize)) ? extensions->newSpaceSize : (2*extensions->absoluteMinimumNewSubSpaceSize);
939
extensions->minNewSpaceSize = extensions->newSpaceSize;
940
}
941
}
942
}
943
}
944
945
if (!flatConfiguration && !opt_XmnxSet) {
946
/* If Xmnx is not set by the user, limit it to the 1/4 of the maximum heap size */
947
extensions->maxNewSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment * 2,extensions->memoryMax / 4);
948
extensions->maxNewSpaceSize = MM_Math::roundToFloor(extensions->regionSize * 2, extensions->maxNewSpaceSize);
949
}
950
return JNI_OK;
951
}
952
953
/**
954
* Verify memory parameters.
955
*
956
* Determine which memory parameter to display to the user in the event of an error.
957
* @param memoryParameters array of parameter values
958
* @return pointer to "-Xmx" or "-XX:MaxRAMPercentage"
959
*/
960
static const char *
961
displayXmxOrMaxRAMPercentage(IDATA* memoryParameters)
962
{
963
if ((-1 != memoryParameters[opt_maxRAMPercent])
964
&& (memoryParameters[opt_Xmx] == memoryParameters[opt_maxRAMPercent])
965
) {
966
return "-Xmx (as set by -XX:MaxRAMPercentage)";
967
} else {
968
return "-Xmx";
969
}
970
}
971
972
/**
973
* Verify memory parameters.
974
*
975
* Determine which memory parameter to display to the user in the event of an error.
976
* @param memoryParameters array of parameter values
977
* @return pointer to "-Xms" or "-XX:InitialRAMPercentage"
978
*/
979
static const char *
980
displayXmsOrInitialRAMPercentage(IDATA* memoryParameters)
981
{
982
if ((-1 != memoryParameters[opt_initialRAMPercent])
983
&& (memoryParameters[opt_Xms] == memoryParameters[opt_initialRAMPercent])
984
) {
985
return "-Xms (as set by -XX:InitialRAMPercentage)";
986
} else {
987
return "-Xms";
988
}
989
}
990
991
/**
992
* Verify memory parameters.
993
*
994
* Determine which memory parameter to display to the user in the event of an error.
995
* @param memoryParameters array of parameter values
996
* @return pointer to "-Xmn" or "-Xmns"
997
*/
998
const char *
999
displayXmnOrXmns(IDATA* memoryParameters)
1000
{
1001
return (memoryParameters[opt_Xmn] == memoryParameters[opt_Xmns]) ? "-Xmn" : "-Xmns";
1002
}
1003
1004
/**
1005
* Verify memory parameters.
1006
*
1007
* Determine which memory parameter to display to the user in the event of an error.
1008
* @param memoryParameters array of parameter values
1009
* @return pointer to "-Xmn" or "-Xmnx" *
1010
*/
1011
const char *
1012
displayXmnOrXmnx(IDATA* memoryParameters)
1013
{
1014
return (memoryParameters[opt_Xmn] == memoryParameters[opt_Xmnx]) ? "-Xmn" : "-Xmnx";
1015
}
1016
1017
/**
1018
* Verify memory parameters.
1019
*
1020
* Determine which memory parameter to display to the user in the event of an error.
1021
* @param memoryParameters array of parameter values
1022
* @return pointer to "-Xmo" or "-Xmos" *
1023
*/
1024
const char *
1025
displayXmoOrXmos(IDATA* memoryParameters)
1026
{
1027
return (memoryParameters[opt_Xmo] == memoryParameters[opt_Xmos]) ? "-Xmo" : "-Xmos";
1028
}
1029
1030
/**
1031
* Verify memory parameters.
1032
*
1033
* Determine which memory parameter to display to the user in the event of an error.
1034
* @param memoryParameters array of parameter values
1035
* @return pointer to "-Xmo" or "-Xmox"
1036
*/
1037
const char *
1038
displayXmoOrXmox(IDATA* memoryParameters)
1039
{
1040
return (memoryParameters[opt_Xmo] == memoryParameters[opt_Xmox]) ? "-Xmo" : "-Xmox";
1041
}
1042
/**
1043
* Verify memory parameters.
1044
*
1045
* Ensure that Xmx is larger than the minimum size.
1046
* Ensure that Xmdx is larger than the minimum size, less than Xmx.
1047
*
1048
* The following is guaranteed after this method
1049
*
1050
* 1/ minimumConfigurationSize <= Xmx
1051
* 2/ minimumConfigurationSize <= Xmdx <= Xmx
1052
*
1053
* @param javaVM The javaVM
1054
* @param memoryParameters Memory options provided by user
1055
* @param flatConfiguration True if running without scavenger
1056
* @param minimumSize The size for lower bound testing
1057
* @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 ...)
1058
* @param memoryOption2 See memoryOption1
1059
*
1060
* @return JNI_OK on success, JNI_ERR on failure.
1061
* @note error message is printed out indicating type of failure
1062
*/
1063
static jint
1064
gcInitializeXmxXmdxVerification(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration, UDATA minimumSizeValue, const char *memoryOption1, const char *memoryOption2)
1065
{
1066
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
1067
1068
/* Error reporting */
1069
const char *subSpaceTooLargeOption;
1070
1071
bool opt_XmxSet = (-1 != memoryParameters[opt_Xmx]);
1072
bool opt_XmdxSet = (-1 != memoryParameters[opt_Xmdx]);
1073
PORT_ACCESS_FROM_JAVAVM(javaVM);
1074
1075
/* Align both Xmx and Xmdx */
1076
extensions->memoryMax = MM_Math::roundToFloor(extensions->heapAlignment, extensions->memoryMax);
1077
extensions->maxSizeDefaultMemorySpace = MM_Math::roundToFloor(extensions->heapAlignment, extensions->maxSizeDefaultMemorySpace);
1078
extensions->memoryMax = MM_Math::roundToFloor(extensions->regionSize, extensions->memoryMax);
1079
extensions->maxSizeDefaultMemorySpace = MM_Math::roundToFloor(extensions->regionSize, extensions->maxSizeDefaultMemorySpace);
1080
1081
#if defined (OMR_GC_COMPRESSED_POINTERS)
1082
if (extensions->compressObjectReferences()) {
1083
if (extensions->shouldAllowShiftingCompression) {
1084
if (extensions->shouldForceSpecifiedShiftingCompression) {
1085
extensions->heapCeiling = NON_SCALING_LOW_MEMORY_HEAP_CEILING << extensions->forcedShiftingCompressionAmount;
1086
} else {
1087
extensions->heapCeiling = LOW_MEMORY_HEAP_CEILING;
1088
}
1089
} else {
1090
extensions->heapCeiling = NON_SCALING_LOW_MEMORY_HEAP_CEILING;
1091
}
1092
1093
#if defined(J9ZOS39064)
1094
{
1095
/*
1096
* In order to support Compressed References ZOS should support one of:
1097
* - 2_TO_64 to support heaps allocation below 64GB
1098
* - 2_TO_32 to support heaps allocation below 32GB
1099
*/
1100
U_64 maxHeapForCR = zosGetMaxHeapSizeForCR();
1101
if (0 == maxHeapForCR) {
1102
/* Redirector should not allow to run Compressed References JVM if options are not available */
1103
Assert_MM_unreachable();
1104
/* Fail to initialize if assertions are off */
1105
return JNI_ERR;
1106
}
1107
1108
/* Adjust heap ceiling value if it is necessary */
1109
if (extensions->heapCeiling > maxHeapForCR) {
1110
extensions->heapCeiling = maxHeapForCR;
1111
}
1112
}
1113
#endif /* defined(J9ZOS39064) */
1114
1115
if (extensions->memoryMax > (extensions->heapCeiling - J9GC_COMPRESSED_POINTER_NULL_REGION_SIZE)) {
1116
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTION_OVERFLOW, displayXmxOrMaxRAMPercentage(memoryParameters));
1117
return JNI_ERR;
1118
}
1119
}
1120
#endif /* defined (OMR_GC_COMPRESSED_POINTERS) */
1121
1122
/* Verify Xmx is too small */
1123
if (extensions->memoryMax < minimumSizeValue) {
1124
if (NULL == memoryOption1) {
1125
memoryOption1 = displayXmxOrMaxRAMPercentage(memoryParameters);
1126
memoryOption2 = NULL;
1127
goto _subSpaceTooSmallForValue;
1128
} else {
1129
if (opt_XmxSet) {
1130
subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);
1131
goto _subSpaceTooLarge;
1132
}
1133
goto _subSpaceTooLargeForHeap;
1134
}
1135
}
1136
1137
#if defined(J9ZTPF)
1138
/* Only if Xmx is specified, verify the value doesn't go over usable memory. */
1139
if (opt_XmxSet) {
1140
if (extensions->memoryMax > extensions->usablePhysicalMemory) {
1141
memoryOption1 = "-Xmx";
1142
memoryOption2 = NULL;
1143
goto _subSpaceTooLargeForHeap;
1144
}
1145
}
1146
#endif /* defined(J9ZTPF) */
1147
1148
/* Verify Xmdx is not too small, or too big */
1149
if (opt_XmdxSet) {
1150
if (extensions->maxSizeDefaultMemorySpace < minimumSizeValue) {
1151
if (NULL == memoryOption1) {
1152
memoryOption1 = "-Xmdx";
1153
memoryOption2 = NULL;
1154
goto _subSpaceTooSmallForValue;
1155
} else {
1156
subSpaceTooLargeOption = "-Xmdx";
1157
goto _subSpaceTooLarge;
1158
}
1159
}
1160
1161
if (extensions->maxSizeDefaultMemorySpace > extensions->memoryMax) {
1162
memoryOption1 = "-Xmdx";
1163
memoryOption2 = NULL;
1164
if (opt_XmxSet) {
1165
subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);
1166
goto _subSpaceTooLarge;
1167
}
1168
goto _subSpaceTooLargeForHeap;
1169
}
1170
} else {
1171
/* Special case for Xmdx. The Xmdx value is calculated as a fraction of Xmx.
1172
* It is possible for small enough values of Xmx that Xmdx will be less than
1173
* the size of a subSpace. Ensure Xmdx is at least as large as the configuration
1174
* size in this case. Xmx is already known to be larger than that size.
1175
*/
1176
if (extensions->maxSizeDefaultMemorySpace < minimumSizeValue) {
1177
extensions->maxSizeDefaultMemorySpace = minimumSizeValue;
1178
}
1179
}
1180
1181
/* Still need to verify the minimum size of Xmx/Xmdx is not less than the required
1182
* minimum subSpace size (oldSpace/NewSpace). Do this verification after those minimum
1183
* values are verified.
1184
*/
1185
return JNI_OK;
1186
1187
_subSpaceTooSmallForValue:
1188
{
1189
const char *qualifier = NULL;
1190
qualifiedSize(&minimumSizeValue, &qualifier);
1191
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_SMALL_FOR_VALUE, memoryOption1, minimumSizeValue, qualifier);
1192
return JNI_ERR;
1193
}
1194
1195
_subSpaceTooLarge:
1196
if (NULL == memoryOption2) {
1197
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE, memoryOption1, subSpaceTooLargeOption);
1198
} else {
1199
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE, memoryOption1, memoryOption2, subSpaceTooLargeOption);
1200
}
1201
return JNI_ERR;
1202
1203
_subSpaceTooLargeForHeap:
1204
if (NULL == memoryOption2) {
1205
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE_FOR_HEAP, memoryOption1);
1206
} else {
1207
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE_FOR_HEAP, memoryOption1, memoryOption2);
1208
}
1209
return JNI_ERR;
1210
}
1211
1212
/**
1213
* Verify memory parameters.
1214
*
1215
* For each memory parameter specified by the user verify the following conditions independent
1216
* of any other memory parameter: alignment, minimum size, maximum size.
1217
*
1218
* Maximum size is compared against either Xmx, Xmdx or Xms. The largest of these values
1219
* that is set by the user is used where applicable.
1220
*
1221
* For all user provided memory parameters, the following are guaranteed upon completion
1222
*
1223
* 1/ minimumConfigurationSize <= Xms <= Xmdx
1224
* 2/ absoluteMinimumOldSubSpaceSize <= Xmos <= Xmox <= Xms|Xmdx|Xmx
1225
* 3/ absoluteMinimumNewSubSpaceSize <= Xmns <= Xmnx <= Xms|Xmdx|Xmx
1226
*
1227
* @return JNI_OK on success, JNI_ERR on failure.
1228
* @note error message is printed out indicating type of failure
1229
*/
1230
jint
1231
independentMemoryParameterVerification(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)
1232
{
1233
PORT_ACCESS_FROM_JAVAVM(javaVM);
1234
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
1235
1236
UDATA minimumSizeValue; /* For displaying error message */
1237
const char *memoryOption = NULL;
1238
const char *memoryOption2 = NULL;
1239
const char *subSpaceTooLargeOption;
1240
1241
/* Maximum size for Xmdx, Xmox, Xmnx */
1242
UDATA maximumXmdxValue = extensions->memoryMax;
1243
const char *maximumXmdxValueParameter = NULL;
1244
1245
/* Maximum size for Xms, Xmos, Xmns */
1246
UDATA maximumXmsValue = extensions->memoryMax;
1247
const char *maximumXmsValueParameter = NULL;
1248
UDATA XmsMinimumValue = 0;
1249
1250
bool opt_XmxSet = (-1 != memoryParameters[opt_Xmx]);
1251
bool opt_XmdxSet = (-1 != memoryParameters[opt_Xmdx]);
1252
bool opt_XmsSet = (-1 != memoryParameters[opt_Xms]);
1253
bool opt_XmnsSet = (-1 != memoryParameters[opt_Xmns]);
1254
bool opt_XmnxSet = (-1 != memoryParameters[opt_Xmnx]);
1255
bool opt_XmosSet = (-1 != memoryParameters[opt_Xmos]);
1256
bool opt_XmoxSet = (-1 != memoryParameters[opt_Xmox]);
1257
bool opt_XsoftmxSet = (-1 != memoryParameters[opt_Xsoftmx]);
1258
1259
/* These values will be reset if Xmos/Xmns are user provided.
1260
* Initially minimum size to verify Xmos/Xmns input.
1261
*
1262
* Can't use extensions->minNewSpaceSize as that value is pre-calculated
1263
* to be a realistic value; a valid user input value may be less than this
1264
* calculated value, but it must be greater than the minimum value.
1265
*/
1266
UDATA oldSpaceSizeMinimum = extensions->absoluteMinimumOldSubSpaceSize;
1267
UDATA newSpaceSizeMinimum = 2*extensions->absoluteMinimumNewSubSpaceSize;
1268
1269
/* Xmx and Xmdx have already been verified
1270
* Need to set maximumXmdxValue and maximumXmsValue as per Xmdx settings
1271
* Can not verify minimum values until Xmns/Xmos have been verified.
1272
*/
1273
if (opt_XmxSet) {
1274
maximumXmdxValueParameter = displayXmxOrMaxRAMPercentage(memoryParameters);
1275
maximumXmsValueParameter = displayXmxOrMaxRAMPercentage(memoryParameters);
1276
}
1277
1278
if (opt_XmdxSet) {
1279
/* When comparing to maximum boundary use the Xmdx value */
1280
maximumXmdxValue = extensions->maxSizeDefaultMemorySpace;
1281
maximumXmdxValueParameter = "-Xmdx";
1282
1283
/* When comparing initialMemorySizes to maximum boundary, use the Xmdx value
1284
* Just need to reset the reported parameter, value is currently set to Xmdx
1285
*/
1286
maximumXmsValue = extensions->maxSizeDefaultMemorySpace;
1287
maximumXmsValueParameter = "-Xmdx";
1288
}
1289
1290
/* Align Xms, verify it is not too large */
1291
if (opt_XmsSet) {
1292
extensions->initialMemorySize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->initialMemorySize);
1293
extensions->initialMemorySize = MM_Math::roundToFloor(extensions->regionSize, extensions->initialMemorySize);
1294
1295
if (flatConfiguration) {
1296
/* Flat configuration Collector can start with one region */
1297
extensions->initialMemorySize = OMR_MAX(extensions->regionSize, extensions->initialMemorySize);
1298
} else {
1299
/* Gencon required at least three regions to start with (one for Tenure and two for Nursery - one for each half) */
1300
extensions->initialMemorySize = OMR_MAX(extensions->regionSize * 3, extensions->initialMemorySize);
1301
}
1302
1303
if (extensions->initialMemorySize > maximumXmsValue) {
1304
memoryOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1305
if (maximumXmsValueParameter) {
1306
subSpaceTooLargeOption = maximumXmsValueParameter;
1307
goto _subSpaceTooLarge;
1308
}
1309
goto _subSpaceTooLargeForHeap;
1310
}
1311
1312
/* When comparing to maximum boundary use the Xms value */
1313
maximumXmsValue = extensions->initialMemorySize;
1314
maximumXmsValueParameter = displayXmsOrInitialRAMPercentage(memoryParameters);
1315
}
1316
1317
/* verify -Xsoftmx is set between -Xms and -Xmx */
1318
if (opt_XsoftmxSet) {
1319
extensions->softMx = MM_Math::roundToFloor(extensions->heapAlignment, extensions->softMx);
1320
extensions->softMx = MM_Math::roundToFloor(extensions->regionSize, extensions->softMx);
1321
1322
if (extensions->softMx > extensions->memoryMax) {
1323
memoryOption = "-Xsoftmx";
1324
goto _subSpaceTooLargeForHeap;
1325
}
1326
1327
if (extensions->softMx < extensions->initialMemorySize) {
1328
memoryOption = "-Xsoftmx";
1329
minimumSizeValue = extensions->initialMemorySize;
1330
goto _subSpaceTooSmallForValue;
1331
}
1332
}
1333
1334
/* Align Xmns, verify it is not too large or too small.
1335
* Defer checking that Xmns <= Xmnx as Xmnx has not been verified yet.
1336
* There are two semi-spaces
1337
*/
1338
if (opt_XmnsSet) {
1339
extensions->newSpaceSize = MM_Math::roundToFloor(2*extensions->heapAlignment, extensions->newSpaceSize);
1340
extensions->newSpaceSize = MM_Math::roundToFloor(2*extensions->regionSize, extensions->newSpaceSize);
1341
extensions->newSpaceSize = OMR_MAX(extensions->regionSize * 2, extensions->newSpaceSize);
1342
1343
if (extensions->newSpaceSize < newSpaceSizeMinimum) {
1344
memoryOption = displayXmnOrXmns(memoryParameters);
1345
minimumSizeValue = newSpaceSizeMinimum; /* display min size */
1346
goto _subSpaceTooSmallForValue;
1347
}
1348
1349
if (extensions->newSpaceSize > maximumXmsValue) {
1350
memoryOption = displayXmnOrXmns(memoryParameters);
1351
if (maximumXmsValueParameter) {
1352
subSpaceTooLargeOption = maximumXmsValueParameter; /* display correct parameter */
1353
goto _subSpaceTooLarge;
1354
}
1355
goto _subSpaceTooLargeForHeap;
1356
}
1357
1358
/* Update newSpaceSizeMinimum */
1359
newSpaceSizeMinimum = extensions->newSpaceSize;
1360
extensions->minNewSpaceSize = extensions->newSpaceSize;
1361
}
1362
1363
/* Align Xmnx, verify it is not too large or too small.
1364
* There are two semi-spaces
1365
*/
1366
if (opt_XmnxSet) {
1367
extensions->maxNewSpaceSize = MM_Math::roundToFloor(2*extensions->heapAlignment, extensions->maxNewSpaceSize);
1368
extensions->maxNewSpaceSize = MM_Math::roundToFloor(2*extensions->regionSize, extensions->maxNewSpaceSize);
1369
1370
if (extensions->maxNewSpaceSize < newSpaceSizeMinimum) {
1371
memoryOption = displayXmnOrXmnx(memoryParameters);
1372
minimumSizeValue = newSpaceSizeMinimum; /* display min size */
1373
goto _subSpaceTooSmallForValue;
1374
}
1375
1376
if (extensions->maxNewSpaceSize > maximumXmdxValue) {
1377
memoryOption = displayXmnOrXmnx(memoryParameters);
1378
if (maximumXmdxValueParameter) {
1379
subSpaceTooLargeOption = maximumXmdxValueParameter;
1380
goto _subSpaceTooLarge;
1381
}
1382
goto _subSpaceTooLargeForHeap;
1383
}
1384
1385
if (opt_XmnsSet && (extensions->maxNewSpaceSize < extensions->newSpaceSize)) {
1386
memoryOption = displayXmnOrXmns(memoryParameters);
1387
subSpaceTooLargeOption = displayXmnOrXmnx(memoryParameters);
1388
goto _subSpaceTooLarge;
1389
}
1390
}
1391
1392
1393
/* Align Xmos, verify it is not too large or too small.
1394
* Defer checking that Xmos < Xmox as Xmox has not been verified yet.
1395
*/
1396
if (opt_XmosSet) {
1397
extensions->oldSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->oldSpaceSize);
1398
extensions->oldSpaceSize = MM_Math::roundToFloor(extensions->regionSize, extensions->oldSpaceSize);
1399
extensions->oldSpaceSize = OMR_MAX(extensions->regionSize, extensions->oldSpaceSize);
1400
1401
if (extensions->oldSpaceSize < oldSpaceSizeMinimum) {
1402
memoryOption = displayXmoOrXmos(memoryParameters);
1403
minimumSizeValue = oldSpaceSizeMinimum;
1404
goto _subSpaceTooSmallForValue;
1405
}
1406
1407
if (extensions->oldSpaceSize > maximumXmsValue) {
1408
memoryOption = displayXmoOrXmos(memoryParameters);
1409
if (maximumXmsValueParameter) {
1410
subSpaceTooLargeOption = maximumXmsValueParameter; /* display correct parameter */
1411
goto _subSpaceTooLarge;
1412
}
1413
goto _subSpaceTooLargeForHeap;
1414
}
1415
1416
/* Update local oldSpaceSizeMinimum */
1417
oldSpaceSizeMinimum = extensions->oldSpaceSize;
1418
extensions->minOldSpaceSize = extensions->oldSpaceSize;
1419
}
1420
1421
/* Align Xmox, verify it is not too large or too small. */
1422
if (opt_XmoxSet) {
1423
extensions->maxOldSpaceSize = MM_Math::roundToFloor(extensions->heapAlignment, extensions->maxOldSpaceSize);
1424
extensions->maxOldSpaceSize = MM_Math::roundToFloor(extensions->regionSize, extensions->maxOldSpaceSize);
1425
1426
if (extensions->maxOldSpaceSize < oldSpaceSizeMinimum) {
1427
/* Display minSubSpace size, or Xmos/Xmox value if both were set */
1428
if (opt_XmosSet) {
1429
subSpaceTooLargeOption = displayXmoOrXmox(memoryParameters);
1430
memoryOption = displayXmoOrXmos(memoryParameters);
1431
goto _subSpaceTooLarge;
1432
}
1433
memoryOption = displayXmoOrXmox(memoryParameters);
1434
minimumSizeValue = oldSpaceSizeMinimum;
1435
goto _subSpaceTooSmallForValue;
1436
}
1437
1438
if (extensions->maxOldSpaceSize > maximumXmdxValue) {
1439
memoryOption = displayXmoOrXmox(memoryParameters);
1440
if (maximumXmdxValueParameter) {
1441
subSpaceTooLargeOption = maximumXmdxValueParameter;
1442
goto _subSpaceTooLarge;
1443
}
1444
goto _subSpaceTooLargeForHeap;
1445
}
1446
1447
if (opt_XmosSet && (extensions->maxOldSpaceSize < extensions->oldSpaceSize)) {
1448
memoryOption = displayXmoOrXmos(memoryParameters);
1449
subSpaceTooLargeOption = displayXmoOrXmox(memoryParameters);
1450
goto _subSpaceTooLarge;
1451
}
1452
1453
}
1454
1455
/* Verify Xmx,Xmdx,Xms are not too small based on minimum oldSpace and newSpace values */
1456
XmsMinimumValue = oldSpaceSizeMinimum;
1457
1458
if (!flatConfiguration) {
1459
XmsMinimumValue += newSpaceSizeMinimum;
1460
}
1461
1462
/* Before verifying Xmx/Xmdx is large enough for user provided values of Xmos/Xmns, create an
1463
* output buffer so the error messages can be displayed in relation to specified memory parameters,
1464
* rather than a random number (the sume of Xmos/Xmns for example). This buffer may never
1465
* be displayed if all values are good.
1466
*
1467
* If the user did not specify either Xmos or Xmns then this buffer will be null, and a number
1468
* will be displayed if Xmx/Xmdx was specified too small.
1469
*/
1470
if (opt_XmosSet) {
1471
if (opt_XmnsSet) {
1472
memoryOption = displayXmoOrXmos(memoryParameters);
1473
memoryOption2 = displayXmnOrXmns(memoryParameters);
1474
} else {
1475
memoryOption = displayXmoOrXmos(memoryParameters);
1476
}
1477
} else {
1478
if (opt_XmnsSet) {
1479
memoryOption = displayXmnOrXmns(memoryParameters);
1480
}
1481
}
1482
1483
/* Will display error message with size error. For example if the combination of Xmos/Xmns is greater
1484
* than the specified Xmdx value, says Xmdx is too small, must be at least xxx bytes, rather than
1485
* the Sum of Xmos + Xmns is too large for Xmdx. It is correct, just possibly confusing
1486
*/
1487
if (gcInitializeXmxXmdxVerification(javaVM, memoryParameters, flatConfiguration, XmsMinimumValue, memoryOption, memoryOption2) != JNI_OK) {
1488
return JNI_ERR;
1489
}
1490
1491
if (opt_XmsSet && (extensions->initialMemorySize < XmsMinimumValue)) {
1492
if (NULL == memoryOption) {
1493
memoryOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1494
minimumSizeValue = XmsMinimumValue; /* display min size */
1495
goto _subSpaceTooSmallForValue;
1496
} else {
1497
subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1498
goto _subSpaceTooLarge;
1499
}
1500
}
1501
1502
/* Align Xmoi if set by the user */
1503
if (extensions->allocationIncrementSetByUser) {
1504
extensions->allocationIncrement = MM_Math::roundToCeiling(extensions->heapAlignment, extensions->allocationIncrement);
1505
extensions->allocationIncrement = MM_Math::roundToCeiling(extensions->regionSize, extensions->allocationIncrement);
1506
}
1507
1508
#if defined(OMR_GC_COMPRESSED_POINTERS)
1509
if (J9JAVAVM_COMPRESS_OBJECT_REFERENCES(javaVM)) {
1510
/* Align the Xmcrs if necessary */
1511
extensions->suballocatorInitialSize = MM_Math::roundToCeiling(SUBALLOCATOR_ALIGNMENT, extensions->suballocatorInitialSize);
1512
}
1513
#endif /* defined(OMR_GC_COMPRESSED_POINTERS) */
1514
1515
return JNI_OK;
1516
1517
_subSpaceTooSmallForValue:
1518
{
1519
const char *qualifier = NULL;
1520
qualifiedSize(&minimumSizeValue, &qualifier);
1521
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_SMALL_FOR_VALUE, memoryOption, minimumSizeValue, qualifier);
1522
return JNI_ERR;
1523
}
1524
1525
_subSpaceTooLarge:
1526
if (NULL == memoryOption2) {
1527
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE, memoryOption, subSpaceTooLargeOption);
1528
} else {
1529
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE, memoryOption, memoryOption2, subSpaceTooLargeOption);
1530
}
1531
return JNI_ERR;
1532
1533
_subSpaceTooLargeForHeap:
1534
if (NULL == memoryOption2) {
1535
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE_FOR_HEAP, memoryOption);
1536
} else {
1537
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE_FOR_HEAP, memoryOption, memoryOption2);
1538
}
1539
return JNI_ERR;
1540
1541
}
1542
1543
/**
1544
* Compares a potentially specified parameter value against a given limit value
1545
* @param toTest[in] The parameter to test
1546
* @param maximum[in] The maximum against which toTest must be compared
1547
* @return true if the given parameter toTest is either unspecified or not greater than the given fixed maximum
1548
*/
1549
static bool
1550
isLessThanEqualOrUnspecifiedAgainstFixed(MM_UserSpecifiedParameterUDATA *toTest, UDATA maximum)
1551
{
1552
bool isSafe = true;
1553
if (toTest->_wasSpecified) {
1554
isSafe = (toTest->_valueSpecified <= maximum);
1555
}
1556
return isSafe;
1557
}
1558
1559
/**
1560
* Compares two potentially specified parameter values against to ensure that they have the permitted relative values
1561
* @param minimum[in] The parameter which, if specified, must be no greater than maximum
1562
* @param maximum[in] The parameter which, if specified, must be no less than maximum
1563
* @return true if not both of the parameters are specified or minimum is no greater than maximum
1564
*/
1565
static bool
1566
isLessThanEqualOrUnspecifiedAgainstOption(MM_UserSpecifiedParameterUDATA *minimum, MM_UserSpecifiedParameterUDATA *maximum)
1567
{
1568
bool isSafe = true;
1569
if (minimum->_wasSpecified && maximum->_wasSpecified) {
1570
isSafe = (minimum->_valueSpecified <= maximum->_valueSpecified);
1571
}
1572
return isSafe;
1573
}
1574
1575
/**
1576
* Verify memory parameters.
1577
*
1578
* For all user set values verify that the provided values are valid for all configurations.
1579
* Since individual verification has already occurred, need only verify that combinations are
1580
* correct. For example if Xmns + Xmos = Xms.
1581
*
1582
* Recalculate non user specified values if required.
1583
*
1584
* @return JNI_OK on success, JNI_ERR on failure.
1585
* @note error message is printed out indicating type of failure
1586
*/
1587
jint
1588
combinationMemoryParameterVerification(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)
1589
{
1590
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
1591
1592
/* For displaying error messages */
1593
const char *memoryOption = NULL;
1594
const char *memoryOption2 = NULL;
1595
const char *subSpaceTooLargeOption = NULL;
1596
const char *subSpaceTooSmallOption = NULL;
1597
const char *memoryOptionMinimumDifference = NULL;
1598
float minValue, maxValue;
1599
UDATA minimumSizeValue;
1600
1601
/* The absolute maximum value that Xms can take, and what memory parameter set it (Xmx/Xmdx/Xms) */
1602
UDATA maximumXmsValue;
1603
const char *maximumXmsValueParameter = NULL;
1604
1605
/* Bitmap of memory parameters set by the user */
1606
UDATA setMemoryParameters;
1607
bool opt_XmxSet = (-1 != memoryParameters[opt_Xmx]);
1608
bool opt_XmdxSet = (-1 != memoryParameters[opt_Xmdx]);
1609
bool opt_XmsSet = (-1 != memoryParameters[opt_Xms]);
1610
bool opt_XmnsSet = (-1 != memoryParameters[opt_Xmns]);
1611
bool opt_XmnxSet = (-1 != memoryParameters[opt_Xmnx]);
1612
bool opt_XmosSet = (-1 != memoryParameters[opt_Xmos]);
1613
bool opt_XmoxSet = (-1 != memoryParameters[opt_Xmox]);
1614
bool opt_XsoftmxSet = (-1 != memoryParameters[opt_Xsoftmx]);
1615
bool opt_XmcrsSet = (-1 != memoryParameters[opt_Xmcrs]);
1616
1617
PORT_ACCESS_FROM_JAVAVM(javaVM);
1618
1619
/* User specified combinations of Xmdx and Xms */
1620
setMemoryParameters = NONE;
1621
if (opt_XmdxSet) {
1622
setMemoryParameters |= XMDX;
1623
}
1624
if (opt_XmsSet) {
1625
setMemoryParameters |= XMS;
1626
}
1627
1628
/* Determine maximumXmsValue.
1629
* Verify Xmdx >= Xms where applicable
1630
*/
1631
switch (setMemoryParameters) {
1632
case XMDX_XMS:
1633
/* Xmdx, Xms - already verified
1634
*/
1635
assume0(extensions->maxSizeDefaultMemorySpace <= extensions->memoryMax);
1636
assume0(extensions->initialMemorySize <= extensions->maxSizeDefaultMemorySpace);
1637
1638
maximumXmsValue = extensions->initialMemorySize;
1639
maximumXmsValueParameter = displayXmsOrInitialRAMPercentage(memoryParameters);
1640
break;
1641
1642
case XMDX:
1643
/* Xmdx, ^Xms - verification required
1644
* adjust Xms if necessary
1645
*/
1646
if (extensions->initialMemorySize > extensions->maxSizeDefaultMemorySpace) {
1647
extensions->initialMemorySize = extensions->maxSizeDefaultMemorySpace;
1648
}
1649
1650
maximumXmsValue = extensions->maxSizeDefaultMemorySpace;
1651
maximumXmsValueParameter = "-Xmdx";
1652
break;
1653
1654
case XMS:
1655
/* ^Xmdx, Xms - verification required
1656
* adjust Xmdx if necessary
1657
*/
1658
if (extensions->initialMemorySize > extensions->maxSizeDefaultMemorySpace) {
1659
extensions->maxSizeDefaultMemorySpace = extensions->initialMemorySize;
1660
}
1661
1662
maximumXmsValue = extensions->initialMemorySize;
1663
maximumXmsValueParameter = displayXmsOrInitialRAMPercentage(memoryParameters);
1664
break;
1665
1666
case NONE:
1667
/* ^Xmdx, ^Xms - both calculated, verification not required
1668
*/
1669
assume0(extensions->maxSizeDefaultMemorySpace <= extensions->memoryMax);
1670
assume0(extensions->initialMemorySize <= extensions->maxSizeDefaultMemorySpace);
1671
1672
maximumXmsValue = extensions->memoryMax;
1673
if (opt_XmxSet) {
1674
maximumXmsValueParameter = displayXmxOrMaxRAMPercentage(memoryParameters);
1675
}
1676
break;
1677
1678
default:
1679
j9tty_printf(PORTLIB, "Internal GC error %p\n", setMemoryParameters); /* No NLS */
1680
assume0(0); /* should never get here */
1681
return JNI_ERR;
1682
break;
1683
}
1684
1685
/* It is now known that for all Xms <= Xmdx <= Xmx for all scenarios (user set or not)
1686
* It is also known what the absolute maximum value for Xmos + Xmns (maximumXmsValue).
1687
* Further it is known which user set parameter that maximum value is dictated by (maximumXmsValueParameter).
1688
*
1689
* First deal with the flat configuration. In this configuration Xmos = Xms, unless the
1690
* user has specified values. Xmns is 0.
1691
*/
1692
if (flatConfiguration) {
1693
/* User specified combinations of Xms and Xmos
1694
*/
1695
setMemoryParameters = NONE;
1696
if (opt_XmsSet) {
1697
setMemoryParameters |= XMS;
1698
}
1699
if (opt_XmosSet) {
1700
setMemoryParameters |= XMOS;
1701
}
1702
1703
/* Following the switch statement memory parameters not set by the user
1704
* will be reset as required
1705
*/
1706
switch (setMemoryParameters) {
1707
case XMS_XMOS:
1708
/* Previously verified that
1709
* 1/ Xms <= Xmx
1710
* 2/ Xms <= Xmdx, if Xmdx was specified
1711
* 3/ Xmos <= Xms
1712
* 4/ Xmos <= Xmnx, if Xmnx was specified
1713
*
1714
* Enforce Xms = Xmos
1715
*/
1716
if (extensions->oldSpaceSize != extensions->initialMemorySize) {
1717
memoryOption = displayXmoOrXmos(memoryParameters);
1718
memoryOption2 = displayXmsOrInitialRAMPercentage(memoryParameters);
1719
goto _subSpaceNotEqualError;
1720
}
1721
break;
1722
1723
case XMS:
1724
/* Previously verified
1725
* 1/ Xms <= Xmx
1726
* 2/ Xms <= Xmdx, if Xmdx was specified
1727
*
1728
* Set Xmos = Xms, (Enforce Xms = Xmos)
1729
* Ensure Xmos <= Xmox, if Xmox was specified
1730
*/
1731
if (extensions->isSegregatedHeap() || extensions->isMetronomeGC()) {
1732
/* TODO aryoung: eventually segregated heaps will allow heap expansion, although metronome
1733
* itself will still require a fully expanded heap on startup */
1734
#if defined(J9VM_GC_REALTIME) || defined(J9VM_GC_SEGREGATED_HEAP)
1735
if (extensions->initialMemorySize != extensions->memoryMax) {
1736
/* Ignore the specified -Xms value.
1737
* Override it too, so that verbose:sizes displays correctly the actual value.
1738
*/
1739
extensions->initialMemorySize = extensions->memoryMax;
1740
/* Sometime in future, we may want to give a hard error, instead.
1741
memoryOption = "-Xms";
1742
memoryOption2 = "-Xmx";
1743
goto _subSpaceNotEqualError;
1744
*/
1745
}
1746
#endif /* defined(J9VM_GC_REALTIME) || defined(J9VM_GC_SEGREGATED_HEAP) */
1747
}
1748
1749
extensions->oldSpaceSize = extensions->initialMemorySize;
1750
extensions->minOldSpaceSize = extensions->initialMemorySize;
1751
1752
if (opt_XmoxSet && (extensions->oldSpaceSize > extensions->maxOldSpaceSize)) {
1753
memoryOption = displayXmoOrXmox(memoryParameters);
1754
subSpaceTooSmallOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1755
goto _subSpaceTooSmall;
1756
}
1757
break;
1758
1759
case XMOS:
1760
/* Previously verified
1761
* 1/ Xmos <= Xmx
1762
* 2/ Xmos <= Xmdx, if Xmdx was specified
1763
* 3/ Xmos <= Xmnx, if Xmnx was specified
1764
*
1765
* Nothing left to do
1766
*/
1767
1768
break;
1769
1770
case NONE:
1771
/* Previously ensured that Xms is <= Xmdx <= Xmx
1772
* Set Xmo = Xms for sovereign compliance
1773
*/
1774
extensions->oldSpaceSize = extensions->initialMemorySize;
1775
extensions->minOldSpaceSize = extensions->initialMemorySize;
1776
break;
1777
1778
default:
1779
j9tty_printf(PORTLIB, "Internal GC error %p\n", setMemoryParameters); /* No NLS */
1780
assume0(0); /* should never get here */
1781
return JNI_ERR;
1782
break;
1783
}
1784
1785
/* Reset Xmdx if necessary */
1786
if (!opt_XmdxSet && (extensions->maxSizeDefaultMemorySpace < extensions->oldSpaceSize)) {
1787
extensions->maxSizeDefaultMemorySpace = extensions->oldSpaceSize;
1788
}
1789
1790
/* Reset Xmox if not user provided */
1791
if (!opt_XmoxSet) {
1792
extensions->maxOldSpaceSize = extensions->maxSizeDefaultMemorySpace;
1793
}
1794
1795
/* Reset Xms if not user provided */
1796
if (!opt_XmsSet) {
1797
extensions->initialMemorySize = extensions->oldSpaceSize;
1798
}
1799
1800
/* Reset minimum values if necessary */
1801
if (extensions->minOldSpaceSize > extensions->oldSpaceSize) {
1802
extensions->minOldSpaceSize = extensions->oldSpaceSize;
1803
}
1804
} else {
1805
/* Non flat configurations
1806
* User specified combinations of Xmos and Xmns
1807
*/
1808
setMemoryParameters = NONE;
1809
if (opt_XmosSet) {
1810
setMemoryParameters |= XMOS;
1811
}
1812
if (opt_XmnsSet) {
1813
setMemoryParameters |= XMNS;
1814
}
1815
1816
/* Calculate Xmns/Xmos where required.
1817
* Following the switch statement memory parameters not set by the user
1818
* will be reset as required
1819
*/
1820
UDATA combinedXmosXmnsSize;
1821
UDATA candidateXmosValue;
1822
UDATA candidateXmnsValue;
1823
UDATA newSpaceSizeMinimum = opt_XmnsSet ? extensions->minNewSpaceSize : 2*extensions->absoluteMinimumNewSubSpaceSize;
1824
UDATA oldSpaceSizeMinimum = opt_XmosSet ? extensions->minOldSpaceSize : extensions->absoluteMinimumOldSubSpaceSize;
1825
1826
switch (setMemoryParameters) {
1827
case XMOS_XMNS:
1828
/* Previously verified
1829
* 1/ Xmos <= Xms|Xmdx|Xmx
1830
* 2/ Xmns <= Xms|Xmdx|Xmx
1831
* 3/ Xmos <= Xmox, if Xmox specified
1832
* 4/ Xmns <= Xmnx, if Xmnx specified
1833
*
1834
* Ensure the combined value will fit in the Xms value. It does not matter if Xms was set
1835
* by the user for this test.
1836
*/
1837
if ((extensions->oldSpaceSize + extensions->newSpaceSize) > maximumXmsValue) {
1838
memoryOption = displayXmoOrXmos(memoryParameters);
1839
memoryOption2 = displayXmnOrXmns(memoryParameters);
1840
if (maximumXmsValueParameter) {
1841
subSpaceTooLargeOption = maximumXmsValueParameter;
1842
goto _subSpaceCombinationTooLarge;
1843
}
1844
goto _subSpaceCombinationTooLargeForHeap;
1845
}
1846
1847
assume0(extensions->newSpaceSize = extensions->minNewSpaceSize);
1848
assume0(extensions->oldSpaceSize = extensions->minOldSpaceSize);
1849
1850
/* Enforce Xms = Xmns + Xmos */
1851
if (opt_XmsSet && ((extensions->oldSpaceSize + extensions->newSpaceSize) != extensions->initialMemorySize)) {
1852
memoryOption = displayXmoOrXmos(memoryParameters);
1853
memoryOption2 = displayXmnOrXmns(memoryParameters);
1854
subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1855
goto _subSpaceCombinationNotEqual;
1856
}
1857
break;
1858
1859
case XMOS:
1860
/* Previously verified
1861
* 1/ Xmos <= Xms|Xmdx|Xmx
1862
* 2/ Xmos <= Xmox, if Xmox specified
1863
*
1864
* If Xms is set, then Xmns = Xms - Xmos, else use the previously calculated Xmns value
1865
* Verify calculated value is not too small or too large.
1866
*
1867
* The same algorithm applies to the XMNS case
1868
*/
1869
assume0(extensions->oldSpaceSize = extensions->minOldSpaceSize);
1870
if(opt_XmsSet) {
1871
/* Live with user input */
1872
candidateXmnsValue = extensions->initialMemorySize - extensions->oldSpaceSize;
1873
1874
/* Verify not too small */
1875
if (candidateXmnsValue < newSpaceSizeMinimum) {
1876
memoryOption = displayXmoOrXmos(memoryParameters);
1877
subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1878
goto _subSpaceTooLarge;
1879
}
1880
1881
/* Ensure Xmns <= Xmnx */
1882
if (opt_XmnxSet && (candidateXmnsValue > extensions->maxNewSpaceSize)) {
1883
memoryOption = displayXmnOrXmnx(memoryParameters);
1884
subSpaceTooSmallOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1885
goto _subSpaceTooSmall;
1886
}
1887
1888
/* Enforce Xms = Xmns + Xmos */
1889
if ((extensions->oldSpaceSize + candidateXmnsValue) != extensions->initialMemorySize) {
1890
memoryOption = displayXmoOrXmos(memoryParameters);
1891
subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1892
goto _subSpaceTooLarge;
1893
}
1894
} else {
1895
if (extensions->oldSpaceSize < (6 * extensions->regionSize)) {
1896
/*
1897
* Minimum initial heap size to provide 75/25 split is 8 regions, six for Tenure and two for Nursery.
1898
* If Tenure Initial size is smaller then six regions it is not large enough to provide 75/25 proportion
1899
* So set initial Nursery size to minimum (two regions) and use reminder for Tenure
1900
*/
1901
candidateXmnsValue = extensions->regionSize * 2;
1902
} else {
1903
/* Make Xmns 1/4 of the Xms value, i.e. 1/3 of Xmos. Xms will be reset */
1904
candidateXmnsValue = MM_Math::roundToFloor(extensions->heapAlignment * 2, extensions->oldSpaceSize / 3);
1905
candidateXmnsValue = MM_Math::roundToFloor(extensions->regionSize * 2, candidateXmnsValue);
1906
}
1907
1908
/* Ensure Xmos + Xmns < MaxXms */
1909
if ((extensions->oldSpaceSize + candidateXmnsValue) > maximumXmsValue) {
1910
candidateXmnsValue = maximumXmsValue - extensions->oldSpaceSize;
1911
if (candidateXmnsValue < newSpaceSizeMinimum) {
1912
memoryOption = displayXmoOrXmos(memoryParameters);
1913
if (maximumXmsValueParameter) {
1914
subSpaceTooLargeOption = maximumXmsValueParameter;
1915
goto _subSpaceTooLarge;
1916
}
1917
goto _subSpaceTooLargeForHeap;
1918
}
1919
}
1920
1921
/* Ensure Xmns <= Xmnx */
1922
if (opt_XmnxSet && (candidateXmnsValue > extensions->maxNewSpaceSize)) {
1923
candidateXmnsValue = extensions->maxNewSpaceSize;
1924
}
1925
}
1926
1927
/* Assign Xmns */
1928
extensions->newSpaceSize = candidateXmnsValue;
1929
extensions->minNewSpaceSize = candidateXmnsValue;
1930
break;
1931
1932
case XMNS:
1933
/* Previously verified
1934
* 1/ Xmns <= Xms|Xmdx|Xmx
1935
* 2/ Xmns <= Xmnx, if Xmnx specified
1936
*
1937
* If Xms is set, then Xmos = Xms - Xmns, else use the previously calculated Xmos value
1938
* Verify calculated value is not too small or too large.
1939
*
1940
* The same algorithm applies to the XMOS case
1941
*/
1942
assume0(extensions->newSpaceSize = extensions->minNewSpaceSize);
1943
if(opt_XmsSet) {
1944
/* Live with user input */
1945
candidateXmosValue = extensions->initialMemorySize - extensions->newSpaceSize;
1946
1947
/* Verify not too small */
1948
if (candidateXmosValue < oldSpaceSizeMinimum) {
1949
memoryOption = displayXmnOrXmns(memoryParameters);
1950
subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1951
goto _subSpaceTooLarge;
1952
}
1953
1954
/* Ensure Xmos <= Xmox */
1955
if (opt_XmoxSet && (candidateXmosValue > extensions->maxOldSpaceSize)) {
1956
memoryOption = displayXmoOrXmox(memoryParameters);
1957
subSpaceTooSmallOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1958
goto _subSpaceTooSmall;
1959
}
1960
1961
/* Enforce Xms = Xmns + Xmos */
1962
if ((candidateXmosValue + extensions->newSpaceSize) != extensions->initialMemorySize) {
1963
memoryOption = displayXmnOrXmns(memoryParameters);
1964
subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);
1965
goto _subSpaceTooLarge;
1966
}
1967
} else {
1968
/* Keep the default value. Xms will be reset */
1969
candidateXmosValue = extensions->oldSpaceSize;
1970
1971
/* Ensure Xmos + Xmns < MaxXms */
1972
if ((candidateXmosValue + extensions->newSpaceSize) > maximumXmsValue) {
1973
candidateXmosValue = maximumXmsValue - extensions->newSpaceSize;
1974
if (candidateXmosValue < oldSpaceSizeMinimum) {
1975
memoryOption = displayXmnOrXmns(memoryParameters);
1976
if (maximumXmsValueParameter) {
1977
subSpaceTooLargeOption = maximumXmsValueParameter;
1978
goto _subSpaceTooLarge;
1979
}
1980
goto _subSpaceTooLargeForHeap;
1981
}
1982
}
1983
1984
/* Ensure Xmos <= Xmox */
1985
if (opt_XmoxSet && (candidateXmosValue > extensions->maxOldSpaceSize)) {
1986
candidateXmosValue = extensions->maxOldSpaceSize;
1987
}
1988
}
1989
1990
/* Assign Xmos */
1991
extensions->oldSpaceSize = candidateXmosValue;
1992
extensions->minOldSpaceSize = candidateXmosValue;
1993
break;
1994
1995
case NONE:
1996
/* Know that Xms <= Xmdx <= Xmx
1997
* If Xms is set, split the space 75/25 between Xmos and Xmns
1998
* If Xms not set, try calculated values
1999
* Honour Xmox and Xmnx
2000
*/
2001
if (opt_XmsSet) {
2002
if (extensions->initialMemorySize < (8 * extensions->regionSize)) {
2003
/*
2004
* Minimum initial size to provide 75/25 split is 8 regions:
2005
* (minimum Nursery size is 2 regions and it is 25%)
2006
* If Initial size is smaller then 8 regions it is not large enough to provide 75/25 proportion
2007
* So set initial Nursery size to minimum (two regions)
2008
*/
2009
candidateXmnsValue = extensions->regionSize * 2;
2010
} else {
2011
/* Split the available space 75/25 */
2012
candidateXmnsValue = MM_Math::roundToFloor(extensions->heapAlignment * 2, extensions->initialMemorySize * 1 / 4);
2013
candidateXmnsValue = MM_Math::roundToFloor(extensions->regionSize * 2, candidateXmnsValue);
2014
}
2015
/* Reminder goes to Tenure */
2016
candidateXmosValue = extensions->initialMemorySize - candidateXmnsValue;
2017
} else {
2018
candidateXmnsValue = extensions->newSpaceSize;
2019
candidateXmosValue = extensions->oldSpaceSize;
2020
}
2021
2022
/* Enforce Xmox */
2023
if (opt_XmoxSet && (candidateXmosValue > extensions->maxOldSpaceSize)) {
2024
candidateXmosValue = extensions->maxOldSpaceSize;
2025
if (opt_XmsSet) {
2026
candidateXmnsValue = extensions->initialMemorySize - candidateXmosValue;
2027
}
2028
}
2029
2030
/* Enforce Xmnx */
2031
if (opt_XmnxSet && (candidateXmnsValue > extensions->maxNewSpaceSize)) {
2032
candidateXmnsValue = extensions->maxNewSpaceSize;
2033
2034
/* Since Xmnx just restricted Xmns, the Xmos value must be adjusted.
2035
* It is possible that Xmos will be adjusted above Xmox. This would mean that Xms > Xmox + Xmnx.
2036
* Only adjust Xmos if Xmox is not set, or Xmos will be less than Xmox.
2037
* Otherwise report the error in the check below.
2038
*
2039
* This check is also order dependant with the "Enforce Xmox" if block above.
2040
*/
2041
if ((opt_XmsSet)
2042
&& (!opt_XmoxSet
2043
|| ((extensions->initialMemorySize - candidateXmnsValue) <= extensions->maxOldSpaceSize)))
2044
{
2045
/* If Xmox is not set it will be the maximum size of the heap. This means that the new Xmos value
2046
* could not possibly exceed the Xmox value, and there is no need to adjust the Xmox value.
2047
*/
2048
candidateXmosValue = extensions->initialMemorySize - candidateXmnsValue;
2049
}
2050
}
2051
2052
/* Xmns and Xmos are now set, honouring Xmnx and Xmox.
2053
* Enforce Xms = Xmos + Xmns
2054
*/
2055
if (opt_XmsSet) {
2056
if ((candidateXmosValue + candidateXmnsValue) != extensions->initialMemorySize) {
2057
/* The user specified values for Xmox/Xmnx and Xms prevent us from
2058
* enforcing Xmos + Xmns = Xms
2059
*/
2060
memoryOption = "-Xmox";
2061
memoryOption2 = "-Xmnx";
2062
subSpaceTooSmallOption = displayXmsOrInitialRAMPercentage(memoryParameters);
2063
goto _subSpaceCombinationTooSmall;
2064
}
2065
} else {
2066
/* Know maximumXmsValue is at least minimum configuration size. Give maximum
2067
* space to Xmos
2068
*/
2069
if ((candidateXmosValue + candidateXmnsValue) > maximumXmsValue) {
2070
candidateXmnsValue = OMR_MAX(newSpaceSizeMinimum, maximumXmsValue - candidateXmosValue);
2071
candidateXmosValue = maximumXmsValue - candidateXmnsValue;
2072
2073
/* Verify not too large */
2074
if (opt_XmoxSet && (candidateXmosValue > extensions->maxOldSpaceSize)) {
2075
UDATA delta = extensions->maxOldSpaceSize - candidateXmosValue;
2076
candidateXmosValue -= delta;
2077
candidateXmnsValue += delta;
2078
}
2079
2080
if (opt_XmnxSet && (candidateXmnsValue > extensions->maxNewSpaceSize)) {
2081
/* The user specified values for Xmox/Xmnx prevent us from succeeding */
2082
memoryOption = "-Xmox";
2083
memoryOption2 = "-Xmnx";
2084
if (maximumXmsValueParameter) {
2085
subSpaceTooLargeOption = maximumXmsValueParameter;
2086
goto _subSpaceCombinationTooLarge;
2087
}
2088
goto _subSpaceCombinationTooLargeForHeap;
2089
}
2090
}
2091
}
2092
2093
/* Assign Xmos and Xmns values */
2094
extensions->oldSpaceSize = candidateXmosValue;
2095
extensions->minOldSpaceSize = candidateXmosValue;
2096
extensions->newSpaceSize = candidateXmnsValue;
2097
extensions->minNewSpaceSize = candidateXmnsValue;
2098
break;
2099
2100
default:
2101
j9tty_printf(PORTLIB, "Internal GC error %p\n", setMemoryParameters); /* No NLS */
2102
assume0(0); /* should never get here */
2103
return JNI_ERR;
2104
break;
2105
}
2106
2107
/* The Xmos + Xmns value */
2108
combinedXmosXmnsSize = extensions->oldSpaceSize + extensions->newSpaceSize;
2109
2110
/* Reset Xmdx if applicable */
2111
if (extensions->maxSizeDefaultMemorySpace < combinedXmosXmnsSize) {
2112
if (!opt_XmdxSet) {
2113
extensions->maxSizeDefaultMemorySpace = combinedXmosXmnsSize;
2114
} else {
2115
assume0(0); /* Previous stage checked Xmdx > minConfiguration */
2116
memoryOption = "-Xmdx";
2117
minimumSizeValue = extensions->absoluteMinimumOldSubSpaceSize + (2*extensions->absoluteMinimumNewSubSpaceSize); /* smallest configuration */
2118
goto _subSpaceTooSmallForValue;
2119
}
2120
}
2121
2122
/* Reset Xms if applicable */
2123
if (extensions->initialMemorySize != combinedXmosXmnsSize) {
2124
if (!opt_XmsSet) {
2125
extensions->initialMemorySize = combinedXmosXmnsSize;
2126
} else {
2127
assume0(0); /* Previous stage checked Xms > minConfiguration */
2128
memoryOption = displayXmsOrInitialRAMPercentage(memoryParameters);
2129
minimumSizeValue = extensions->absoluteMinimumOldSubSpaceSize + (2*extensions->absoluteMinimumNewSubSpaceSize); /* smallest configuration */
2130
goto _subSpaceTooSmallForValue;
2131
}
2132
}
2133
2134
/* Reset Xmox if applicable */
2135
if (!opt_XmoxSet) {
2136
/* We know initial Nursery size now so adjust maximum Tenure size */
2137
extensions->maxOldSpaceSize = extensions->memoryMax - extensions->newSpaceSize;
2138
if (extensions->oldSpaceSize > extensions->maxOldSpaceSize) {
2139
extensions->maxOldSpaceSize = extensions->oldSpaceSize;
2140
}
2141
}
2142
2143
/* Reset Xmnx if applicable */
2144
if (extensions->newSpaceSize > extensions->maxNewSpaceSize) {
2145
if (!opt_XmnxSet) {
2146
extensions->maxNewSpaceSize = extensions->newSpaceSize;
2147
} else {
2148
/* Should have already been verified */
2149
assume0(0);
2150
}
2151
}
2152
2153
/* Reset minimum values if necessary */
2154
if (extensions->minOldSpaceSize > extensions->oldSpaceSize) {
2155
extensions->minOldSpaceSize = extensions->oldSpaceSize;
2156
}
2157
2158
if (extensions->minNewSpaceSize > extensions->newSpaceSize) {
2159
extensions->minNewSpaceSize = extensions->newSpaceSize;
2160
}
2161
2162
/* Verify Xmox + Xmnx combination */
2163
if (opt_XmoxSet && opt_XmnxSet) {
2164
if ((extensions->maxOldSpaceSize + extensions->maxNewSpaceSize) > extensions->maxSizeDefaultMemorySpace) {
2165
memoryOption = displayXmoOrXmox(memoryParameters);
2166
memoryOption2 = displayXmnOrXmnx(memoryParameters);
2167
if (opt_XmdxSet) {
2168
subSpaceTooLargeOption = "-Xmdx";
2169
goto _subSpaceCombinationTooLarge;
2170
}
2171
if (opt_XmxSet) {
2172
subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);
2173
goto _subSpaceCombinationTooLarge;
2174
}
2175
goto _subSpaceCombinationTooLargeForHeap;
2176
}
2177
}
2178
} /* of Non flat configurations */
2179
2180
/* Verify that -Xminf is at least 0.05 less than -Xmaxf */
2181
if (extensions->heapFreeMinimumRatioMultiplier + 5 > extensions->heapFreeMaximumRatioMultiplier) {
2182
memoryOption = "-Xminf";
2183
minValue = (float)extensions->heapFreeMinimumRatioMultiplier / 100;
2184
memoryOption2 = "-Xmaxf";
2185
maxValue = (float)extensions->heapFreeMaximumRatioMultiplier / 100;
2186
memoryOptionMinimumDifference = "0.05";
2187
goto _subSpaceCombinationTooClose;
2188
}
2189
2190
#if defined(J9VM_GC_TILTED_NEW_SPACE)
2191
/* Verify that -Xgc:scvTiltRatioMin is no larger than -Xgc:scvTiltRatioMax */
2192
/* NOTE: (stored min) == (100 - specified max) */
2193
if (extensions->survivorSpaceMinimumSizeRatio > extensions->survivorSpaceMaximumSizeRatio) {
2194
memoryOption = "scvTiltRatioMin=";
2195
memoryOption2 = "scvTiltRatioMax=";
2196
goto _combinationLargerThan;
2197
}
2198
#endif /* J9VM_GC_TILTED_NEW_SPACE */
2199
2200
#if defined(J9VM_GC_LARGE_OBJECT_AREA)
2201
/* Verify that -Xloainitial is not less than -Xloaminimum */
2202
if (extensions->largeObjectAreaInitialRatio < extensions->largeObjectAreaMinimumRatio) {
2203
memoryOption = "-Xloainitial";
2204
subSpaceTooSmallOption = "-Xloaminimum";
2205
goto _subSpaceTooSmall;
2206
}
2207
2208
/* Verify that -Xloainitial is less than -Xloamaximum */
2209
if (extensions->largeObjectAreaInitialRatio > extensions->largeObjectAreaMaximumRatio) {
2210
memoryOption = "-Xloamaximum";
2211
subSpaceTooSmallOption = "-Xloainitial";
2212
goto _subSpaceTooSmall;
2213
}
2214
#endif /* J9VM_GC_LARGE_OBJECT_AREA */
2215
2216
#if defined(J9VM_GC_GENERATIONAL)
2217
/* if the user asked for split heaps, apply our additional constraints here */
2218
if (extensions->enableSplitHeap) {
2219
if (opt_XmoxSet) {
2220
if (!opt_XmnxSet) {
2221
/* strong-arm the Xmnx to fit against this Xmox */
2222
extensions->maxNewSpaceSize = extensions->memoryMax - extensions->maxOldSpaceSize;
2223
}
2224
} else {
2225
if (opt_XmnxSet) {
2226
/* strong-arm the Xmox to fit against this Xmnx */
2227
extensions->maxOldSpaceSize = extensions->memoryMax - extensions->maxNewSpaceSize;
2228
} else {
2229
/* neither were set so just correct the old space size since it will be set too big for us to use correctly */
2230
extensions->maxOldSpaceSize = extensions->memoryMax - extensions->maxNewSpaceSize;
2231
}
2232
}
2233
/* Force the immediate expansion to maximum memory */
2234
extensions->initialMemorySize = extensions->memoryMax;
2235
/* Force all the new space sizes to be "locked-in" */
2236
extensions->minNewSpaceSize = extensions->maxNewSpaceSize;
2237
extensions->newSpaceSize = extensions->maxNewSpaceSize;
2238
/* Force all the old space sizes to be "locked-in" */
2239
extensions->minOldSpaceSize = extensions->maxOldSpaceSize;
2240
extensions->oldSpaceSize = extensions->maxOldSpaceSize;
2241
2242
UDATA total = extensions->maxNewSpaceSize + extensions->maxOldSpaceSize;
2243
if (extensions->memoryMax > total) {
2244
goto _subSpaceCombinationTooSmall;
2245
} else if (extensions->memoryMax < total) {
2246
goto _subSpaceCombinationTooLarge;
2247
}
2248
}
2249
#endif /* defined(J9VM_GC_GENERATIONAL) */
2250
2251
#if defined (J9VM_GC_VLHGC)
2252
{
2253
/* calculate our eden size boundaries based on -Xmn inputs */
2254
UDATA mx = extensions->memoryMax;
2255
UDATA ms = extensions->initialMemorySize;
2256
/* first, the error checking */
2257
if (!isLessThanEqualOrUnspecifiedAgainstFixed(&extensions->userSpecifiedParameters._Xmn, mx)) {
2258
memoryOption = "-Xmn";
2259
subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);
2260
goto _subSpaceTooLarge;
2261
}
2262
if (!isLessThanEqualOrUnspecifiedAgainstFixed(&extensions->userSpecifiedParameters._Xmns, mx)) {
2263
memoryOption = "-Xmns";
2264
subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);
2265
goto _subSpaceTooLarge;
2266
}
2267
if (!isLessThanEqualOrUnspecifiedAgainstFixed(&extensions->userSpecifiedParameters._Xmnx, mx)) {
2268
memoryOption = "-Xmnx";
2269
subSpaceTooLargeOption = displayXmxOrMaxRAMPercentage(memoryParameters);
2270
goto _subSpaceTooLarge;
2271
}
2272
if (!isLessThanEqualOrUnspecifiedAgainstOption(&extensions->userSpecifiedParameters._Xmns, &extensions->userSpecifiedParameters._Xmnx)) {
2273
memoryOption = "-Xmnx";
2274
subSpaceTooLargeOption = "-Xmns";
2275
goto _subSpaceTooLarge;
2276
}
2277
if (!isLessThanEqualOrUnspecifiedAgainstFixed(&extensions->userSpecifiedParameters._Xmns, ms)) {
2278
if (!opt_XmsSet) {
2279
ms = extensions->userSpecifiedParameters._Xmns._valueSpecified;
2280
extensions->initialMemorySize = ms;
2281
extensions->oldSpaceSize = extensions->initialMemorySize;
2282
} else {
2283
memoryOption = "-Xmn";
2284
subSpaceTooLargeOption = displayXmsOrInitialRAMPercentage(memoryParameters);
2285
goto _subSpaceTooLarge;
2286
}
2287
}
2288
/* now interpret the values */
2289
UDATA idealEdenMin = 0;
2290
UDATA idealEdenMax = 0;
2291
/*----------------------------------------------------------------
2292
Arguments specified | initial Eden | maxEden
2293
----------------------------------------------------------------
2294
XmnA | OMR_MIN(A,ms) | A
2295
XmnsB | B | B
2296
XmnxC | OMR_MIN(C,ms) | C
2297
XmnsB XmnxC | B | C
2298
(none) | OMR_MIN(mx/4,ms) | mx*3/4
2299
----------------------------------------------------------------*/
2300
if (extensions->userSpecifiedParameters._Xmn._wasSpecified) {
2301
/* earlier error checking would have ensured that we didn't specify -Xmns or -Xmnx with -Xmn */
2302
UDATA mn = extensions->userSpecifiedParameters._Xmn._valueSpecified;
2303
idealEdenMin = OMR_MIN(mn, ms);
2304
idealEdenMax = mn;
2305
} else if (extensions->userSpecifiedParameters._Xmns._wasSpecified) {
2306
UDATA mns = extensions->userSpecifiedParameters._Xmns._valueSpecified;
2307
if (extensions->userSpecifiedParameters._Xmnx._wasSpecified) {
2308
UDATA mnx = extensions->userSpecifiedParameters._Xmnx._valueSpecified;
2309
idealEdenMin = mns;
2310
idealEdenMax = mnx;
2311
} else {
2312
idealEdenMin = mns;
2313
idealEdenMax = mns;
2314
}
2315
} else if (extensions->userSpecifiedParameters._Xmnx._wasSpecified) {
2316
UDATA mnx = extensions->userSpecifiedParameters._Xmnx._valueSpecified;
2317
idealEdenMin = OMR_MIN(mnx, ms);
2318
idealEdenMax = mnx;
2319
} else {
2320
UDATA quarterMax = mx/4;
2321
UDATA threeQuarterMax = quarterMax * 3;
2322
2323
idealEdenMin = OMR_MIN(quarterMax, ms);
2324
idealEdenMax = threeQuarterMax;
2325
}
2326
2327
/* eden size has to be aligned with region size */
2328
idealEdenMin = MM_Math::roundToFloor(extensions->regionSize, idealEdenMin);
2329
idealEdenMax = MM_Math::roundToFloor(extensions->regionSize, idealEdenMax);
2330
2331
/* eden size can not be smaller than 2 * region size
2332
1, during initialization for first collection, it needs 2 regions
2333
2, 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) */
2334
UDATA minSizeForMinEden = extensions->regionSize * 2;
2335
if (minSizeForMinEden > idealEdenMin) {
2336
idealEdenMin = minSizeForMinEden;
2337
}
2338
2339
UDATA numaNodes = extensions->_numaManager.getAffinityLeaderCount() + 1;
2340
2341
/* minimum 2 regions for each numa node */
2342
UDATA minSizeForMaxEden = extensions->regionSize * 2 * numaNodes;
2343
if (minSizeForMaxEden > idealEdenMax) {
2344
idealEdenMax = minSizeForMaxEden;
2345
}
2346
2347
/* 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 */
2348
extensions->tarokIdealEdenMinimumBytes = idealEdenMin;
2349
extensions->tarokIdealEdenMaximumBytes = idealEdenMax;
2350
}
2351
#endif /* J9VM_GC_VLHGC */
2352
2353
if (opt_XmcrsSet) {
2354
/* Silently handle a size mismatch; don't report an error about undocumented options
2355
* if the user has specified the official one. */
2356
if (extensions->suballocatorCommitSize > extensions->suballocatorInitialSize) {
2357
extensions->suballocatorCommitSize = extensions->suballocatorInitialSize;
2358
}
2359
} else {
2360
if (extensions->suballocatorCommitSize > extensions->suballocatorInitialSize) {
2361
memoryOption = "-Xgc:suballocatorCommitSize=";
2362
memoryOption2 = "-Xgc:suballocatorInitialSize=";
2363
goto _combinationLargerThan;
2364
}
2365
}
2366
2367
/* verify -Xsoftmx is set between -Xms and -Xmx */
2368
if (opt_XsoftmxSet) {
2369
if (extensions->softMx > extensions->memoryMax) {
2370
memoryOption = "-Xsoftmx";
2371
goto _subSpaceTooLargeForHeap;
2372
}
2373
2374
if (extensions->softMx < extensions->initialMemorySize) {
2375
memoryOption = "-Xsoftmx";
2376
minimumSizeValue = extensions->initialMemorySize;
2377
goto _subSpaceTooSmallForValue;
2378
}
2379
}
2380
2381
return JNI_OK;
2382
2383
_subSpaceCombinationTooLarge:
2384
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE, memoryOption, memoryOption2, subSpaceTooLargeOption);
2385
return JNI_ERR;
2386
2387
_subSpaceCombinationTooLargeForHeap:
2388
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_LARGE_FOR_HEAP, memoryOption, memoryOption2);
2389
return JNI_ERR;
2390
2391
_subSpaceCombinationNotEqual:
2392
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_NOT_EQUAL, memoryOption, memoryOption2, subSpaceTooLargeOption);
2393
return JNI_ERR;
2394
2395
_subSpaceCombinationTooSmall:
2396
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_SUM_OF_TOO_SMALL, memoryOption, memoryOption2, subSpaceTooSmallOption);
2397
return JNI_ERR;
2398
2399
_subSpaceNotEqualError:
2400
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_NOT_EQUAL_ERROR, memoryOption, memoryOption2);
2401
return JNI_ERR;
2402
2403
_subSpaceTooSmallForValue:
2404
{
2405
const char *qualifier = NULL;
2406
qualifiedSize(&minimumSizeValue, &qualifier);
2407
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_SMALL_FOR_VALUE, memoryOption, minimumSizeValue, qualifier);
2408
return JNI_ERR;
2409
}
2410
2411
_subSpaceTooSmall:
2412
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_SMALL, memoryOption, subSpaceTooSmallOption);
2413
return JNI_ERR;
2414
2415
_subSpaceTooLarge:
2416
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE, memoryOption, subSpaceTooLargeOption);
2417
return JNI_ERR;
2418
2419
_subSpaceTooLargeForHeap:
2420
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_SUBSPACE_TOO_LARGE_FOR_HEAP, memoryOption);
2421
return JNI_ERR;
2422
2423
_subSpaceCombinationTooClose:
2424
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_OPTION_MINIMUM_DIFFERENCE, memoryOption, minValue, memoryOptionMinimumDifference, memoryOption2, maxValue);
2425
return JNI_ERR;
2426
2427
_combinationLargerThan:
2428
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_OPTIONS_MUST_BE_NO_GREATER_THAN, memoryOption, memoryOption2);
2429
return JNI_ERR;
2430
}
2431
2432
/**
2433
* Recalculate Xms, Xmn, Xmo values based on user input.
2434
* @param memoryParameters array of parameter values
2435
* @param flatConfiguration with or without New memory space
2436
* @return JNI_OK if OK
2437
*/
2438
jint
2439
gcCalculateMemoryParameters(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)
2440
{
2441
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
2442
jint result;
2443
2444
/* Handle any configuration specific details. For example in the flat configuration
2445
* the -Xmns/-Xmnx values have no meaning
2446
*/
2447
result = setConfigurationSpecificMemoryParameters(javaVM, memoryParameters, flatConfiguration);
2448
if (JNI_OK != result) {
2449
return result;
2450
}
2451
2452
/* Verify all memory parameters provided by the user are larger than the minimum size
2453
* and smaller than the value of Xmx. Only verify individual parameters, not combinations
2454
*/
2455
result = independentMemoryParameterVerification(javaVM, memoryParameters, flatConfiguration);
2456
if (JNI_OK != result) {
2457
return result;
2458
}
2459
2460
/* Verify the combinations of memory parameters are valid. For example ensure that
2461
* Xms >= Xmns + Xmos for non flat configurations.
2462
*/
2463
result = combinationMemoryParameterVerification(javaVM, memoryParameters, flatConfiguration);
2464
if (JNI_OK != result) {
2465
return result;
2466
}
2467
2468
assume0(extensions->minOldSpaceSize >= OMR_MAX(extensions->absoluteMinimumOldSubSpaceSize, extensions->heapAlignment));
2469
#if defined(DEBUG)
2470
if (!flatConfiguration) {
2471
assume0(extensions->minNewSpaceSize >= 2*OMR_MAX(extensions->absoluteMinimumNewSubSpaceSize, extensions->heapAlignment));
2472
}
2473
#endif /* DEBUG */
2474
2475
assume0(extensions->oldSpaceSize >= extensions->minOldSpaceSize);
2476
assume0(extensions->oldSpaceSize <= extensions->maxOldSpaceSize);
2477
2478
#if defined(DEBUG)
2479
if (!flatConfiguration) {
2480
assume0(extensions->newSpaceSize >= extensions->minNewSpaceSize);
2481
assume0(extensions->newSpaceSize <= extensions->maxNewSpaceSize);
2482
}
2483
#endif /* DEBUG */
2484
2485
assume0(extensions->initialMemorySize = (extensions->oldSpaceSize + extensions->newSpaceSize));
2486
assume0(extensions->initialMemorySize <= extensions->maxSizeDefaultMemorySpace);
2487
2488
assume0(extensions->maxSizeDefaultMemorySpace <= extensions->memoryMax);
2489
assume0(extensions->maxSizeDefaultMemorySpace >= extensions->maxOldSpaceSize);
2490
assume0(extensions->maxSizeDefaultMemorySpace >= extensions->maxNewSpaceSize);
2491
2492
/* initialize the dynamicMaxSoftReferenceAge to the maxSoftReferenceAge since the first GC starts with reference age at its maximum */
2493
extensions->dynamicMaxSoftReferenceAge = extensions->maxSoftReferenceAge;
2494
2495
return result;
2496
}
2497
2498
/**
2499
* Ensure all values are correct.
2500
* Values input by the user can not be changed, values that have been calculated
2501
* may be updated if required.
2502
* @param memoryParameters array of parameter values
2503
* @param flatConfiguration with or without New memory space
2504
* @return JNI_OK if OK
2505
*/
2506
jint
2507
gcInitializeVerification(J9JavaVM *javaVM, IDATA* memoryParameters, bool flatConfiguration)
2508
{
2509
#if defined(J9VM_GC_THREAD_LOCAL_HEAP) || defined(J9VM_GC_MODRON_SCAVENGER)
2510
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
2511
#endif /* J9VM_GC_THREAD_LOCAL_HEAP || J9VM_GC_MODRON_SCAVENGER */
2512
jint result;
2513
2514
#if defined(J9VM_GC_THREAD_LOCAL_HEAP)
2515
/* Make sure TLH sizes are appropriately rounded */
2516
extensions->tlhMinimumSize = MM_Math::roundToSizeofUDATA(extensions->tlhMinimumSize);
2517
extensions->tlhIncrementSize = MM_Math::roundToSizeofUDATA(extensions->tlhIncrementSize);
2518
extensions->tlhInitialSize = MM_Math::roundToCeiling(extensions->tlhIncrementSize, extensions->tlhInitialSize);
2519
extensions->tlhMaximumSize = MM_Math::roundToCeiling(extensions->tlhIncrementSize, extensions->tlhMaximumSize);
2520
extensions->tlhSurvivorDiscardThreshold = MM_Math::roundToSizeofUDATA(extensions->tlhSurvivorDiscardThreshold);
2521
extensions->tlhTenureDiscardThreshold = MM_Math::roundToSizeofUDATA(extensions->tlhTenureDiscardThreshold);
2522
#endif /* J9VM_GC_THREAD_LOCAL_HEAP */
2523
2524
#if defined(J9VM_GC_MODRON_SCAVENGER)
2525
if (extensions->scavengerScanCacheMaximumSize < extensions->scavengerScanCacheMinimumSize) {
2526
PORT_ACCESS_FROM_JAVAVM(javaVM);
2527
j9nls_printf(PORTLIB,J9NLS_ERROR,J9NLS_GC_OPTIONS_MUST_BE_NO_GREATER_THAN, "-XXgc:scanCacheMinimumSize", "-XXgc:scanCacheMaximumSize");
2528
return JNI_ERR;
2529
}
2530
/* make sure scavengerScanCacheMinimumSize and scavengerScanCacheMaximumSize are properly aligned */
2531
extensions->scavengerScanCacheMaximumSize = MM_Math::roundToCeiling(extensions->tlhMinimumSize, extensions->scavengerScanCacheMaximumSize);
2532
extensions->scavengerScanCacheMinimumSize = MM_Math::roundToCeiling(extensions->tlhMinimumSize, extensions->scavengerScanCacheMinimumSize);
2533
#endif /* J9VM_GC_MODRON_SCAVENGER */
2534
2535
/* Recalculate memory parameters based on user input (Xms, Xmo, Xmn) */
2536
result = gcCalculateMemoryParameters(javaVM, memoryParameters, flatConfiguration);
2537
if (JNI_OK != result) {
2538
return result;
2539
}
2540
2541
return JNI_OK;
2542
}
2543
2544
/**
2545
* If appropriate, lower the Xmx value before re-attempting to allocate basic heap structures.
2546
* Called after we have failed to allocate basic heap structures, this function
2547
* may resize the Xmx value so we can try again with a smaller Xmx value.
2548
*
2549
* @param memoryParameterTable the table containing user-specified memory parameters
2550
* @param memoryMinimum the minimum allowable Xmx value
2551
*
2552
* @note This function assumes that all memory parameters have been verified, and
2553
* will be re-verified based on the new Xmx value
2554
*
2555
* @return true - if the Xmx value was resized, and we should try again
2556
* @return false - otherwise
2557
*/
2558
bool
2559
reduceXmxValueForHeapInitialization(J9JavaVM *javaVM, IDATA *memoryParameterTable, UDATA memoryMinimum)
2560
{
2561
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
2562
bool optXmxSet = (-1 != memoryParameterTable[opt_Xmx]);
2563
bool optXmdxSet = (-1 != memoryParameterTable[opt_Xmdx]);
2564
2565
if (optXmxSet) {
2566
/* -Xmx was set by the user, so just fail */
2567
return false;
2568
} else if (extensions->memoryMax <= memoryMinimum) {
2569
/* We can't reduce the Xmx value any more -- fail */
2570
return false;
2571
}
2572
2573
extensions->memoryMax = (extensions->memoryMax / DEFAULT_XMX_REDUCTION_DENOMINATOR) * DEFAULT_XMX_REDUCTION_NUMERATOR;
2574
extensions->memoryMax = MM_Math::roundToFloor(extensions->heapAlignment, extensions->memoryMax);
2575
extensions->memoryMax = MM_Math::roundToFloor(extensions->regionSize, extensions->memoryMax);
2576
2577
/* Don't shrink below the minimum value */
2578
if (extensions->memoryMax < memoryMinimum) {
2579
extensions->memoryMax = memoryMinimum;
2580
}
2581
2582
/* If Xmdx is now > Xmx, and the Xmdx value was not set by the user, change Xmdx also */
2583
if ((!optXmdxSet) && (extensions->memoryMax < extensions->maxSizeDefaultMemorySpace)) {
2584
extensions->maxSizeDefaultMemorySpace = extensions->memoryMax;
2585
}
2586
2587
return true;
2588
}
2589
2590
/**
2591
* If the requested page size does not match the actual page size, and the
2592
* user specified -Xlp:objectheap:warn, output a warning message.
2593
*
2594
* @param extensions the instance of GCExtensions
2595
* @param loadInfo The loadInfo object to store the error message
2596
*/
2597
void
2598
warnIfPageSizeNotSatisfied(J9JavaVM* vm, MM_GCExtensions *extensions) {
2599
PORT_ACCESS_FROM_JAVAVM(vm);
2600
2601
if(extensions == NULL || extensions->heap == NULL) {
2602
return;
2603
}
2604
2605
if((extensions->heap->getPageSize() != extensions->requestedPageSize) && extensions->largePageWarnOnError) {
2606
/* Obtain the qualified sizes (e.g. 2k) */
2607
UDATA requestedSize = extensions->requestedPageSize;
2608
const char* requestedSizeQualifier = NULL;
2609
qualifiedSize(&requestedSize, &requestedSizeQualifier);
2610
2611
UDATA actualSize = extensions->heap->getPageSize();
2612
const char* actualSizeQualifier = NULL;
2613
qualifiedSize(&actualSize, &actualSizeQualifier);
2614
2615
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_XLP_PAGE_NOT_AVAILABLE_WARN, requestedSize, requestedSizeQualifier, actualSize, actualSizeQualifier);
2616
}
2617
}
2618
2619
/**
2620
* Set default configuration options for SE
2621
* @param extensions GCExtensions
2622
* @param scavenge value to set extensions->scavengerEnabled except it is already forced
2623
* @param concurrentMark value to set extensions->concurrentMark except it is already forced
2624
* @param concurrentSweep value to set extensions->concurrentSweep except it is already forced
2625
* @param largeObjectArea value to set extensions->largeObjectArea except it is already forced
2626
*/
2627
void
2628
setDefaultConfigOptions(MM_GCExtensions *extensions, bool scavenge, bool concurrentMark, bool concurrentSweep, bool largeObjectArea)
2629
{
2630
#if defined(J9VM_GC_MODRON_SCAVENGER)
2631
if(!extensions->configurationOptions._forceOptionScavenge) {
2632
extensions->scavengerEnabled = scavenge;
2633
}
2634
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
2635
#if defined (OMR_GC_MODRON_CONCURRENT_MARK)
2636
if(!extensions->configurationOptions._forceOptionConcurrentMark) {
2637
extensions->concurrentMark = concurrentMark;
2638
}
2639
#endif /* defined (OMR_GC_MODRON_CONCURRENT_MARK) */
2640
#if defined(J9VM_GC_CONCURRENT_SWEEP)
2641
if(!extensions->configurationOptions._forceOptionConcurrentSweep) {
2642
extensions->concurrentSweep = concurrentSweep;
2643
}
2644
#endif /* defined(J9VM_GC_CONCURRENT_SWEEP) */
2645
#if defined(J9VM_GC_LARGE_OBJECT_AREA)
2646
if(!extensions->configurationOptions._forceOptionLargeObjectArea) {
2647
extensions->largeObjectArea = largeObjectArea;
2648
}
2649
#endif /* defined(J9VM_GC_LARGE_OBJECT_AREA) */
2650
}
2651
2652
void
2653
setConfigOptionsForNoGc(MM_GCExtensions *extensions)
2654
{
2655
/* noScavenger noConcurrentMark noConcurrentSweep, noLOA */
2656
#if defined(J9VM_GC_MODRON_SCAVENGER)
2657
extensions->configurationOptions._forceOptionScavenge = true;
2658
extensions->scavengerEnabled = false;
2659
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
2660
#if defined (OMR_GC_MODRON_CONCURRENT_MARK)
2661
extensions->configurationOptions._forceOptionConcurrentMark = true;
2662
extensions->concurrentMark = false;
2663
#endif /* defined (OMR_GC_MODRON_CONCURRENT_MARK) */
2664
#if defined(J9VM_GC_CONCURRENT_SWEEP)
2665
extensions->configurationOptions._forceOptionConcurrentSweep = true;
2666
extensions->concurrentSweep = false;
2667
#endif /* defined(J9VM_GC_CONCURRENT_SWEEP) */
2668
#if defined(J9VM_GC_LARGE_OBJECT_AREA)
2669
extensions->configurationOptions._forceOptionLargeObjectArea = true;
2670
extensions->largeObjectArea = false;
2671
#endif /* defined(J9VM_GC_LARGE_OBJECT_AREA) */
2672
/* 1 gcThread */
2673
extensions->gcThreadCountForced = true;
2674
extensions->gcThreadCount = 1;
2675
2676
extensions->splitFreeListSplitAmount = 1;
2677
extensions->objectListFragmentCount = 1;
2678
2679
/* disable excessiveGC */
2680
extensions->excessiveGCEnabled._wasSpecified = true;
2681
extensions->excessiveGCEnabled._valueSpecified = false;
2682
/* disable estimate fragmentation */
2683
extensions->estimateFragmentation = 0;
2684
extensions->processLargeAllocateStats = false;
2685
/* disable system gc */
2686
extensions->disableExplicitGC = true;
2687
}
2688
2689
/**
2690
* Create proper configuration for SE based on options
2691
* @param env pointer to Environment
2692
* @return pointer to created configuration or NULL if failed
2693
*/
2694
MM_Configuration *
2695
configurateGCWithPolicyAndOptionsStandard(MM_EnvironmentBase *env)
2696
{
2697
MM_Configuration *result = NULL;
2698
MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(env->getOmrVM());
2699
2700
#if defined(J9VM_GC_MODRON_SCAVENGER)
2701
if (extensions->scavengerEnabled) {
2702
#if defined(J9VM_GC_CONCURRENT_SWEEP)
2703
/* Scavenger does not support concurrent sweep */
2704
if (!extensions->concurrentSweep) {
2705
#endif /* defined(J9VM_GC_CONCURRENT_SWEEP) */
2706
2707
/*
2708
* Set region size based on section size of Concurrent Scavenger Page
2709
* - get an estimation of maximum Nursery size based at -Xmn, -Xmnx, -Xmns or -Xmx / 4
2710
* (this is fast check without full parameters analysis for Concurrent Scavenger prototype, it is recommended to provide -Xmn explicitly)
2711
* - select Concurrent Scavenger Page size based at estimated Nursery size: if should be rounded up to next power of 2 but not smaller then 32M
2712
* - select region size as a Concurrent Scavenger Page Section size
2713
*/
2714
if (extensions->isConcurrentScavengerHWSupported()) {
2715
OMRPORT_ACCESS_FROM_ENVIRONMENT(env);
2716
/* Default maximum Nursery size estimation in case of none of -Xmn* options is specified */
2717
uintptr_t nurserySize = extensions->memoryMax / 4;
2718
2719
/*
2720
* correctness of -Xmn* values will be analyzed later on with initialization error in case of bad combination
2721
* so assume here all of them are correct, just check none of them is larger then entire heap size
2722
*/
2723
if (extensions->userSpecifiedParameters._Xmn._wasSpecified) {
2724
/* maximum Nursery size was set in -Xmn */
2725
if (extensions->userSpecifiedParameters._Xmn._valueSpecified < extensions->memoryMax) {
2726
nurserySize = extensions->userSpecifiedParameters._Xmn._valueSpecified;
2727
}
2728
} else if (extensions->userSpecifiedParameters._Xmnx._wasSpecified) {
2729
/* maximum Nursery size was set in -Xmnx */
2730
if (extensions->userSpecifiedParameters._Xmnx._valueSpecified < extensions->memoryMax) {
2731
nurserySize = extensions->userSpecifiedParameters._Xmnx._valueSpecified;
2732
}
2733
} else if (extensions->userSpecifiedParameters._Xmns._wasSpecified) {
2734
/* maximum Nursery size was set in -Xmns, it is related in case if it is larger then default maximum Nursery size */
2735
if (extensions->userSpecifiedParameters._Xmns._valueSpecified < extensions->memoryMax) {
2736
if (extensions->userSpecifiedParameters._Xmns._valueSpecified > nurserySize) {
2737
nurserySize = extensions->userSpecifiedParameters._Xmns._valueSpecified;
2738
}
2739
}
2740
}
2741
2742
/* Calculate Concurrent Scavenger Page parameters based at maximum Nursery size estimation */
2743
extensions->calculateConcurrentScavengerPageParameters(nurserySize);
2744
2745
if (extensions->isDebugConcurrentScavengerPageAlignment()) {
2746
omrtty_printf("Nursery size early projection 0x%zx, Concurrent Scavenger Page size 0x%zx, Section size for heap alignment 0x%zx\n",
2747
nurserySize, extensions->getConcurrentScavengerPageSectionSize() * CONCURRENT_SCAVENGER_PAGE_SECTIONS, extensions->getConcurrentScavengerPageSectionSize());
2748
}
2749
}
2750
2751
result = MM_ConfigurationGenerational::newInstance(env);
2752
2753
#if defined(J9VM_GC_CONCURRENT_SWEEP)
2754
}
2755
#endif /* defined(J9VM_GC_CONCURRENT_SWEEP) */
2756
} else
2757
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
2758
{
2759
result = MM_ConfigurationFlat::newInstance(env);
2760
}
2761
2762
return result;
2763
}
2764
2765
/**
2766
* Create configuration based on GC policy
2767
* @param vm pointer to JavaVM
2768
* @return pointer to created configuration or NULL if failed
2769
*/
2770
MM_Configuration *
2771
configurateGCWithPolicyAndOptions(OMR_VM* omrVM)
2772
{
2773
MM_Configuration *result = NULL;
2774
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(omrVM);
2775
MM_EnvironmentBase env(omrVM);
2776
2777
switch(extensions->configurationOptions._gcPolicy) {
2778
case gc_policy_optthruput:
2779
extensions->gcModeString = "-Xgcpolicy:optthruput";
2780
omrVM->gcPolicy = J9_GC_POLICY_OPTTHRUPUT;
2781
/* noScavenge, noConcurrentMark, noConcurrentSweep, loa */
2782
setDefaultConfigOptions(extensions, false, false, false, true);
2783
result = configurateGCWithPolicyAndOptionsStandard(&env);
2784
break;
2785
2786
case gc_policy_optavgpause:
2787
extensions->gcModeString = "-Xgcpolicy:optavgpause";
2788
omrVM->gcPolicy = J9_GC_POLICY_OPTAVGPAUSE;
2789
/* noScavenge, concurrentMark, concurrentSweep, loa */
2790
setDefaultConfigOptions(extensions, false, true, true, true);
2791
result = configurateGCWithPolicyAndOptionsStandard(&env);
2792
break;
2793
2794
case gc_policy_gencon:
2795
extensions->gcModeString = "-Xgcpolicy:gencon";
2796
omrVM->gcPolicy = J9_GC_POLICY_GENCON;
2797
/* scavenge, concurrentMark, noConcurrentSweep, loa */
2798
setDefaultConfigOptions(extensions, true, true, false, true);
2799
result = configurateGCWithPolicyAndOptionsStandard(&env);
2800
break;
2801
2802
case gc_policy_metronome:
2803
extensions->gcModeString = "-Xgcpolicy:metronome";
2804
omrVM->gcPolicy = J9_GC_POLICY_METRONOME;
2805
result = MM_ConfigurationRealtime::newInstance(&env);
2806
break;
2807
2808
case gc_policy_balanced:
2809
extensions->gcModeString = "-Xgcpolicy:balanced";
2810
omrVM->gcPolicy = J9_GC_POLICY_BALANCED;
2811
result = MM_ConfigurationIncrementalGenerational::newInstance(&env);
2812
break;
2813
2814
case gc_policy_nogc:
2815
extensions->gcModeString = "-Xgcpolicy:nogc";
2816
omrVM->gcPolicy = J9_GC_POLICY_NOGC;
2817
/* noScavenge, noConcurrentMark, noConcurrentSweep, noLOA */
2818
setConfigOptionsForNoGc(extensions);
2819
result = configurateGCWithPolicyAndOptionsStandard(&env);
2820
break;
2821
2822
case gc_policy_undefined:
2823
default:
2824
/* Undefined or unknown GC policy */
2825
Assert_MM_unreachable();
2826
break;
2827
}
2828
2829
return result;
2830
}
2831
2832
/**
2833
* Initialize GC parameters.
2834
* Initialize GC parameters with default values, parse the command line, massage values
2835
* as required and finally verify values.
2836
* @return J9VMDLLMAIN_OK or J9VMDLLMAIN_FAILED
2837
*/
2838
jint
2839
gcInitializeDefaults(J9JavaVM* vm)
2840
{
2841
J9VMDllLoadInfo *loadInfo = getGCDllLoadInfo(vm);
2842
UDATA tableSize = (opt_none + 1) * sizeof(IDATA);
2843
UDATA realtimeSizeClassesAllocationSize = ROUND_TO(sizeof(UDATA), sizeof(J9VMGCSizeClasses));
2844
IDATA *memoryParameterTable;
2845
UDATA minimumVMSize;
2846
bool flatConfiguration = true;
2847
MM_GCExtensions *extensions;
2848
MM_EnvironmentBase env(vm->omrVM);
2849
PORT_ACCESS_FROM_JAVAVM(vm);
2850
2851
minimumVMSize = MINIMUM_VM_SIZE;
2852
2853
memoryParameterTable = (IDATA *)j9mem_allocate_memory(tableSize, OMRMEM_CATEGORY_MM);
2854
if (!memoryParameterTable) {
2855
loadInfo->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.");
2856
goto error;
2857
}
2858
memset(memoryParameterTable, -1, tableSize);
2859
2860
vm->memoryManagerFunctions = ((J9MemoryManagerFunctions *)GLOBAL_TABLE(MemoryManagerFunctions));
2861
2862
// todo: dagar centralize language init
2863
//gcOmrInitializeDefaults(vm->omrVM);
2864
extensions = MM_GCExtensions::newInstance(&env);
2865
if (NULL == extensions) {
2866
loadInfo->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.");
2867
goto error;
2868
}
2869
extensions->setOmrVM(vm->omrVM);
2870
vm->omrVM->_gcOmrVMExtensions = (void *)extensions;
2871
vm->gcExtensions = vm->omrVM->_gcOmrVMExtensions;
2872
2873
/* enable estimateFragmentation for all GCs as default for java, but not the estimated result would not affect concurrentgc kickoff by default */
2874
extensions->estimateFragmentation = (GLOBALGC_ESTIMATE_FRAGMENTATION | LOCALGC_ESTIMATE_FRAGMENTATION);
2875
extensions->processLargeAllocateStats = true;
2876
extensions->concurrentSlackFragmentationAdjustmentWeight = 0;
2877
2878
/* allocate and set the collector language interface to Java */
2879
extensions->collectorLanguageInterface = MM_CollectorLanguageInterfaceImpl::newInstance(&env);
2880
if (NULL == extensions->collectorLanguageInterface) {
2881
goto error;
2882
}
2883
2884
initializeVerboseFunctionTableWithDummies(&extensions->verboseFunctionTable);
2885
2886
if (JNI_OK != gcParseCommandLineAndInitializeWithValues(vm, memoryParameterTable)) {
2887
loadInfo->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.");
2888
goto error;
2889
}
2890
2891
if ((-1 == memoryParameterTable[opt_Xms]) && (-1 != memoryParameterTable[opt_initialRAMPercent])) {
2892
extensions->initialMemorySize = (uintptr_t)(((double)extensions->usablePhysicalMemory / 100.0) * extensions->initialRAMPercent);
2893
/* Update memory parameter table to appear that -Xms was specified */
2894
memoryParameterTable[opt_Xms] = memoryParameterTable[opt_initialRAMPercent];
2895
}
2896
if ((-1 == memoryParameterTable[opt_Xmx]) && (-1 != memoryParameterTable[opt_maxRAMPercent])) {
2897
extensions->memoryMax = (uintptr_t)(((double)extensions->usablePhysicalMemory / 100.0) * extensions->maxRAMPercent);
2898
/* Update memory parameter table to appear that -Xmx was specified */
2899
memoryParameterTable[opt_Xmx] = memoryParameterTable[opt_maxRAMPercent];
2900
}
2901
2902
if (gc_policy_metronome == extensions->configurationOptions._gcPolicy) {
2903
/* Heap is segregated; take into account segregatedAllocationCache. */
2904
vm->segregatedAllocationCacheSize = (J9VMGC_SIZECLASSES_NUM_SMALL + 1)*sizeof(J9VMGCSegregatedAllocationCacheEntry);
2905
2906
vm->realtimeSizeClasses = (J9VMGCSizeClasses *)j9mem_allocate_memory(realtimeSizeClassesAllocationSize, OMRMEM_CATEGORY_VM);
2907
if (NULL == vm->realtimeSizeClasses) {
2908
loadInfo->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.");
2909
goto error;
2910
}
2911
}
2912
vm->vmThreadSize = J9_VMTHREAD_SEGREGATED_ALLOCATION_CACHE_OFFSET + vm->segregatedAllocationCacheSize + sizeof(OMR_VMThread);
2913
2914
#if defined(OMR_GC_CONCURRENT_SCAVENGER)
2915
if (gc_policy_gencon == extensions->configurationOptions._gcPolicy) {
2916
/* after we parsed cmd line options, check if we can obey the request to run CS (valid for Gencon only) */
2917
if (extensions->concurrentScavengerForced) {
2918
#if defined(J9VM_ARCH_X86) || defined(J9VM_ARCH_POWER) || defined(J9VM_ARCH_AARCH64)
2919
/*
2920
* x86, POWER and AArch64 do not respect -XXgc:softwareRangeCheckReadBarrier and have it set to true always.
2921
*
2922
* Z is the only consumer that actually uses -XXgc:softwareRangeCheckReadBarrier
2923
* to overwrite HW concurrent scavenge.
2924
*/
2925
extensions->softwareRangeCheckReadBarrier = true;
2926
#endif /* J9VM_ARCH_X86 || J9VM_ARCH_POWER || J9VM_ARCH_AARCH64 */
2927
if (LOADED == (FIND_DLL_TABLE_ENTRY(J9_JIT_DLL_NAME)->loadFlags & LOADED)) {
2928
/* If running jitted, it must be on supported h/w */
2929
J9ProcessorDesc processorDesc;
2930
j9sysinfo_get_processor_description(&processorDesc);
2931
bool hwSupported = j9sysinfo_processor_has_feature(&processorDesc, J9PORT_S390_FEATURE_GUARDED_STORAGE) &&
2932
j9sysinfo_processor_has_feature(&processorDesc, J9PORT_S390_FEATURE_SIDE_EFFECT_ACCESS);
2933
2934
if (hwSupported) {
2935
/* Software Barrier request overwrites HW usage on supported HW */
2936
extensions->concurrentScavengerHWSupport = hwSupported
2937
&& !extensions->softwareRangeCheckReadBarrier
2938
#if defined(J9VM_OPT_CRIU_SUPPORT)
2939
&& !vm->internalVMFunctions->isCRIUSupportEnabled(vm->internalVMFunctions->currentVMThread(vm))
2940
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
2941
&& !J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_PORTABLE_SHARED_CACHE);
2942
extensions->concurrentScavenger = hwSupported || extensions->softwareRangeCheckReadBarrier;
2943
} else {
2944
extensions->concurrentScavengerHWSupport = false;
2945
#if defined(J9VM_ARCH_X86) || defined(J9VM_ARCH_POWER) || defined(J9VM_ARCH_AARCH64) || defined(J9VM_ARCH_S390)
2946
extensions->concurrentScavenger = true;
2947
#endif /*J9VM_ARCH_X86 || J9VM_ARCH_POWER || J9VM_ARCH_AARCH64 || J9VM_ARCH_S390 */
2948
}
2949
} else {
2950
/* running interpreted is ok on any h/w */
2951
extensions->concurrentScavenger = true;
2952
}
2953
}
2954
}
2955
#endif /* OMR_GC_CONCURRENT_SCAVENGER */
2956
2957
extensions->configuration = configurateGCWithPolicyAndOptions(vm->omrVM);
2958
2959
/* omrVM->gcPolicy is set by configurateGCWithPolicyAndOptions */
2960
((J9JavaVM*)env.getLanguageVM())->gcPolicy = vm->omrVM->gcPolicy;
2961
2962
if (NULL == extensions->configuration) {
2963
loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE, "Failed to initialize.");
2964
goto error;
2965
}
2966
2967
extensions->trackMutatorThreadCategory = J9_ARE_NO_BITS_SET(vm->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_REDUCE_CPU_MONITOR_OVERHEAD);
2968
2969
if (!gcParseTGCCommandLine(vm)) {
2970
loadInfo->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.");
2971
goto error;
2972
}
2973
2974
#if defined(J9VM_GC_MODRON_SCAVENGER)
2975
if (extensions->scavengerEnabled) {
2976
flatConfiguration = false;
2977
}
2978
#endif /* J9VM_GC_MODRON_SCAVENGER */
2979
2980
while (true) {
2981
/* Verify Xmx and Xmdx before using the Xmdx value to calculate further values */
2982
if (JNI_OK != gcInitializeXmxXmdxVerification(vm, memoryParameterTable, flatConfiguration, minimumVMSize, NULL, NULL)) {
2983
loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE, "Failed to initialize.");
2984
goto error;
2985
}
2986
2987
/* Calculate memory parameters based on Xmx/Xmdx */
2988
if (JNI_OK != gcInitializeCalculatedValues(vm, memoryParameterTable)) {
2989
loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE, "Failed to initialize.");
2990
goto error;
2991
}
2992
2993
/* Verify all memory parameters */
2994
if (JNI_OK != gcInitializeVerification(vm, memoryParameterTable, flatConfiguration)) {
2995
loadInfo->fatalErrorStr = (char *)j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_GC_FAILED_TO_INITIALIZE, "Failed to initialize.");
2996
goto error;
2997
}
2998
2999
/* Try to initialize basic heap structures with the memory parameters we currently have */
3000
if (JNI_OK == j9gc_initialize_heap(vm, memoryParameterTable, extensions->memoryMax)) {
3001
break;
3002
}
3003
3004
if(extensions->largePageFailedToSatisfy) {
3005
/* We were unable to satisfy the user's request for a strict page size. */
3006
goto error;
3007
}
3008
3009
if (!reduceXmxValueForHeapInitialization(vm, memoryParameterTable, minimumVMSize)) {
3010
/* Unable to reduce the Xmx value -- fail */
3011
/* Error string is set by j9gc_initialize_heap */
3012
goto error;
3013
}
3014
3015
/* We are going to try again -- free any buffer we already have from j9gc_initialize_heap */
3016
if ((loadInfo->loadFlags & FREE_ERROR_STRING) && (NULL != loadInfo->fatalErrorStr)) {
3017
j9mem_free_memory(loadInfo->fatalErrorStr);
3018
loadInfo->loadFlags &= ~FREE_ERROR_STRING;
3019
}
3020
loadInfo->fatalErrorStr = NULL;
3021
}
3022
3023
/* initialize largeObjectAllocationProfilingVeryLargeObjectThreshold, largeObjectAllocationProfilingVeryLargeObjectSizeClass and freeMemoryProfileMaxSizeClasses for non segregated memoryPool case */
3024
if (gc_policy_metronome != extensions->configurationOptions._gcPolicy) {
3025
MM_LargeObjectAllocateStats::initializeFreeMemoryProfileMaxSizeClasses(&env, extensions->largeObjectAllocationProfilingVeryLargeObjectThreshold,
3026
(float)extensions->largeObjectAllocationProfilingSizeClassRatio / (float)100.0, extensions->heap->getMaximumMemorySize());
3027
}
3028
warnIfPageSizeNotSatisfied(vm,extensions);
3029
j9mem_free_memory(memoryParameterTable);
3030
return J9VMDLLMAIN_OK;
3031
3032
error:
3033
if (memoryParameterTable) {
3034
j9mem_free_memory(memoryParameterTable);
3035
}
3036
return J9VMDLLMAIN_FAILED;
3037
}
3038
3039
#if defined(OMR_GC_CONCURRENT_SCAVENGER)
3040
static void
3041
hookAcquireVMAccess(J9HookInterface** hook, UDATA eventNum, void* voidEventData, void* userData)
3042
{
3043
J9VMAcquireVMAccessEvent* eventData = (J9VMAcquireVMAccessEvent*)voidEventData;
3044
3045
J9VMThread *currentThread = eventData->currentThread;
3046
MM_EnvironmentStandard *env = MM_EnvironmentStandard::getEnvironment(currentThread->omrVMThread);
3047
MM_GCExtensions* ext = MM_GCExtensions::getExtensions(currentThread);
3048
3049
Assert_MM_true(ext->concurrentScavenger);
3050
3051
ext->scavenger->switchConcurrentForThread(env);
3052
}
3053
3054
static void
3055
hookReleaseVMAccess(J9HookInterface** hook, UDATA eventNum, void* voidEventData, void* userData)
3056
{
3057
J9VMReleaseVMAccessEvent* eventData = (J9VMReleaseVMAccessEvent*)voidEventData;
3058
3059
J9VMThread *currentThread = eventData->currentThread;
3060
MM_EnvironmentStandard *env = MM_EnvironmentStandard::getEnvironment(currentThread->omrVMThread);
3061
MM_GCExtensions* ext = MM_GCExtensions::getExtensions(currentThread);
3062
3063
if (ext->isConcurrentScavengerInProgress()) {
3064
/* Flush and final flags are false, which means that we will not release the copy caches to scan queue, but just make them inactive,
3065
* for someone else to release them if needed. More often, however, this thread will re-acquire VM access and re-active the caches
3066
*/
3067
ext->scavenger->threadReleaseCaches(env, env, false, false);
3068
}
3069
}
3070
3071
static void
3072
hookAcquiringExclusiveInNative(J9HookInterface** hook, UDATA eventNum, void* voidEventData, void* userData)
3073
{
3074
J9VMAcquringExclusiveInNativeEvent* eventData = (J9VMAcquringExclusiveInNativeEvent*)voidEventData;
3075
3076
J9VMThread *targetThread = eventData->targetThread;
3077
MM_EnvironmentStandard *env = MM_EnvironmentStandard::getEnvironment(targetThread->omrVMThread);
3078
MM_GCExtensions* ext = MM_GCExtensions::getExtensions(targetThread);
3079
3080
if (ext->isConcurrentScavengerInProgress()) {
3081
/* 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). */
3082
ext->scavenger->threadReleaseCaches(NULL, env, true, true);
3083
3084
}
3085
}
3086
3087
#endif /* OMR_GC_CONCURRENT_SCAVENGER */
3088
3089
/**
3090
* Report an event indicating that the GC is initialized
3091
*/
3092
jint
3093
triggerGCInitialized(J9VMThread* vmThread)
3094
{
3095
J9JavaVM* vm = vmThread->javaVM;
3096
PORT_ACCESS_FROM_JAVAVM(vm);
3097
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
3098
3099
UDATA beatMicro = 0;
3100
UDATA timeWindowMicro = 0;
3101
UDATA targetUtilizationPercentage = 0;
3102
UDATA gcInitialTrigger = 0;
3103
UDATA headRoom = 0;
3104
#if defined(J9VM_GC_REALTIME)
3105
beatMicro = extensions->beatMicro;
3106
timeWindowMicro = extensions->timeWindowMicro;
3107
targetUtilizationPercentage = extensions->targetUtilizationPercentage;
3108
gcInitialTrigger = extensions->gcInitialTrigger;
3109
headRoom = extensions->headRoom;
3110
#endif /* J9VM_GC_REALTIME */
3111
3112
UDATA numaNodes = extensions->_numaManager.getAffinityLeaderCount();
3113
3114
UDATA regionSize = extensions->getHeap()->getHeapRegionManager()->getRegionSize();
3115
UDATA regionCount = extensions->getHeap()->getHeapRegionManager()->getTableRegionCount();
3116
3117
UDATA arrayletLeafSize = 0;
3118
arrayletLeafSize = vm->arrayletLeafSize;
3119
3120
TRIGGER_J9HOOK_MM_OMR_INITIALIZED(
3121
extensions->omrHookInterface,
3122
vmThread->omrVMThread,
3123
j9time_hires_clock(),
3124
j9gc_get_gcmodestring(vm),
3125
0, /* unused */
3126
j9gc_get_maximum_heap_size(vm),
3127
j9gc_get_initial_heap_size(vm),
3128
j9sysinfo_get_physical_memory(),
3129
j9sysinfo_get_number_CPUs_by_type(J9PORT_CPU_ONLINE),
3130
extensions->gcThreadCount,
3131
j9sysinfo_get_CPU_architecture(),
3132
j9sysinfo_get_OS_type(),
3133
j9sysinfo_get_OS_version(),
3134
extensions->accessBarrier->compressedPointersShift(),
3135
beatMicro,
3136
timeWindowMicro,
3137
targetUtilizationPercentage,
3138
gcInitialTrigger,
3139
headRoom,
3140
extensions->heap->getPageSize(),
3141
getPageTypeString(extensions->heap->getPageFlags()),
3142
extensions->requestedPageSize,
3143
getPageTypeString(extensions->requestedPageFlags),
3144
numaNodes,
3145
regionSize,
3146
regionCount,
3147
arrayletLeafSize);
3148
3149
return J9VMDLLMAIN_OK;
3150
}
3151
3152
static void
3153
hookValidatorVMThreadCrash(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
3154
{
3155
J9VMThread *vmThread = ((J9VMThreadCrashEvent *)eventData)->currentThread;
3156
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);
3157
if (NULL != env) {
3158
MM_Validator *activeValidator = env->_activeValidator;
3159
if (NULL != activeValidator) {
3160
env->_activeValidator = NULL; /* make absolutely sure we don't go recursive */
3161
activeValidator->threadCrash(env);
3162
}
3163
}
3164
}
3165
3166
static void
3167
hookVMRegistrationEvent(J9HookInterface** hook, UDATA eventNum, void* voidEventData, void* userData)
3168
{
3169
J9HookRegistrationEvent* eventData = (J9HookRegistrationEvent*)voidEventData;
3170
3171
switch (eventData->eventNum) {
3172
case J9HOOK_VM_OBJECT_ALLOCATE_WITHIN_THRESHOLD:
3173
case J9HOOK_VM_OBJECT_ALLOCATE_INSTRUMENTABLE: {
3174
J9JavaVM* vm = (J9JavaVM*)userData;
3175
J9VMThread * currentThread = vm->internalVMFunctions->currentVMThread(vm);
3176
if (currentThread != NULL) {
3177
j9gc_allocation_threshold_changed(currentThread);
3178
}
3179
}
3180
}
3181
}
3182
3183
static bool
3184
gcInitializeVMHooks(MM_GCExtensionsBase *extensions)
3185
{
3186
bool result = true;
3187
J9JavaVM* javaVM = (J9JavaVM *)extensions->getOmrVM()->_language_vm;
3188
3189
J9HookInterface **vmHookInterface = javaVM->internalVMFunctions->getVMHookInterface(javaVM);
3190
if (NULL == vmHookInterface) {
3191
result = false;
3192
} else if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_VM_THREAD_CRASH, hookValidatorVMThreadCrash, OMR_GET_CALLSITE(), NULL)) {
3193
result = false;
3194
} else if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_REGISTRATION_EVENT, hookVMRegistrationEvent, OMR_GET_CALLSITE(), javaVM)) {
3195
result = false;
3196
}
3197
#if defined(OMR_GC_CONCURRENT_SCAVENGER)
3198
else if (extensions->concurrentScavenger) {
3199
if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_VM_ACQUIREVMACCESS, hookAcquireVMAccess, OMR_GET_CALLSITE(), NULL)) {
3200
result = false;
3201
} else if (extensions->concurrentScavengeExhaustiveTermination) {
3202
/* Register these hooks only if Exhaustive Termination optimization is enabled */
3203
if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_VM_RELEASEVMACCESS, hookReleaseVMAccess, OMR_GET_CALLSITE(), NULL)) {
3204
result = false;
3205
} else if ((*vmHookInterface)->J9HookRegisterWithCallSite(vmHookInterface, J9HOOK_VM_ACQUIRING_EXCLUSIVE_IN_NATIVE, hookAcquiringExclusiveInNative, OMR_GET_CALLSITE(), NULL)) {
3206
result = false;
3207
}
3208
}
3209
}
3210
#endif /* OMR_GC_CONCURRENT_SCAVENGER */
3211
3212
return result;
3213
}
3214
3215
static void
3216
gcCleanupVMHooks(MM_GCExtensionsBase *extensions)
3217
{
3218
J9JavaVM* javaVM = (J9JavaVM *)extensions->getOmrVM()->_language_vm;
3219
J9HookInterface **vmHookInterface = javaVM->internalVMFunctions->getVMHookInterface(javaVM);
3220
if (NULL != vmHookInterface) {
3221
(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_VM_THREAD_CRASH, hookValidatorVMThreadCrash, NULL);
3222
(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_REGISTRATION_EVENT, hookVMRegistrationEvent, javaVM);
3223
#if defined(OMR_GC_CONCURRENT_SCAVENGER)
3224
if (extensions->concurrentScavenger) {
3225
(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_VM_ACQUIREVMACCESS, hookAcquireVMAccess, NULL);
3226
if (extensions->concurrentScavengeExhaustiveTermination) {
3227
(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_VM_RELEASEVMACCESS, hookReleaseVMAccess, NULL);
3228
(*vmHookInterface)->J9HookUnregister(vmHookInterface, J9HOOK_VM_ACQUIRING_EXCLUSIVE_IN_NATIVE, hookAcquiringExclusiveInNative, NULL);
3229
}
3230
}
3231
#endif /* OMR_GC_CONCURRENT_SCAVENGER */
3232
}
3233
}
3234
3235
} /* extern "C" */
3236
3237