Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_base/GCExtensions.cpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2021 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
#include "GCExtensions.hpp"
24
25
#include "hookable_api.h"
26
#include "j9cfg.h"
27
#include "j2sever.h"
28
#include "j9memcategories.h"
29
#include "j9nongenerated.h"
30
#include "j9port.h"
31
#include "util_api.h"
32
33
#include "EnvironmentBase.hpp"
34
#include "Forge.hpp"
35
#if defined(OMR_GC_IDLE_HEAP_MANAGER)
36
#include "IdleGCManager.hpp"
37
#endif /* defined(OMR_GC_IDLE_HEAP_MANAGER) */
38
#include "MemorySpace.hpp"
39
#include "MemorySubSpace.hpp"
40
#include "ObjectModel.hpp"
41
#include "ReferenceChainWalkerMarkMap.hpp"
42
#include "SublistPool.hpp"
43
#include "Wildcard.hpp"
44
45
MM_GCExtensions *
46
MM_GCExtensions::newInstance(MM_EnvironmentBase *env)
47
{
48
PORT_ACCESS_FROM_ENVIRONMENT(env);
49
MM_GCExtensions *extensions;
50
51
/* Avoid using MM_Forge to allocate memory for the extension, since MM_Forge itself has not been created! */
52
extensions = static_cast<MM_GCExtensions*>(j9mem_allocate_memory(sizeof(MM_GCExtensions), OMRMEM_CATEGORY_MM));
53
if (extensions) {
54
/* Initialize all the fields to zero */
55
memset((void *)extensions, 0, sizeof(*extensions));
56
57
new(extensions) MM_GCExtensions();
58
if (!extensions->initialize(env)) {
59
extensions->kill(env);
60
return NULL;
61
}
62
}
63
return extensions;
64
}
65
66
void
67
MM_GCExtensions::kill(MM_EnvironmentBase *env)
68
{
69
/* Avoid using MM_Forge to free memory for the extension, since MM_Forge was not used to allocate the memory */
70
PORT_ACCESS_FROM_ENVIRONMENT(env);
71
tearDown(env);
72
j9mem_free_memory(this);
73
}
74
75
/**
76
* Initialize the global GC extensions structure.
77
* Clear all values within the extensions structure and call the appropriate initialization routines
78
* on all substructures. Upon completion of this call, the extensions structure is ready for use.
79
*
80
* @return true if the initialization was successful, false otherwise.
81
*/
82
bool
83
MM_GCExtensions::initialize(MM_EnvironmentBase *env)
84
{
85
PORT_ACCESS_FROM_ENVIRONMENT(env);
86
87
if (!MM_GCExtensionsBase::initialize(env)) {
88
goto failed;
89
}
90
91
#if defined(J9VM_GC_REALTIME)
92
/* only ref slots, size in bytes: 2 * minObjectSize - header size */
93
minArraySizeToSetAsScanned = 2 * (1 << J9VMGC_SIZECLASSES_LOG_SMALLEST) - J9JAVAVM_CONTIGUOUS_HEADER_SIZE(getJavaVM());
94
#endif /* J9VM_GC_REALTIME */
95
96
#if defined(J9VM_GC_JNI_ARRAY_CACHE)
97
getJavaVM()->jniArrayCacheMaxSize = J9_GC_JNI_ARRAY_CACHE_SIZE;
98
#endif /* J9VM_GC_JNI_ARRAY_CACHE */
99
100
#if defined(J9VM_GC_THREAD_LOCAL_HEAP)
101
getJavaVM()->gcInfo.tlhThreshold = J9_GC_TLH_THRESHOLD;
102
getJavaVM()->gcInfo.tlhSize = J9_GC_TLH_SIZE;
103
#endif /* J9VM_GC_THREAD_LOCAL_HEAP */
104
105
/* if tuned for virtualized environment, we compromise a bit of performance for lower footprint */
106
if (getJavaVM()->runtimeFlags & J9_RUNTIME_TUNE_VIRTUALIZED) {
107
heapFreeMinimumRatioMultiplier = 20;
108
}
109
110
padToPageSize = J9_ARE_ALL_BITS_SET(getJavaVM()->runtimeFlags, J9_RUNTIME_AGGRESSIVE);
111
112
if (J9HookInitializeInterface(getHookInterface(), OMRPORT_FROM_J9PORT(PORTLIB), sizeof(hookInterface))) {
113
goto failed;
114
}
115
116
initializeReferenceArrayCopyTable(&referenceArrayCopyTable);
117
118
{
119
J9InternalVMFunctions const * const vmFuncs = getJavaVM()->internalVMFunctions;
120
_asyncCallbackKey = vmFuncs->J9RegisterAsyncEvent(getJavaVM(), memoryManagerAsyncCallbackHandler, getJavaVM());
121
_TLHAsyncCallbackKey = vmFuncs->J9RegisterAsyncEvent(getJavaVM(), memoryManagerTLHAsyncCallbackHandler, getJavaVM());
122
if ((_asyncCallbackKey < 0) || (_TLHAsyncCallbackKey < 0)) {
123
goto failed;
124
}
125
}
126
127
#if defined(OMR_GC_IDLE_HEAP_MANAGER)
128
/* absorbs GC specific idle tuning flags */
129
if (J9_IDLE_TUNING_GC_ON_IDLE == (getJavaVM()->vmRuntimeStateListener.idleTuningFlags & J9_IDLE_TUNING_GC_ON_IDLE)) {
130
gcOnIdle = true;
131
}
132
if (J9_IDLE_TUNING_COMPACT_ON_IDLE == (getJavaVM()->vmRuntimeStateListener.idleTuningFlags & J9_IDLE_TUNING_COMPACT_ON_IDLE)) {
133
compactOnIdle = true;
134
}
135
idleMinimumFree = getJavaVM()->vmRuntimeStateListener.idleMinFreeHeap;
136
#endif /* if defined(OMR_GC_IDLE_HEAP_MANAGER) */
137
138
return true;
139
140
failed:
141
tearDown(env);
142
return false;
143
}
144
145
/**
146
* Tear down the global GC extensions structure and all sub structures.
147
*/
148
void
149
MM_GCExtensions::tearDown(MM_EnvironmentBase *env)
150
{
151
J9InternalVMFunctions const * const vmFuncs = getJavaVM()->internalVMFunctions;
152
vmFuncs->J9UnregisterAsyncEvent(getJavaVM(), _TLHAsyncCallbackKey);
153
_TLHAsyncCallbackKey = -1;
154
vmFuncs->J9UnregisterAsyncEvent(getJavaVM(), _asyncCallbackKey);
155
_asyncCallbackKey = -1;
156
157
#if defined(J9VM_GC_MODRON_TRACE) && !defined(J9VM_GC_REALTIME)
158
tgcTearDownExtensions(getJavaVM());
159
#endif /* J9VM_GC_MODRON_TRACE && !defined(J9VM_GC_REALTIME) */
160
161
MM_Wildcard *wildcard = numaCommonThreadClassNamePatterns;
162
while (NULL != wildcard) {
163
MM_Wildcard *nextWildcard = wildcard->_next;
164
wildcard->kill(this);
165
wildcard = nextWildcard;
166
}
167
numaCommonThreadClassNamePatterns = NULL;
168
169
J9HookInterface** tmpHookInterface = getHookInterface();
170
if((NULL != tmpHookInterface) && (NULL != *tmpHookInterface)){
171
(*tmpHookInterface)->J9HookShutdownInterface(tmpHookInterface);
172
*tmpHookInterface = NULL; /* avoid issues with double teardowns */
173
}
174
175
#if defined(OMR_GC_IDLE_HEAP_MANAGER)
176
if (NULL != idleGCManager) {
177
idleGCManager->kill(env);
178
idleGCManager = NULL;
179
}
180
#endif /* defined(OMR_GC_IDLE_HEAP_MANAGER) */
181
182
MM_GCExtensionsBase::tearDown(env);
183
}
184
185
void
186
MM_GCExtensions::identityHashDataAddRange(MM_EnvironmentBase *env, MM_MemorySubSpace* subspace, UDATA size, void* lowAddress, void* highAddress)
187
{
188
J9IdentityHashData* hashData = getJavaVM()->identityHashData;
189
if (J9_IDENTITY_HASH_SALT_POLICY_STANDARD == hashData->hashSaltPolicy) {
190
if (MEMORY_TYPE_NEW == (subspace->getTypeFlags() & MEMORY_TYPE_NEW)) {
191
if (hashData->hashData1 == (UDATA)highAddress) {
192
/* Expanding low bound */
193
hashData->hashData1 = (UDATA)lowAddress;
194
} else if (hashData->hashData2 == (UDATA)lowAddress) {
195
/* Expanding high bound */
196
hashData->hashData2 = (UDATA)highAddress;
197
} else {
198
/* First expand */
199
Assert_MM_true(UDATA_MAX == hashData->hashData1);
200
Assert_MM_true(0 == hashData->hashData2);
201
hashData->hashData1 = (UDATA)lowAddress;
202
hashData->hashData2 = (UDATA)highAddress;
203
}
204
}
205
}
206
}
207
208
void
209
MM_GCExtensions::identityHashDataRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace* subspace, UDATA size, void* lowAddress, void* highAddress)
210
{
211
J9IdentityHashData* hashData = getJavaVM()->identityHashData;
212
if (J9_IDENTITY_HASH_SALT_POLICY_STANDARD == hashData->hashSaltPolicy) {
213
if (MEMORY_TYPE_NEW == (subspace->getTypeFlags() & MEMORY_TYPE_NEW)) {
214
if (hashData->hashData1 == (UDATA)lowAddress) {
215
/* Contracting low bound */
216
Assert_MM_true(hashData->hashData1 <= (UDATA)highAddress);
217
Assert_MM_true((UDATA)highAddress <= hashData->hashData2);
218
hashData->hashData1 = (UDATA)highAddress;
219
} else if (hashData->hashData2 == (UDATA)highAddress) {
220
/* Contracting high bound */
221
Assert_MM_true(hashData->hashData1 <= (UDATA)lowAddress);
222
Assert_MM_true((UDATA)lowAddress <= hashData->hashData2);
223
hashData->hashData2 = (UDATA)lowAddress;
224
} else {
225
Assert_MM_unreachable();
226
}
227
}
228
}
229
}
230
231
void
232
MM_GCExtensions::updateIdentityHashDataForSaltIndex(UDATA index)
233
{
234
getJavaVM()->identityHashData->hashSaltTable[index] = (U_32)convertValueToHash(getJavaVM(), getJavaVM()->identityHashData->hashSaltTable[index]);
235
}
236
237
/*
238
* computeDefaultMaxHeapForJava is for Java only, it will be called during gcParseCommandLineAndInitializeWithValues(),
239
* computeDefaultMaxHeap() will still be called during MM_GCExtensionsBase::initialize(), computeDefaultMaxHeapForJava() can overwrite value of memoryMax.
240
*/
241
void
242
MM_GCExtensions::computeDefaultMaxHeapForJava(bool enableOriginalJDK8HeapSizeCompatibilityOption)
243
{
244
OMRPORT_ACCESS_FROM_OMRVM(_omrVM);
245
246
if (OMR_CGROUP_SUBSYSTEM_MEMORY == omrsysinfo_cgroup_are_subsystems_enabled(OMR_CGROUP_SUBSYSTEM_MEMORY)) {
247
if (omrsysinfo_cgroup_is_memlimit_set()) {
248
/* If running in a cgroup with memory limit > 1G, reserve at-least 512M for JVM's internal requirements
249
* like JIT compilation etc, and extend default max heap memory to at-most 75% of cgroup limit.
250
* The value reserved for JVM's internal requirements excludes heap. This value is a conservative
251
* estimate of the JVM's internal requirements, given that one compilation thread can use up to 256M.
252
*/
253
#define OPENJ9_IN_CGROUP_NATIVE_FOOTPRINT_EXCLUDING_HEAP ((U_64)512 * 1024 * 1024)
254
memoryMax = (uintptr_t)OMR_MAX((int64_t)(usablePhysicalMemory / 2), (int64_t)(usablePhysicalMemory - OPENJ9_IN_CGROUP_NATIVE_FOOTPRINT_EXCLUDING_HEAP));
255
memoryMax = (uintptr_t)OMR_MIN(memoryMax, (usablePhysicalMemory / 4) * 3);
256
#undef OPENJ9_IN_CGROUP_NATIVE_FOOTPRINT_EXCLUDING_HEAP
257
}
258
}
259
260
#if defined(OMR_ENV_DATA64)
261
if (!enableOriginalJDK8HeapSizeCompatibilityOption) {
262
/* extend java default max memory to 25% of usable RAM */
263
memoryMax = OMR_MAX(memoryMax, usablePhysicalMemory / 4);
264
}
265
266
/* limit maxheapsize up to MAXIMUM_HEAP_SIZE_RECOMMENDED_FOR_3BIT_SHIFT_COMPRESSEDREFS, then can set 3bit compressedrefs as the default */
267
memoryMax = OMR_MIN(memoryMax, MAXIMUM_HEAP_SIZE_RECOMMENDED_FOR_3BIT_SHIFT_COMPRESSEDREFS);
268
#endif /* OMR_ENV_DATA64 */
269
270
memoryMax = MM_Math::roundToFloor(heapAlignment, memoryMax);
271
maxSizeDefaultMemorySpace = memoryMax;
272
}
273
274
MM_OwnableSynchronizerObjectList *
275
MM_GCExtensions::getOwnableSynchronizerObjectListsExternal(J9VMThread *vmThread)
276
{
277
Assert_MM_true(!isConcurrentScavengerInProgress());
278
279
return ownableSynchronizerObjectLists;
280
}
281
282