Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/ConcurrentMarkingDelegate.cpp
5985 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
#include "ConcurrentMarkingDelegate.hpp"
24
#if defined(OMR_GC_MODRON_CONCURRENT_MARK)
25
#include "AsyncCallbackHandler.hpp"
26
#include "ClassLoaderIterator.hpp"
27
#include "ConfigurationDelegate.hpp"
28
#include "FinalizeListManager.hpp"
29
#include "Heap.hpp"
30
#include "HeapRegionDescriptorStandard.hpp"
31
#include "HeapRegionIteratorStandard.hpp"
32
#include "ReferenceObjectList.hpp"
33
#include "StackSlotValidator.hpp"
34
#include "VMInterface.hpp"
35
#include "VMThreadListIterator.hpp"
36
37
/**
38
* Concurrents stack slot iterator.
39
* Called for each slot in a threads active stack frames which contains a object reference.
40
*
41
* @param objectIndirect
42
* @param localdata
43
* @param isDerivedPointer
44
* @param objectIndirectBase
45
*/
46
void
47
concurrentStackSlotIterator(J9JavaVM *javaVM, omrobjectptr_t *objectIndirect, void *localData, J9StackWalkState *walkState, const void *stackLocation)
48
{
49
MM_ConcurrentMarkingDelegate::markSchemeStackIteratorData *data = (MM_ConcurrentMarkingDelegate::markSchemeStackIteratorData *)localData;
50
51
omrobjectptr_t object = *objectIndirect;
52
if (data->env->getExtensions()->heap->objectIsInGap(object)) {
53
/* CMVC 136483: Ensure that the object is not in the gap of a split heap (stack-allocated object) since we can't mark that part of the address space */
54
Assert_MM_validStackSlot(MM_StackSlotValidator(MM_StackSlotValidator::NOT_ON_HEAP, object, stackLocation, walkState).validate(data->env));
55
} else if (data->markingScheme->isHeapObject(object)) {
56
/* heap object - validate and mark */
57
Assert_MM_validStackSlot(MM_StackSlotValidator(0, object, stackLocation, walkState).validate(data->env));
58
data->markingScheme->markObject(data->env, object);
59
} else if (NULL != object) {
60
/* stack object - just validate */
61
Assert_MM_validStackSlot(MM_StackSlotValidator(MM_StackSlotValidator::NOT_ON_HEAP, object, stackLocation, walkState).validate(data->env));
62
}
63
}
64
65
bool
66
MM_ConcurrentMarkingDelegate::initialize(MM_EnvironmentBase *env, MM_ConcurrentGC *collector)
67
{
68
MM_GCExtensionsBase *extensions = env->getExtensions();
69
_javaVM = (J9JavaVM *)extensions->getOmrVM()->_language_vm;
70
_objectModel = &(extensions->objectModel);
71
_markingScheme = collector->getMarkingScheme();
72
_collector = collector;
73
return true;
74
}
75
76
void
77
MM_ConcurrentMarkingDelegate::signalThreadsToTraceStacks(MM_EnvironmentBase *env)
78
{
79
uintptr_t threadCount = 0;
80
81
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
82
GC_VMInterface::lockVMThreadList(extensions);
83
84
GC_VMThreadListIterator vmThreadListIterator(_javaVM);
85
J9VMThread *walkThread;
86
87
while((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {
88
MM_AsyncCallbackHandler::signalThreadForCallback(walkThread);
89
threadCount += 1;
90
}
91
GC_VMInterface::unlockVMThreadList(extensions);
92
93
_collector->getConcurrentGCStats()->setThreadsToScanCount(threadCount);
94
}
95
96
void
97
MM_ConcurrentMarkingDelegate::signalThreadsToActivateWriteBarrier(MM_EnvironmentBase *env)
98
{
99
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
100
GC_VMInterface::lockVMThreadList(extensions);
101
102
J9VMThread *walkThread;
103
GC_VMThreadListIterator vmThreadListIterator(_javaVM);
104
while ((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {
105
walkThread->privateFlags |= J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE;
106
}
107
GC_VMInterface::unlockVMThreadList(extensions);
108
}
109
110
void
111
MM_ConcurrentMarkingDelegate::signalThreadsToDeactivateWriteBarrier(MM_EnvironmentBase *env)
112
{
113
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(_javaVM);
114
if (extensions->optimizeConcurrentWB) {
115
GC_VMInterface::lockVMThreadList(extensions);
116
GC_VMThreadListIterator vmThreadListIterator(_javaVM);
117
J9VMThread *walkThread;
118
119
/* Reset vmThread flag so mutators don't dirty cards or run write barriers until next concurrent KO */
120
while ((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {
121
walkThread->privateFlags &= ~J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE;
122
}
123
GC_VMInterface::unlockVMThreadList(extensions);
124
}
125
}
126
127
bool
128
MM_ConcurrentMarkingDelegate::scanThreadRoots(MM_EnvironmentBase *env)
129
{
130
J9VMThread *vmThread = (J9VMThread *)env->getLanguageVMThread();
131
Assert_GC_true_with_message(env, vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n",
132
_collector->getConcurrentGCStats()->getExecutionMode());
133
134
GC_VMThreadIterator vmThreadIterator(vmThread);
135
omrobjectptr_t *slotPtr;
136
uintptr_t slotNum = 0;
137
while (NULL != (slotPtr = vmThreadIterator.nextSlot())) {
138
slotNum +=1;
139
if (!_collector->isExclusiveAccessRequestWaitingSparseSample(env, slotNum)) {
140
omrobjectptr_t objectPtr = *slotPtr;
141
if (_markingScheme->isHeapObject(objectPtr) && !env->getExtensions()->heap->objectIsInGap(objectPtr)) {
142
_markingScheme->markObject(env, objectPtr);
143
} else if (NULL != objectPtr) {
144
Assert_MM_true(vmthreaditerator_state_monitor_records == vmThreadIterator.getState());
145
}
146
} else {
147
break;
148
}
149
}
150
151
markSchemeStackIteratorData localData;
152
localData.markingScheme = _markingScheme;
153
localData.env = env;
154
GC_VMThreadStackSlotIterator::scanSlots(vmThread, vmThread, (void *)&localData, concurrentStackSlotIterator, true, false);
155
156
return true;
157
}
158
159
/**
160
* Collect any JNI global references.
161
* Iterate over all JNI global references; mark and push any found.
162
*
163
*/
164
void
165
MM_ConcurrentMarkingDelegate::collectJNIRoots(MM_EnvironmentBase *env, bool *completedJNIRoots)
166
{
167
*completedJNIRoots = false;
168
169
Assert_GC_true_with_message(env, ((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());
170
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
171
GC_VMInterface::lockJNIGlobalReferences(extensions);
172
GC_PoolIterator jniGlobalReferenceIterator(_javaVM->jniGlobalReferences);
173
omrobjectptr_t *slotPtr;
174
uintptr_t slotNum = 0;
175
while((slotPtr = (omrobjectptr_t *)jniGlobalReferenceIterator.nextSlot()) != NULL) {
176
slotNum += 1;
177
if (_collector->isExclusiveAccessRequestWaitingSparseSample(env, slotNum)) {
178
goto quitTracingJNIRefs;
179
} else {
180
_markingScheme->markObject(env, *slotPtr);
181
}
182
}
183
184
*completedJNIRoots = true;
185
186
quitTracingJNIRefs:
187
GC_VMInterface::unlockJNIGlobalReferences(extensions);
188
}
189
190
/**
191
* Collect any roots in classes
192
* Iterate over all classes and mark and push all references
193
*
194
*/
195
void
196
MM_ConcurrentMarkingDelegate::collectClassRoots(MM_EnvironmentBase *env, bool *completedClassRoots, bool *classesMarkedAsRoots)
197
{
198
*completedClassRoots = false;
199
*classesMarkedAsRoots = false;
200
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
201
202
if (!setupClassScanning(env)) {
203
/* mark classes as roots, scanning classes is disabled by default */
204
*classesMarkedAsRoots = true;
205
206
Assert_GC_true_with_message(env, ((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());
207
208
GC_VMInterface::lockClasses(extensions);
209
210
GC_SegmentIterator segmentIterator(_javaVM->classMemorySegments, MEMORY_TYPE_RAM_CLASS);
211
J9MemorySegment *segment;
212
J9Class *clazz;
213
214
while((segment = segmentIterator.nextSegment()) != NULL) {
215
GC_ClassHeapIterator classHeapIterator(_javaVM, segment);
216
while((clazz = classHeapIterator.nextClass()) != NULL) {
217
if (env->isExclusiveAccessRequestWaiting()) {
218
goto quitMarkClasses;
219
} else {
220
_markingScheme->getMarkingDelegate()->scanClass(env, clazz);
221
}
222
}
223
}
224
225
*completedClassRoots = true;
226
227
quitMarkClasses:
228
GC_VMInterface::unlockClasses(extensions);
229
}
230
}
231
232
/**
233
* Mark all finalizable objects
234
* Iterate over finalizable list and mark and push all finalizable objects
235
*
236
*/
237
void
238
MM_ConcurrentMarkingDelegate::collectFinalizableRoots(MM_EnvironmentBase *env, bool *completedFinalizableRoots)
239
{
240
*completedFinalizableRoots = false;
241
242
Assert_GC_true_with_message(env, ((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());
243
244
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
245
GC_VMInterface::lockFinalizeList(extensions);
246
247
GC_FinalizeListManager * finalizeListManager = extensions->finalizeListManager;
248
{
249
/* walk finalizable objects created by the system class loader */
250
j9object_t systemObject = finalizeListManager->peekSystemFinalizableObject();
251
while (!env->isExclusiveAccessRequestWaiting() && (NULL != systemObject)) {
252
_markingScheme->markObject(env, systemObject);
253
systemObject = finalizeListManager->peekNextSystemFinalizableObject(systemObject);
254
}
255
}
256
257
{
258
/* walk finalizable objects created by all other class loaders*/
259
j9object_t defaultObject = finalizeListManager->peekDefaultFinalizableObject();
260
while (!env->isExclusiveAccessRequestWaiting() && (NULL != defaultObject)) {
261
_markingScheme->markObject(env, defaultObject);
262
defaultObject = finalizeListManager->peekNextDefaultFinalizableObject(defaultObject);
263
}
264
}
265
266
{
267
/* walk reference objects */
268
j9object_t referenceObject = finalizeListManager->peekReferenceObject();
269
while (!env->isExclusiveAccessRequestWaiting() && (NULL != referenceObject)) {
270
_markingScheme->markObject(env, referenceObject);
271
referenceObject = finalizeListManager->peekNextReferenceObject(referenceObject);
272
}
273
}
274
275
*completedFinalizableRoots = !env->isExclusiveAccessRequestWaiting();
276
277
GC_VMInterface::unlockFinalizeList(extensions);
278
}
279
280
/**
281
* Collect all roots in string table
282
* Iterate over string table and mark and push all strings
283
*
284
*/
285
void
286
MM_ConcurrentMarkingDelegate::collectStringRoots(MM_EnvironmentBase *env, bool *completedStringRoots, bool *collectedStringRoots)
287
{
288
*completedStringRoots = false;
289
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
290
*collectedStringRoots = !extensions->collectStringConstants;
291
if (*collectedStringRoots) {
292
/* CMVC 103513 - Do not mark strings as roots if extensions->collectStringConstants is set
293
* since this will not allow them to be collected unless the concurrent mark is aborted
294
* before we hit this point.
295
*/
296
MM_StringTable *stringTable = extensions->getStringTable();
297
298
Assert_GC_true_with_message(env, ((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE, "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());
299
300
for (uintptr_t tableIndex = 0; tableIndex < stringTable->getTableCount(); tableIndex++) {
301
302
stringTable->lockTable(tableIndex);
303
304
GC_HashTableIterator stringTableIterator(stringTable->getTable(tableIndex));
305
omrobjectptr_t* slotPtr;
306
307
while((slotPtr = (omrobjectptr_t *)stringTableIterator.nextSlot()) != NULL) {
308
if (env->isExclusiveAccessRequestWaiting()) {
309
stringTable->unlockTable(tableIndex);
310
goto quitMarkStrings;
311
} else {
312
_markingScheme->markObject(env, *slotPtr);
313
}
314
}
315
316
stringTable->unlockTable(tableIndex);
317
}
318
319
*completedStringRoots = true;
320
}
321
322
quitMarkStrings:
323
return;
324
}
325
326
void
327
MM_ConcurrentMarkingDelegate::abortCollection(MM_EnvironmentBase *env)
328
{
329
MM_HeapRegionDescriptorStandard *region = NULL;
330
GC_HeapRegionIteratorStandard regionIterator(env->getExtensions()->heap->getHeapRegionManager());
331
332
while(NULL != (region = regionIterator.nextRegion())) {
333
MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);
334
for (uintptr_t i = 0; i < regionExtension->_maxListIndex; i++) {
335
MM_ReferenceObjectList *list = &regionExtension->_referenceObjectLists[i];
336
list->resetLists();
337
}
338
}
339
}
340
341
342
bool
343
MM_ConcurrentMarkingDelegate::setupClassScanning(MM_EnvironmentBase *env)
344
{
345
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
346
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
347
MM_GCExtensions::DynamicClassUnloading dynamicClassUnloadingFlag = (MM_GCExtensions::DynamicClassUnloading )extensions->dynamicClassUnloading;
348
if (MM_GCExtensions::DYNAMIC_CLASS_UNLOADING_NEVER != dynamicClassUnloadingFlag) {
349
setConcurrentScanning(env);
350
return true;
351
}
352
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
353
354
return false;
355
}
356
357
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
358
uintptr_t
359
MM_ConcurrentMarkingDelegate::concurrentClassMark(MM_EnvironmentBase *env, bool *completedClassMark)
360
{
361
J9ClassLoader *classLoader;
362
uintptr_t sizeTraced = 0;
363
*completedClassMark = false;
364
365
Trc_MM_concurrentClassMarkStart(env->getLanguageVMThread());
366
367
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
368
369
Assert_GC_true_with_message(env, (((J9VMThread *)env->getLanguageVMThread())->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE) || (extensions->isSATBBarrierActive()), "MM_ConcurrentStats::_executionMode = %zu\n", _collector->getConcurrentGCStats()->getExecutionMode());
370
371
GC_VMInterface::lockClasses(extensions);
372
GC_VMInterface::lockClassLoaders(extensions);
373
374
MM_MarkingDelegate *markingDelegate = _markingScheme->getMarkingDelegate();
375
GC_ClassLoaderIterator classLoaderIterator(_javaVM->classLoaderBlocks);
376
while((classLoader = classLoaderIterator.nextSlot()) != NULL) {
377
/* skip dead and anonymous classloaders */
378
if ((0 == (classLoader->gcFlags & J9_GC_CLASS_LOADER_DEAD)) && (0 == (classLoader->flags & J9CLASSLOADER_ANON_CLASS_LOADER))) {
379
/* Check if the class loader has not been scanned but the class loader is live */
380
if( !(classLoader->gcFlags & J9_GC_CLASS_LOADER_SCANNED) && _markingScheme->isMarkedOutline(classLoader->classLoaderObject)) {
381
GC_ClassLoaderSegmentIterator segmentIterator(classLoader, MEMORY_TYPE_RAM_CLASS);
382
J9MemorySegment *segment = NULL;
383
J9Class *clazz;
384
385
while(NULL != (segment = segmentIterator.nextSegment())) {
386
GC_ClassHeapIterator classHeapIterator(_javaVM, segment);
387
while(NULL != (clazz = classHeapIterator.nextClass())) {
388
/* TODO CRGTMP investigate proper value here */
389
sizeTraced += sizeof(J9Class);
390
markingDelegate->scanClass(env, clazz);
391
if (env->isExclusiveAccessRequestWaiting()) { /* interrupt if exclusive access request is waiting */
392
goto quitConcurrentClassMark;
393
}
394
}
395
}
396
397
/* CMVC 131487 */
398
J9HashTableState walkState;
399
/*
400
* We believe that (NULL == classLoader->classHashTable) is set ONLY for DEAD class loader
401
* so, if this pointer happened to be NULL at this point let it crash here
402
*/
403
Assert_MM_true(NULL != classLoader->classHashTable);
404
clazz = _javaVM->internalVMFunctions->hashClassTableStartDo(classLoader, &walkState, 0);
405
while (NULL != clazz) {
406
sizeTraced += sizeof(uintptr_t);
407
_markingScheme->markObject(env, (j9object_t)clazz->classObject);
408
if (env->isExclusiveAccessRequestWaiting()) { /* interrupt if exclusive access request is waiting */
409
goto quitConcurrentClassMark;
410
}
411
clazz = _javaVM->internalVMFunctions->hashClassTableNextDo(&walkState);
412
}
413
414
if (NULL != classLoader->moduleHashTable) {
415
J9HashTableState moduleWalkState;
416
J9Module **modulePtr = (J9Module**)hashTableStartDo(classLoader->moduleHashTable, &moduleWalkState);
417
while (NULL != modulePtr) {
418
J9Module * const module = *modulePtr;
419
420
_markingScheme->markObject(env, (j9object_t)module->moduleObject);
421
if (NULL != module->moduleName) {
422
_markingScheme->markObject(env, (j9object_t)module->moduleName);
423
}
424
if (NULL != module->version) {
425
_markingScheme->markObject(env, (j9object_t)module->version);
426
}
427
if (env->isExclusiveAccessRequestWaiting()) { /* interrupt if exclusive access request is waiting */
428
goto quitConcurrentClassMark;
429
}
430
modulePtr = (J9Module**)hashTableNextDo(&moduleWalkState);
431
}
432
433
if (classLoader == _javaVM->systemClassLoader) {
434
_markingScheme->markObject(env, _javaVM->unamedModuleForSystemLoader->moduleObject);
435
}
436
}
437
438
classLoader->gcFlags |= J9_GC_CLASS_LOADER_SCANNED;
439
}
440
}
441
}
442
443
*completedClassMark = true;
444
445
quitConcurrentClassMark:
446
GC_VMInterface::unlockClassLoaders(extensions);
447
GC_VMInterface::unlockClasses(extensions);
448
449
return sizeTraced;
450
}
451
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
452
453
#endif /* defined(OMR_GC_MODRON_CONCURRENT_MARK) */
454
455