Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/EnvironmentDelegate.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2017, 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
#include "j9protos.h"
23
#include "ModronAssertions.h"
24
25
#include "EnvironmentBase.hpp"
26
#include "EnvironmentDelegate.hpp"
27
#include "GCExtensions.hpp"
28
#include "JNICriticalRegion.hpp"
29
#include "OMRVMInterface.hpp"
30
#include "OwnableSynchronizerObjectBufferRealtime.hpp"
31
#include "OwnableSynchronizerObjectBufferStandard.hpp"
32
#include "OwnableSynchronizerObjectBufferVLHGC.hpp"
33
#include "ReferenceObjectBufferRealtime.hpp"
34
#include "ReferenceObjectBufferStandard.hpp"
35
#include "ReferenceObjectBufferVLHGC.hpp"
36
#include "SublistFragment.hpp"
37
#include "UnfinalizedObjectBufferRealtime.hpp"
38
#include "UnfinalizedObjectBufferStandard.hpp"
39
#include "UnfinalizedObjectBufferVLHGC.hpp"
40
#include "VMAccess.hpp"
41
#include "omrlinkedlist.h"
42
43
/**
44
* Initialize the delegate's internal structures and values.
45
*/
46
bool
47
MM_EnvironmentDelegate::initialize(MM_EnvironmentBase *env)
48
{
49
_env = env;
50
_extensions = _env->getExtensions();
51
_vmThread = (J9VMThread *)_env->getOmrVMThread()->_language_vmthread;
52
53
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
54
if (extensions->isStandardGC()) {
55
#if defined(OMR_GC_MODRON_STANDARD)
56
_gcEnv._referenceObjectBuffer = MM_ReferenceObjectBufferStandard::newInstance(env);
57
_gcEnv._unfinalizedObjectBuffer = MM_UnfinalizedObjectBufferStandard::newInstance(env);
58
_gcEnv._ownableSynchronizerObjectBuffer = MM_OwnableSynchronizerObjectBufferStandard::newInstance(env);
59
#endif /* defined(OMR_GC_MODRON_STANDARD) */
60
} else if (extensions->isMetronomeGC()) {
61
#if defined(OMR_GC_REALTIME)
62
_gcEnv._referenceObjectBuffer = MM_ReferenceObjectBufferRealtime::newInstance(env);
63
_gcEnv._unfinalizedObjectBuffer = MM_UnfinalizedObjectBufferRealtime::newInstance(env);
64
_gcEnv._ownableSynchronizerObjectBuffer = MM_OwnableSynchronizerObjectBufferRealtime::newInstance(env);
65
#endif /* defined(OMR_GC_REALTIME) */
66
} else if (extensions->isVLHGC()) {
67
#if defined(OMR_GC_VLHGC)
68
_gcEnv._referenceObjectBuffer = MM_ReferenceObjectBufferVLHGC::newInstance(env);
69
_gcEnv._unfinalizedObjectBuffer = MM_UnfinalizedObjectBufferVLHGC::newInstance(env);
70
_gcEnv._ownableSynchronizerObjectBuffer = MM_OwnableSynchronizerObjectBufferVLHGC::newInstance(env);
71
#endif /* defined(OMR_GC_VLHGC) */
72
} else {
73
Assert_MM_unreachable();
74
}
75
76
if ((NULL == _gcEnv._referenceObjectBuffer) ||
77
(NULL == _gcEnv._unfinalizedObjectBuffer) ||
78
(NULL == _gcEnv._ownableSynchronizerObjectBuffer)) {
79
return false;
80
}
81
82
return true;
83
}
84
85
/**
86
* Free any internal structures associated to the receiver.
87
*/
88
void
89
MM_EnvironmentDelegate::tearDown()
90
{
91
if (NULL != _gcEnv._referenceObjectBuffer) {
92
_gcEnv._referenceObjectBuffer->kill(_env);
93
_gcEnv._referenceObjectBuffer = NULL;
94
}
95
96
if (NULL != _gcEnv._unfinalizedObjectBuffer) {
97
_gcEnv._unfinalizedObjectBuffer->kill(_env);
98
_gcEnv._unfinalizedObjectBuffer = NULL;
99
}
100
101
if (NULL != _gcEnv._ownableSynchronizerObjectBuffer) {
102
_gcEnv._ownableSynchronizerObjectBuffer->kill(_env);
103
_gcEnv._ownableSynchronizerObjectBuffer = NULL;
104
}
105
}
106
107
OMR_VMThread *
108
MM_EnvironmentDelegate::attachVMThread(OMR_VM *omrVM, const char *threadName, uintptr_t reason)
109
{
110
J9JavaVM *javaVM = (J9JavaVM *)omrVM->_language_vm;
111
J9VMThread *vmThread = NULL;
112
if (JNI_OK != javaVM->internalVMFunctions->attachSystemDaemonThread(javaVM, &vmThread, threadName)) {
113
return NULL;
114
}
115
116
#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)
117
if ((MM_EnvironmentBase::ATTACH_THREAD != reason) && (NULL != javaVM->javaOffloadSwitchOnWithReasonFunc)) {
118
(*javaVM->javaOffloadSwitchOnWithReasonFunc)(vmThread, J9_JNI_OFFLOAD_SWITCH_FINALIZE_WORKER_THREAD + reason);
119
vmThread->javaOffloadState = 1;
120
}
121
#endif /* J9VM_OPT_JAVA_OFFLOAD_SUPPORT */
122
123
return vmThread->omrVMThread;
124
}
125
126
void
127
MM_EnvironmentDelegate::detachVMThread(OMR_VM *omrVM, OMR_VMThread *omrThread, uintptr_t reason)
128
{
129
J9JavaVM *javaVM = (J9JavaVM *)omrVM->_language_vm;
130
131
#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)
132
if ((MM_EnvironmentBase::ATTACH_THREAD != reason) && (NULL != javaVM->javaOffloadSwitchOnWithReasonFunc)) {
133
(*javaVM->javaOffloadSwitchOffWithReasonFunc)((J9VMThread *)omrThread->_language_vmthread, reason);
134
}
135
#endif
136
137
javaVM->internalVMFunctions->DetachCurrentThread((JavaVM *)javaVM);
138
}
139
140
void
141
MM_EnvironmentDelegate::flushNonAllocationCaches()
142
{
143
#if defined(J9VM_GC_GENERATIONAL)
144
if (_env->getExtensions()->isStandardGC()) {
145
MM_SublistFragment::flush((J9VMGC_SublistFragment*)&_vmThread->gcRememberedSet);
146
}
147
#endif /* J9VM_GC_GENERATIONAL */
148
149
#if defined(J9VM_GC_FINALIZATION)
150
_gcEnv._unfinalizedObjectBuffer->flush(_env);
151
#endif /* J9VM_GC_FINALIZATION */
152
153
_gcEnv._ownableSynchronizerObjectBuffer->flush(_env);
154
}
155
156
void
157
MM_EnvironmentDelegate::setGCMainThread(bool isMainThread)
158
{
159
if (isMainThread) {
160
_vmThread->privateFlags |= J9_PRIVATE_FLAGS_GC_MAIN_THREAD;
161
} else {
162
_vmThread->privateFlags &= ~J9_PRIVATE_FLAGS_GC_MAIN_THREAD;
163
}
164
}
165
166
void
167
MM_EnvironmentDelegate::acquireVMAccess()
168
{
169
_vmThread->javaVM->internalVMFunctions->internalAcquireVMAccess(_vmThread);
170
}
171
172
void
173
MM_EnvironmentDelegate::releaseVMAccess()
174
{
175
_vmThread->javaVM->internalVMFunctions->internalReleaseVMAccess(_vmThread);
176
}
177
178
bool
179
MM_EnvironmentDelegate::inNative()
180
{
181
return (FALSE != _vmThread->inNative);
182
}
183
184
bool
185
MM_EnvironmentDelegate::isExclusiveAccessRequestWaiting()
186
{
187
return (J9_PUBLIC_FLAGS_HALT_THREAD_EXCLUSIVE == (_vmThread->publicFlags & J9_PUBLIC_FLAGS_HALT_THREAD_EXCLUSIVE));
188
}
189
190
/**
191
* Acquires exclusive VM access
192
*/
193
void
194
MM_EnvironmentDelegate::acquireExclusiveVMAccess()
195
{
196
_vmThread->javaVM->internalVMFunctions->acquireExclusiveVMAccess(_vmThread);
197
}
198
199
/**
200
* Releases exclusive VM access.
201
*/
202
void
203
MM_EnvironmentDelegate::releaseExclusiveVMAccess()
204
{
205
_vmThread->javaVM->internalVMFunctions->releaseExclusiveVMAccess(_vmThread);
206
}
207
208
209
uintptr_t
210
MM_EnvironmentDelegate::relinquishExclusiveVMAccess()
211
{
212
uintptr_t savedExclusiveCount = _vmThread->omrVMThread->exclusiveCount;
213
214
Assert_MM_true(J9_PUBLIC_FLAGS_VM_ACCESS == (_vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS));
215
Assert_MM_true(0 < savedExclusiveCount);
216
217
_vmThread->omrVMThread->exclusiveCount = 0;
218
VM_VMAccess::clearPublicFlags(_vmThread, J9_PUBLIC_FLAGS_VM_ACCESS);
219
220
return savedExclusiveCount;
221
}
222
223
void
224
MM_EnvironmentDelegate::assumeExclusiveVMAccess(uintptr_t exclusiveCount)
225
{
226
Assert_MM_true(exclusiveCount >= 1);
227
Assert_MM_true(0 == (_vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS));
228
Assert_MM_true(0 == _vmThread->omrVMThread->exclusiveCount);
229
230
_vmThread->omrVMThread->exclusiveCount = exclusiveCount;
231
VM_VMAccess::setPublicFlags(_vmThread, J9_PUBLIC_FLAGS_VM_ACCESS);
232
}
233
234
void
235
MM_EnvironmentDelegate::releaseCriticalHeapAccess(uintptr_t *data)
236
{
237
VM_VMAccess::setPublicFlags(_vmThread, J9_PUBLIC_FLAGS_NOT_AT_SAFE_POINT);
238
MM_JNICriticalRegion::releaseAccess(_vmThread, data);
239
}
240
241
void
242
MM_EnvironmentDelegate::reacquireCriticalHeapAccess(uintptr_t data)
243
{
244
MM_JNICriticalRegion::reacquireAccess(_vmThread, data);
245
VM_VMAccess::clearPublicFlags(_vmThread, J9_PUBLIC_FLAGS_NOT_AT_SAFE_POINT);
246
}
247
248
void
249
MM_EnvironmentDelegate::forceOutOfLineVMAccess()
250
{
251
VM_VMAccess::setPublicFlags(_vmThread, J9_PUBLIC_FLAGS_DISABLE_INLINE_VM_ACCESS);
252
}
253
254
#if defined (J9VM_GC_THREAD_LOCAL_HEAP)
255
/**
256
* Disable inline TLH allocates by hiding the real heap top address from
257
* JIT/Interpreter in realHeapTop and setting HeapTop == heapALloc so TLH
258
* looks full.
259
*
260
*/
261
void
262
MM_EnvironmentDelegate::disableInlineTLHAllocate()
263
{
264
J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;
265
if (NULL == tlh->realHeapTop) {
266
tlh->realHeapTop = _vmThread->heapTop;
267
}
268
_vmThread->heapTop = _vmThread->heapAlloc;
269
270
#if defined(J9VM_GC_NON_ZERO_TLH)
271
tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;
272
if (NULL == tlh->realHeapTop) {
273
tlh->realHeapTop = _vmThread->nonZeroHeapTop;
274
}
275
_vmThread->nonZeroHeapTop = _vmThread->nonZeroHeapAlloc;
276
#endif /* defined(J9VM_GC_NON_ZERO_TLH) */
277
}
278
279
/**
280
* Re-enable inline TLH allocate by restoring heapTop from realHeapTop
281
*/
282
void
283
MM_EnvironmentDelegate::enableInlineTLHAllocate()
284
{
285
J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;
286
if (NULL != tlh->realHeapTop) {
287
_vmThread->heapTop = tlh->realHeapTop;
288
tlh->realHeapTop = NULL;
289
}
290
291
#if defined(J9VM_GC_NON_ZERO_TLH)
292
tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;
293
if (NULL != tlh->realHeapTop) {
294
_vmThread->nonZeroHeapTop = tlh->realHeapTop;
295
tlh->realHeapTop = NULL;
296
}
297
#endif /* defined(J9VM_GC_NON_ZERO_TLH) */
298
}
299
300
/**
301
* Determine if inline TLH allocate is enabled; its enabled if realheapTop is NULL.
302
* @return TRUE if inline TLH allocates currently enabled for this thread; FALSE otherwise
303
*/
304
bool
305
MM_EnvironmentDelegate::isInlineTLHAllocateEnabled()
306
{
307
J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;
308
bool result = (NULL == tlh->realHeapTop);
309
310
#if defined(J9VM_GC_NON_ZERO_TLH)
311
tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;
312
result = result && (NULL == tlh->realHeapTop);
313
#endif /* defined(J9VM_GC_NON_ZERO_TLH) */
314
315
return result;
316
}
317
318
319
void
320
MM_EnvironmentDelegate::setTLHSamplingTop(uintptr_t size)
321
{
322
uintptr_t max = 0;
323
J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;
324
if (NULL != tlh->realHeapTop) {
325
max = tlh->realHeapTop - _vmThread->heapAlloc;
326
} else {
327
max = _vmThread->heapTop - _vmThread->heapAlloc;
328
}
329
330
if (max > size) {
331
if (NULL == tlh->realHeapTop) {
332
tlh->realHeapTop = _vmThread->heapTop;
333
}
334
_vmThread->heapTop = _vmThread->heapAlloc + size;
335
} else {
336
if (NULL != tlh->realHeapTop) {
337
_vmThread->heapTop = tlh->realHeapTop;
338
tlh->realHeapTop = NULL;
339
}
340
}
341
342
#if defined(J9VM_GC_NON_ZERO_TLH)
343
/* TODO: need to find better way set TLH sampling Top for NON ZERO case */
344
tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;
345
if (NULL != tlh->realHeapTop) {
346
max = tlh->realHeapTop - _vmThread->nonZeroHeapAlloc;
347
} else {
348
max = _vmThread->nonZeroHeapTop - _vmThread->nonZeroHeapAlloc;
349
}
350
351
if (max > size) {
352
if (NULL == tlh->realHeapTop) {
353
tlh->realHeapTop = _vmThread->nonZeroHeapTop;
354
}
355
_vmThread->nonZeroHeapTop = _vmThread->nonZeroHeapAlloc + size;
356
} else {
357
if (NULL != tlh->realHeapTop) {
358
_vmThread->nonZeroHeapTop = tlh->realHeapTop;
359
tlh->realHeapTop = NULL;
360
}
361
}
362
363
#endif /* defined(J9VM_GC_NON_ZERO_TLH) */
364
}
365
366
void
367
MM_EnvironmentDelegate::resetTLHSamplingTop()
368
{
369
enableInlineTLHAllocate();
370
}
371
372
uintptr_t
373
MM_EnvironmentDelegate::getAllocatedSizeInsideTLH()
374
{
375
uintptr_t ret = 0;
376
J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;
377
ret += _vmThread->heapAlloc - tlh->heapBase;
378
#if defined(J9VM_GC_NON_ZERO_TLH)
379
tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;
380
ret += _vmThread->nonZeroHeapAlloc - tlh->heapBase;
381
#endif /* defined(J9VM_GC_NON_ZERO_TLH) */
382
return ret;
383
}
384
385
#endif /* J9VM_GC_THREAD_LOCAL_HEAP */
386
387
388