Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/MetronomeDelegate.hpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2019, 2020 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
#if !defined(METRONOMEDELEGATE_HPP_)
24
#define METRONOMEDELEGATE_HPP_
25
26
#include "j9.h"
27
#include "j9cfg.h"
28
29
#if defined(J9VM_GC_REALTIME)
30
31
#include "BaseNonVirtual.hpp"
32
#include "EnvironmentRealtime.hpp"
33
#include "GCExtensions.hpp"
34
#include "RealtimeAccessBarrier.hpp"
35
#include "RealtimeMarkingScheme.hpp"
36
#include "ReferenceObjectBuffer.hpp"
37
#include "Scheduler.hpp"
38
39
class MM_HeapRegionDescriptorRealtime;
40
class MM_RealtimeMarkingSchemeRootMarker;
41
class MM_RealtimeRootScanner;
42
class MM_Scheduler;
43
44
class MM_MetronomeDelegate : public MM_BaseNonVirtual
45
{
46
private:
47
MM_GCExtensions *_extensions;
48
MM_RealtimeGC *_realtimeGC;
49
J9JavaVM *_javaVM;
50
MM_Scheduler *_scheduler;
51
MM_RealtimeMarkingScheme *_markingScheme;
52
UDATA _vmResponsesRequiredForExclusiveVMAccess; /**< Used to support the (request/wait)ExclusiveVMAccess methods. */
53
UDATA _jniResponsesRequiredForExclusiveVMAccess; /**< Used to support the (request/wait)ExclusiveVMAccess methods. */
54
55
public:
56
void yieldWhenRequested(MM_EnvironmentBase *env);
57
static int J9THREAD_PROC metronomeAlarmThreadWrapper(void* userData);
58
static uintptr_t signalProtectedFunction(J9PortLibrary *privatePortLibrary, void* userData);
59
60
MM_MetronomeDelegate(MM_EnvironmentBase *env) :
61
_extensions(MM_GCExtensions::getExtensions(env)),
62
_realtimeGC(NULL),
63
_javaVM((J9JavaVM*)env->getOmrVM()->_language_vm) {}
64
65
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
66
bool _unmarkedImpliesClasses; /**< if true the mark bit can be used to check is class alive or not */
67
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
68
bool _unmarkedImpliesCleared;
69
bool _unmarkedImpliesStringsCleared; /**< If true, we can assume that unmarked strings in the string table will be cleared */
70
71
#if defined(J9VM_GC_FINALIZATION)
72
bool _finalizationRequired;
73
#endif /* J9VM_GC_FINALIZATION */
74
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
75
bool _dynamicClassUnloadingEnabled;
76
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
77
78
bool initialize(MM_EnvironmentBase *env);
79
void tearDown(MM_EnvironmentBase *env);
80
81
bool allocateAndInitializeReferenceObjectLists(MM_EnvironmentBase *env);
82
bool allocateAndInitializeUnfinalizedObjectLists(MM_EnvironmentBase *env);
83
bool allocateAndInitializeOwnableSynchronizerObjectLists(MM_EnvironmentBase *env);
84
85
#if defined(J9VM_GC_FINALIZATION)
86
bool isFinalizationRequired() { return _finalizationRequired; }
87
#endif /* J9VM_GC_FINALIZATION */
88
89
void mainSetupForGC(MM_EnvironmentBase *env);
90
void mainCleanupAfterGC(MM_EnvironmentBase *env);
91
void incrementalCollectStart(MM_EnvironmentRealtime *env);
92
void incrementalCollect(MM_EnvironmentRealtime *env);
93
void doAuxiliaryGCWork(MM_EnvironmentBase *env);
94
void clearGCStats();
95
void clearGCStatsEnvironment(MM_EnvironmentRealtime *env);
96
void mergeGCStats(MM_EnvironmentRealtime *env);
97
uintptr_t getSplitArraysProcessed(MM_EnvironmentRealtime *env);
98
void reportSyncGCEnd(MM_EnvironmentBase *env);
99
100
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
101
MMINLINE bool isDynamicClassUnloadingEnabled() { return _dynamicClassUnloadingEnabled; };
102
void unloadDeadClassLoaders(MM_EnvironmentBase *env);
103
104
void reportClassUnloadingStart(MM_EnvironmentBase *env);
105
void reportClassUnloadingEnd(MM_EnvironmentBase *env);
106
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
107
108
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
109
/**
110
* Perform initial cleanup for classloader unloading. The current thread has exclusive access.
111
* The J9AccClassDying bit is set and J9HOOK_VM_CLASS_UNLOAD is triggered for each class that will be unloaded.
112
* The J9_GC_CLASS_LOADER_DEAD bit is set for each class loader that will be unloaded.
113
* J9HOOK_VM_CLASSES_UNLOAD is triggered if any classes will be unloaded.
114
*
115
* @param env[in] the main GC thread
116
* @param classUnloadCountResult[out] returns the number of classes about to be unloaded
117
* @param anonymousClassUnloadCount[out] returns the number of anonymous classes about to be unloaded
118
* @param classLoaderUnloadCountResult[out] returns the number of class loaders about to be unloaded
119
* @param classLoaderUnloadListResult[out] returns a linked list of class loaders about to be unloaded
120
*/
121
void processDyingClasses(MM_EnvironmentRealtime *env, UDATA* classUnloadCountResult, UDATA* anonymousClassUnloadCount, UDATA* classLoaderUnloadCountResult, J9ClassLoader** classLoaderUnloadListResult);
122
void processUnlinkedClassLoaders(MM_EnvironmentBase *env, J9ClassLoader *deadClassLoaders);
123
void updateClassUnloadStats(MM_EnvironmentBase *env, UDATA classUnloadCount, UDATA anonymousClassUnloadCount, UDATA classLoaderUnloadCount);
124
125
/**
126
* Scan classloader for dying classes and add them to the list
127
* @param env[in] the current thread
128
* @param classLoader[in] the list of class loaders to clean up
129
* @param setAll[in] bool if true if all classes must be set dying, if false unmarked classes only
130
* @param classUnloadListStart[in] root of list dying classes should be added to
131
* @param classUnloadCountOut[out] number of classes dying added to the list
132
* @return new root to list of dying classes
133
*/
134
J9Class *addDyingClassesToList(MM_EnvironmentRealtime *env, J9ClassLoader * classLoader, bool setAll, J9Class *classUnloadListStart, UDATA *classUnloadCountResult);
135
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
136
137
void yieldFromClassUnloading(MM_EnvironmentRealtime *env);
138
void lockClassUnloadMonitor(MM_EnvironmentRealtime *env);
139
void unlockClassUnloadMonitor(MM_EnvironmentRealtime *env);
140
141
UDATA getUnfinalizedObjectListCount(MM_EnvironmentBase *env) { return _extensions->gcThreadCount; }
142
UDATA getOwnableSynchronizerObjectListCount(MM_EnvironmentBase *env) { return _extensions->gcThreadCount; }
143
UDATA getReferenceObjectListCount(MM_EnvironmentBase *env) { return _extensions->gcThreadCount; }
144
145
void defaultMemorySpaceAllocated(MM_GCExtensionsBase *extensions, void* defaultMemorySpace);
146
MM_RealtimeAccessBarrier* allocateAccessBarrier(MM_EnvironmentBase *env);
147
void enableDoubleBarrier(MM_EnvironmentBase* env);
148
void disableDoubleBarrierOnThread(MM_EnvironmentBase* env, OMR_VMThread* vmThread);
149
void disableDoubleBarrier(MM_EnvironmentBase* env);
150
151
/* New methods */
152
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
153
bool doClassTracing(MM_EnvironmentRealtime* env);
154
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
155
bool doTracing(MM_EnvironmentRealtime* env);
156
157
/*
158
* These functions are used by classic Metronome gang-scheduling and
159
* also transitionally used for the parts of realtime that have not
160
* been made concurrent.
161
*/
162
void preRequestExclusiveVMAccess(OMR_VMThread *threadRequestingExclusive);
163
void postRequestExclusiveVMAccess(OMR_VMThread *threadRequestingExclusive);
164
uintptr_t requestExclusiveVMAccess(MM_EnvironmentBase *env, uintptr_t block, uintptr_t *gcPriority);
165
void waitForExclusiveVMAccess(MM_EnvironmentBase *env, bool waitRequired);
166
void acquireExclusiveVMAccess(MM_EnvironmentBase *env, bool waitRequired);
167
void releaseExclusiveVMAccess(MM_EnvironmentBase *env, bool releaseRequired);
168
169
void markLiveObjectsRoots(MM_EnvironmentRealtime *env);
170
void markLiveObjectsScan(MM_EnvironmentRealtime *env);
171
void markLiveObjectsComplete(MM_EnvironmentRealtime *env);
172
void checkReferenceBuffer(MM_EnvironmentRealtime *env);
173
void setUnmarkedImpliesCleared();
174
void unsetUnmarkedImpliesCleared();
175
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
176
MMINLINE void
177
markClassOfObject(MM_EnvironmentRealtime *env, J9Object *objectPtr)
178
{
179
markClassNoCheck(env, J9GC_J9OBJECT_CLAZZ(objectPtr, env));
180
}
181
182
MMINLINE bool
183
markClassNoCheck(MM_EnvironmentRealtime *env, J9Class *clazz)
184
{
185
bool result = false;
186
if (J9_ARE_ANY_BITS_SET(J9CLASS_EXTENDED_FLAGS(clazz), J9ClassIsAnonymous)) {
187
/*
188
* If class is anonymous it's classloader will not be rescanned
189
* so class object should be marked directly
190
*/
191
result = _markingScheme->markObject(env, clazz->classObject);
192
} else {
193
result = _markingScheme->markObject(env, clazz->classLoader->classLoaderObject);
194
}
195
return result;
196
}
197
bool markClass(MM_EnvironmentRealtime *env, J9Class *objectPtr);
198
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
199
200
MMINLINE uintptr_t
201
scanPointerArraylet(MM_EnvironmentRealtime *env, fomrobject_t *arraylet)
202
{
203
fomrobject_t *startScanPtr = arraylet;
204
fomrobject_t *endScanPtr = (fomrobject_t*)((uintptr_t)startScanPtr + _javaVM->arrayletLeafSize);
205
return scanPointerRange(env, startScanPtr, endScanPtr);
206
}
207
208
MMINLINE uintptr_t
209
scanObject(MM_EnvironmentRealtime *env, omrobjectptr_t objectPtr)
210
{
211
UDATA pointersScanned = 0;
212
switch(_extensions->objectModel.getScanType(objectPtr)) {
213
case GC_ObjectModel::SCAN_MIXED_OBJECT_LINKED:
214
case GC_ObjectModel::SCAN_ATOMIC_MARKABLE_REFERENCE_OBJECT:
215
case GC_ObjectModel::SCAN_MIXED_OBJECT:
216
case GC_ObjectModel::SCAN_OWNABLESYNCHRONIZER_OBJECT:
217
case GC_ObjectModel::SCAN_CLASS_OBJECT:
218
case GC_ObjectModel::SCAN_CLASSLOADER_OBJECT:
219
pointersScanned = scanMixedObject(env, objectPtr);
220
break;
221
case GC_ObjectModel::SCAN_POINTER_ARRAY_OBJECT:
222
pointersScanned = scanPointerArrayObject(env, (J9IndexableObject *)objectPtr);
223
break;
224
case GC_ObjectModel::SCAN_REFERENCE_MIXED_OBJECT:
225
pointersScanned = scanReferenceMixedObject(env, objectPtr);
226
break;
227
case GC_ObjectModel::SCAN_PRIMITIVE_ARRAY_OBJECT:
228
pointersScanned = 0;
229
break;
230
default:
231
Assert_MM_unreachable();
232
}
233
234
return pointersScanned;
235
}
236
237
MMINLINE UDATA
238
scanPointerRange(MM_EnvironmentRealtime *env, fj9object_t *startScanPtr, fj9object_t *endScanPtr)
239
{
240
UDATA pointerField = 0;
241
242
if (env->compressObjectReferences()) {
243
uint32_t *scanPtr = (uint32_t*)startScanPtr;
244
uint32_t *endPtr = (uint32_t*)endScanPtr;
245
pointerField = endPtr - scanPtr;
246
while(scanPtr < endPtr) {
247
GC_SlotObject slotObject(_javaVM->omrVM, (fj9object_t*)scanPtr);
248
_markingScheme->markObject(env, slotObject.readReferenceFromSlot());
249
scanPtr++;
250
}
251
} else {
252
uintptr_t *scanPtr = (uintptr_t*)startScanPtr;
253
uintptr_t *endPtr = (uintptr_t*)endScanPtr;
254
pointerField = endPtr - scanPtr;
255
while(scanPtr < endPtr) {
256
GC_SlotObject slotObject(_javaVM->omrVM, (fj9object_t*)scanPtr);
257
_markingScheme->markObject(env, slotObject.readReferenceFromSlot());
258
scanPtr++;
259
}
260
}
261
262
return pointerField;
263
}
264
265
MMINLINE UDATA
266
scanMixedObject(MM_EnvironmentRealtime *env, J9Object *objectPtr)
267
{
268
/* Object slots */
269
270
bool const compressed = env->compressObjectReferences();
271
fj9object_t *scanPtr = _extensions->mixedObjectModel.getHeadlessObject(objectPtr);
272
UDATA objectSize = _extensions->mixedObjectModel.getSizeInBytesWithHeader(objectPtr);
273
fj9object_t *endScanPtr = (fj9object_t*)(((U_8 *)objectPtr) + objectSize);
274
UDATA *descriptionPtr;
275
UDATA descriptionBits;
276
UDATA descriptionIndex;
277
#if defined(J9VM_GC_LEAF_BITS)
278
UDATA *leafPtr;
279
UDATA leafBits;
280
#endif /* J9VM_GC_LEAF_BITS */
281
282
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
283
if(isDynamicClassUnloadingEnabled()) {
284
markClassOfObject(env, objectPtr);
285
}
286
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
287
288
descriptionPtr = (UDATA *)J9GC_J9OBJECT_CLAZZ(objectPtr, env)->instanceDescription;
289
#if defined(J9VM_GC_LEAF_BITS)
290
leafPtr = (UDATA *)J9GC_J9OBJECT_CLAZZ(objectPtr, env)->instanceLeafDescription;
291
#endif /* J9VM_GC_LEAF_BITS */
292
293
if(((UDATA)descriptionPtr) & 1) {
294
descriptionBits = ((UDATA)descriptionPtr) >> 1;
295
#if defined(J9VM_GC_LEAF_BITS)
296
leafBits = ((UDATA)leafPtr) >> 1;
297
#endif /* J9VM_GC_LEAF_BITS */
298
} else {
299
descriptionBits = *descriptionPtr++;
300
#if defined(J9VM_GC_LEAF_BITS)
301
leafBits = *leafPtr++;
302
#endif /* J9VM_GC_LEAF_BITS */
303
}
304
descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;
305
306
UDATA pointerFields = 0;
307
while(scanPtr < endScanPtr) {
308
/* Determine if the slot should be processed */
309
if(descriptionBits & 1) {
310
pointerFields++;
311
GC_SlotObject slotObject(_javaVM->omrVM, scanPtr);
312
#if defined(J9VM_GC_LEAF_BITS)
313
_markingScheme->markObject(env, slotObject.readReferenceFromSlot(), 1 == (leafBits & 1));
314
#else /* J9VM_GC_LEAF_BITS */
315
_markingScheme->markObject(env, slotObject.readReferenceFromSlot(), false);
316
#endif /* J9VM_GC_LEAF_BITS */
317
}
318
descriptionBits >>= 1;
319
#if defined(J9VM_GC_LEAF_BITS)
320
leafBits >>= 1;
321
#endif /* J9VM_GC_LEAF_BITS */
322
if(descriptionIndex-- == 0) {
323
descriptionBits = *descriptionPtr++;
324
#if defined(J9VM_GC_LEAF_BITS)
325
leafBits = *leafPtr++;
326
#endif /* J9VM_GC_LEAF_BITS */
327
descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;
328
}
329
scanPtr = GC_SlotObject::addToSlotAddress(scanPtr, 1, compressed);
330
}
331
332
env->incScannedObjects();
333
334
return pointerFields;
335
}
336
337
MMINLINE UDATA
338
scanPointerArrayObject(MM_EnvironmentRealtime *env, J9IndexableObject *objectPtr)
339
{
340
UDATA pointerFields = 0;
341
bool const compressed = env->compressObjectReferences();
342
343
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
344
if(isDynamicClassUnloadingEnabled()) {
345
markClassOfObject(env, (J9Object *)objectPtr);
346
}
347
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
348
349
bool isContiguous = _extensions->indexableObjectModel.isInlineContiguousArraylet(objectPtr);
350
351
/* Very small arrays cannot be set as scanned (no scanned bit in Mark Map reserved for them) */
352
bool canSetAsScanned = (isContiguous
353
&& (_extensions->minArraySizeToSetAsScanned <= _extensions->indexableObjectModel.arrayletSize(objectPtr, 0)));
354
355
if (canSetAsScanned && _markingScheme->isScanned((J9Object *)objectPtr)) {
356
/* Already scanned by ref array copy optimization */
357
return pointerFields;
358
}
359
360
/* if NUA is enabled, separate path for contiguous arrays */
361
UDATA sizeInElements = _extensions->indexableObjectModel.getSizeInElements(objectPtr);
362
if (isContiguous || (0 == sizeInElements)) {
363
fj9object_t *startScanPtr = (fj9object_t *)_extensions->indexableObjectModel.getDataPointerForContiguous(objectPtr);
364
fj9object_t *endScanPtr = GC_SlotObject::addToSlotAddress(startScanPtr, sizeInElements, compressed);
365
pointerFields += scanPointerRange(env, startScanPtr, endScanPtr);
366
} else {
367
fj9object_t *arrayoid = _extensions->indexableObjectModel.getArrayoidPointer(objectPtr);
368
UDATA numArraylets = _extensions->indexableObjectModel.numArraylets(objectPtr);
369
for (UDATA i=0; i<numArraylets; i++) {
370
UDATA arrayletSize = _extensions->indexableObjectModel.arrayletSize(objectPtr, i);
371
/* need to check leaf pointer because this can be a partially allocated arraylet (not all leafs are allocated) */
372
GC_SlotObject slotObject(_javaVM->omrVM, GC_SlotObject::addToSlotAddress(arrayoid, i, compressed));
373
fj9object_t *startScanPtr = (fj9object_t*) (slotObject.readReferenceFromSlot());
374
if (NULL != startScanPtr) {
375
fj9object_t *endScanPtr = (fj9object_t*)((uintptr_t)startScanPtr + arrayletSize);
376
if (i == (numArraylets - 1)) {
377
pointerFields += scanPointerRange(env, startScanPtr, endScanPtr);
378
if (canSetAsScanned) {
379
_markingScheme->setScanAtomic((J9Object *)objectPtr);
380
}
381
} else {
382
env->getWorkStack()->push(env, (void *)ARRAYLET_TO_ITEM(startScanPtr));
383
}
384
}
385
}
386
}
387
388
/* check for yield if we've actually scanned a leaf */
389
if (0 != pointerFields) {
390
_scheduler->condYieldFromGC(env);
391
}
392
393
env->incScannedObjects();
394
395
return pointerFields;
396
}
397
398
MMINLINE UDATA
399
scanReferenceMixedObject(MM_EnvironmentRealtime *env, J9Object *objectPtr)
400
{
401
bool const compressed = env->compressObjectReferences();
402
fj9object_t *scanPtr = _extensions->mixedObjectModel.getHeadlessObject(objectPtr);
403
UDATA objectSize = _extensions->mixedObjectModel.getSizeInBytesWithHeader(objectPtr);
404
fj9object_t *endScanPtr = (fj9object_t*)(((U_8 *)objectPtr) + objectSize);
405
UDATA *descriptionPtr;
406
UDATA descriptionBits;
407
UDATA descriptionIndex;
408
#if defined(J9VM_GC_LEAF_BITS)
409
UDATA *leafPtr;
410
UDATA leafBits;
411
#endif /* J9VM_GC_LEAF_BITS */
412
413
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
414
if(isDynamicClassUnloadingEnabled()) {
415
markClassOfObject(env, objectPtr);
416
}
417
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
418
419
descriptionPtr = (UDATA *)J9GC_J9OBJECT_CLAZZ(objectPtr, env)->instanceDescription;
420
#if defined(J9VM_GC_LEAF_BITS)
421
leafPtr = (UDATA *)J9GC_J9OBJECT_CLAZZ(objectPtr, env)->instanceLeafDescription;
422
#endif /* J9VM_GC_LEAF_BITS */
423
424
if(((UDATA)descriptionPtr) & 1) {
425
descriptionBits = ((UDATA)descriptionPtr) >> 1;
426
#if defined(J9VM_GC_LEAF_BITS)
427
leafBits = ((UDATA)leafPtr) >> 1;
428
#endif /* J9VM_GC_LEAF_BITS */
429
} else {
430
descriptionBits = *descriptionPtr++;
431
#if defined(J9VM_GC_LEAF_BITS)
432
leafBits = *leafPtr++;
433
#endif /* J9VM_GC_LEAF_BITS */
434
}
435
descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;
436
437
I_32 referenceState = J9GC_J9VMJAVALANGREFERENCE_STATE(env, objectPtr);
438
UDATA referenceObjectType = J9CLASS_FLAGS(J9GC_J9OBJECT_CLAZZ(objectPtr, env)) & J9AccClassReferenceMask;
439
UDATA referenceObjectOptions = env->_cycleState->_referenceObjectOptions;
440
bool isReferenceCleared = (GC_ObjectModel::REF_STATE_CLEARED == referenceState) || (GC_ObjectModel::REF_STATE_ENQUEUED == referenceState);
441
bool referentMustBeMarked = isReferenceCleared;
442
bool referentMustBeCleared = false;
443
444
switch (referenceObjectType) {
445
case J9AccClassReferenceWeak:
446
referentMustBeCleared = (0 != (referenceObjectOptions & MM_CycleState::references_clear_weak));
447
break;
448
case J9AccClassReferenceSoft:
449
referentMustBeCleared = (0 != (referenceObjectOptions & MM_CycleState::references_clear_soft));
450
referentMustBeMarked = referentMustBeMarked || (
451
((0 == (referenceObjectOptions & MM_CycleState::references_soft_as_weak))
452
&& ((UDATA)J9GC_J9VMJAVALANGSOFTREFERENCE_AGE(env, objectPtr) < _extensions->getDynamicMaxSoftReferenceAge())));
453
break;
454
case J9AccClassReferencePhantom:
455
referentMustBeCleared = (0 != (referenceObjectOptions & MM_CycleState::references_clear_phantom));
456
break;
457
default:
458
Assert_MM_unreachable();
459
}
460
461
GC_SlotObject referentPtr(_javaVM->omrVM, J9GC_J9VMJAVALANGREFERENCE_REFERENT_ADDRESS(env, objectPtr));
462
463
if (referentMustBeCleared) {
464
/* Discovering this object at this stage in the GC indicates that it is being resurrected. Clear its referent slot. */
465
referentPtr.writeReferenceToSlot(NULL);
466
/* record that the reference has been cleared if it's not already in the cleared or enqueued state */
467
if (!isReferenceCleared) {
468
J9GC_J9VMJAVALANGREFERENCE_STATE(env, objectPtr) = GC_ObjectModel::REF_STATE_CLEARED;
469
}
470
} else {
471
/* we don't need to process cleared or enqueued references */
472
if (!isReferenceCleared) {
473
env->getGCEnvironment()->_referenceObjectBuffer->add(env, objectPtr);
474
}
475
}
476
477
UDATA pointerFields = 0;
478
while(scanPtr < endScanPtr) {
479
/* Determine if the slot should be processed */
480
if((descriptionBits & 1) && ((scanPtr != referentPtr.readAddressFromSlot()) || referentMustBeMarked)) {
481
pointerFields++;
482
GC_SlotObject slotObject(_javaVM->omrVM, scanPtr);
483
#if defined(J9VM_GC_LEAF_BITS)
484
_markingScheme->markObject(env, slotObject.readReferenceFromSlot(), 1 == (leafBits & 1));
485
#else /* J9VM_GC_LEAF_BITS */
486
_markingScheme->markObject(env, slotObject.readReferenceFromSlot(), false);
487
#endif /* J9VM_GC_LEAF_BITS */
488
}
489
descriptionBits >>= 1;
490
#if defined(J9VM_GC_LEAF_BITS)
491
leafBits >>= 1;
492
#endif /* J9VM_GC_LEAF_BITS */
493
if(descriptionIndex-- == 0) {
494
descriptionBits = *descriptionPtr++;
495
#if defined(J9VM_GC_LEAF_BITS)
496
leafBits = *leafPtr++;
497
#endif /* J9VM_GC_LEAF_BITS */
498
descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;
499
}
500
scanPtr = GC_SlotObject::addToSlotAddress(scanPtr, 1, compressed);
501
}
502
503
env->incScannedObjects();
504
505
return pointerFields;
506
}
507
508
#if defined(J9VM_GC_FINALIZATION)
509
void scanUnfinalizedObjects(MM_EnvironmentRealtime *env);
510
#endif /* J9VM_GC_FINALIZATION */
511
512
/**
513
* Wraps the MM_RootScanner::scanOwnableSynchronizerObjects method to disable yielding during the scan
514
* then yield after scanning.
515
* @see MM_RootScanner::scanOwnableSynchronizerObjects()
516
*/
517
void scanOwnableSynchronizerObjects(MM_EnvironmentRealtime *env);
518
519
private:
520
/**
521
* Called by the root scanner to scan all WeakReference objects discovered by the mark phase,
522
* clearing and enqueuing them if necessary.
523
* @param env[in] the current thread
524
*/
525
void scanWeakReferenceObjects(MM_EnvironmentRealtime *env);
526
/**
527
* Process the list of reference objects recorded in the specified list.
528
* References with unmarked referents are cleared and optionally enqueued.
529
* SoftReferences have their ages incremented.
530
* @param env[in] the current thread
531
* @param region[in] the region all the objects in the list belong to
532
* @param headOfList[in] the first object in the linked list
533
*/
534
void processReferenceList(MM_EnvironmentRealtime *env, MM_HeapRegionDescriptorRealtime* region, J9Object* headOfList, MM_ReferenceStats *referenceStats);
535
536
/**
537
* Called by the root scanner to scan all SoftReference objects discovered by the mark phase,
538
* clearing and enqueuing them if necessary.
539
* @param env[in] the current thread
540
*/
541
void scanSoftReferenceObjects(MM_EnvironmentRealtime *env);
542
543
/**
544
* Called by the root scanner to scan all PhantomReference objects discovered by the mark phase,
545
* clearing and enqueuing them if necessary.
546
* @param env[in] the current thread
547
*/
548
void scanPhantomReferenceObjects(MM_EnvironmentRealtime *env);
549
550
/*
551
* Friends
552
*/
553
friend class MM_RealtimeGC;
554
friend class MM_RealtimeMarkingSchemeRootClearer;
555
};
556
557
#endif /* defined(J9VM_GC_REALTIME) */
558
559
#endif /* defined(METRONOMEDELEGATE_HPP_) */
560
561
562