Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_base/ReferenceChainWalker.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 "ReferenceChainWalker.hpp"
24
25
#include "j9cfg.h"
26
#include "j9consts.h"
27
#include "omrgcconsts.h"
28
#include "j9cp.h"
29
#include "j9port.h"
30
#include "modron.h"
31
#include "omr.h"
32
33
#include "ClassIteratorClassSlots.hpp"
34
#include "ClassIteratorDeclarationOrder.hpp"
35
#include "EnvironmentBase.hpp"
36
#include "Forge.hpp"
37
#include "GCExtensions.hpp"
38
#include "Heap.hpp"
39
#include "HeapRegionIterator.hpp"
40
#include "MixedObjectDeclarationOrderIterator.hpp"
41
#include "ModronAssertions.h"
42
#include "ObjectHeapBufferedIterator.hpp"
43
#include "ObjectModel.hpp"
44
#include "PointerArrayIterator.hpp"
45
#include "SlotObject.hpp"
46
#include "VMThreadIterator.hpp"
47
48
class GC_HashTableIterator;
49
class GC_JVMTIObjectTagTableIterator;
50
class GC_VMClassSlotIterator;
51
class MM_HeapRegionDescriptor;
52
class MM_HeapRegionManager;
53
class MM_OwnableSynchronizerObjectList;
54
class MM_UnfinalizedObjectList;
55
56
#define TEMP_RCW_STACK_SIZE (10 * 1024 * 1024)
57
58
extern "C" {
59
/**
60
* Walk the reference chains starting at the root set, call user provided function.
61
* The user function will be called for each root with the type set to one of the
62
* J9GC_ROOT_TYPE_* values. A root may appear multiple times. The user function
63
* will be called for each reference once, with the type set to one of the
64
* J9GC_REFERENCE_TYPE_* values.
65
* @note This function requires the caller to already have exclusive.
66
* @param vmThread
67
* @param userCallback User function to be run for each root and reference
68
* @param userData Pointer to storage for userData.
69
*/
70
void
71
j9gc_ext_reachable_objects_do(
72
J9VMThread *vmThread,
73
J9MODRON_REFERENCE_CHAIN_WALKER_CALLBACK userCallback,
74
void *userData,
75
UDATA walkFlags)
76
{
77
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);
78
79
/* Make sure the heap is walkable (flush TLH's, secure heap integrity) */
80
vmThread->javaVM->memoryManagerFunctions->j9gc_flush_caches_for_walk(vmThread->javaVM);
81
82
MM_ReferenceChainWalker referenceChainWalker(env, TEMP_RCW_STACK_SIZE, userCallback, userData);
83
if (referenceChainWalker.initialize(env)) {
84
#if defined(J9VM_OPT_JVMTI)
85
referenceChainWalker.setIncludeJVMTIObjectTagTables(0 == (walkFlags & J9_MU_WALK_SKIP_JVMTI_TAG_TABLES));
86
#endif /* J9VM_OPT_JVMTI */
87
referenceChainWalker.setTrackVisibleStackFrameDepth(0 != (walkFlags & J9_MU_WALK_TRACK_VISIBLE_FRAME_DEPTH));
88
referenceChainWalker.setPreindexInterfaceFields(0 != (walkFlags & J9_MU_WALK_PREINDEX_INTERFACE_FIELDS));
89
/* walker configuration complete. Scan objects... */
90
referenceChainWalker.scanReachableObjects(env);
91
referenceChainWalker.tearDown(env);
92
}
93
}
94
95
/**
96
* Walk the reference chains starting at an object, call user provided function.
97
* The user function will be called for each reference once, with the type set to
98
* one of the J9GC_REFERENCE_TYPE_* values. An objects class and class loader are
99
* considered reachable.
100
* @note This function requires the caller to already have exclusive.
101
* @param vmThread
102
* @param userCallback User function to be run for each root and reference
103
* @param userData Pointer to storage for userData.
104
*/
105
void
106
j9gc_ext_reachable_from_object_do(
107
J9VMThread *vmThread,
108
J9Object *objectPtr,
109
J9MODRON_REFERENCE_CHAIN_WALKER_CALLBACK userCallback,
110
void *userData,
111
UDATA walkFlags)
112
{
113
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);
114
115
/* Make sure the heap is walkable (flush TLH's, secure heap integrity) */
116
vmThread->javaVM->memoryManagerFunctions->j9gc_flush_caches_for_walk(vmThread->javaVM);
117
118
MM_ReferenceChainWalker referenceChainWalker(env, TEMP_RCW_STACK_SIZE, userCallback, userData);
119
if (referenceChainWalker.initialize(env)) {
120
referenceChainWalker.setPreindexInterfaceFields(0 != (walkFlags & J9_MU_WALK_PREINDEX_INTERFACE_FIELDS));
121
/* walker configuration complete. Scan objects... */
122
referenceChainWalker.scanReachableFromObject(env, objectPtr);
123
referenceChainWalker.tearDown(env);
124
}
125
}
126
} /* extern "C" */
127
128
/**
129
* Initialized the internal structures.
130
* @param env
131
* @return true if successfully initialized.
132
*/
133
bool
134
MM_ReferenceChainWalker::initialize(MM_EnvironmentBase *env)
135
{
136
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
137
_heap = _extensions->heap;
138
_heapBase = _heap->getHeapBase();
139
_heapTop = _heap->getHeapTop();
140
if (NULL == extensions->referenceChainWalkerMarkMap) {
141
/* first call - create a new Mark Map and initialize it */
142
_markMap = MM_ReferenceChainWalkerMarkMap::newInstance(env, _heap->getMaximumPhysicalRange());
143
if (NULL != _markMap) {
144
extensions->referenceChainWalkerMarkMap = _markMap;
145
}
146
} else {
147
/* mark map is already created, just zero it */
148
_markMap = extensions->referenceChainWalkerMarkMap;
149
_markMap->clearMap(env);
150
}
151
152
bool result = (NULL != _markMap);
153
154
if (result) {
155
_queue = (J9Object **)env->getForge()->allocate(_queueSlots * sizeof(J9Object **), MM_AllocationCategory::REFERENCES, J9_GET_CALLSITE());
156
if(NULL != _queue) {
157
_queueEnd = _queue + _queueSlots;
158
_queueCurrent = _queue;
159
} else {
160
result = false;
161
}
162
}
163
return result;
164
}
165
166
/**
167
* Cleans up the internal structures.
168
* @param env
169
*/
170
void
171
MM_ReferenceChainWalker::tearDown(MM_EnvironmentBase *env)
172
{
173
if (NULL != _queue) {
174
env->getForge()->free(_queue);
175
_queue = NULL;
176
_queueEnd = NULL;
177
_queueCurrent = NULL;
178
}
179
180
/* Mark Map should not be released here and stay active - will be released in MM_GCExtensions::tearDown */
181
}
182
183
/**
184
* Main handler for each slot. Calls the <code>_userCallback</code> for each slot
185
* and adds the slot to queue for scanning.
186
* @param slotPtr pointer to the slot
187
* @param type root or reference type (J9GC_ROOT_TYPE_* or J9GC_REFERENCE_TYPE_*)
188
* @param index an index identifying the slot within the sourceObj
189
* @param sourceObj the object which contains this slot, or NULL if a root
190
*/
191
void
192
MM_ReferenceChainWalker::doSlot(J9Object **slotPtr, IDATA type, IDATA index, J9Object *sourceObj)
193
{
194
jvmtiIterationControl returnCode;
195
J9Object *objectPtr = *slotPtr;
196
197
if ((NULL == objectPtr) || _isTerminating) {
198
return;
199
}
200
201
/* call the call back before the object is corrupted */
202
returnCode = _userCallback(slotPtr, sourceObj, _userData, type, index, isMarked(objectPtr) ? 1 : 0);
203
204
if (JVMTI_ITERATION_CONTINUE == returnCode) {
205
pushObject(objectPtr);
206
} else if (JVMTI_ITERATION_ABORT == returnCode) {
207
_isTerminating = true;
208
clearQueue();
209
}
210
}
211
212
/**
213
* Main handler for each class slot. Calls the <code>_userCallback</code> for each slot
214
* and adds the slot to queue for scanning.
215
* @param slotPtr pointer to the class slot
216
* @param type root or reference type (J9GC_ROOT_TYPE_* or J9GC_REFERENCE_TYPE_*)
217
* @param index an index identifying the slot within the sourceObj
218
* @param sourceObj the object which contains this slot, or NULL if a root
219
*/
220
void
221
MM_ReferenceChainWalker::doClassSlot(J9Class *classPtr, IDATA type, IDATA index, J9Object *sourceObj)
222
{
223
if (NULL != classPtr) {
224
/* NOTE: this "O-slot" is actually a pointer to a local variable in this
225
* function. As such, any changes written back into it will be lost.
226
* Since no-one writes back into the slot in classes-on-heap VMs this is
227
* OK. We should simplify this code once classes-on-heap is enabled
228
* everywhere.
229
*/
230
J9Object* clazzObject = J9VM_J9CLASS_TO_HEAPCLASS(classPtr);
231
doSlot(&clazzObject, type, index, sourceObj);
232
}
233
}
234
235
/**
236
* Main handler for field slots. Decodes the field and forwards to <code>doSlot</code>.
237
* If the slot is modified by the callback, stores the modified value back into the field.
238
* @param slotPtr pointer to the field slot
239
* @param type root or reference type (J9GC_ROOT_TYPE_* or J9GC_REFERENCE_TYPE_*)
240
* @param index an index identifying the slot within the sourceObj
241
* @param sourceObj the object which contains this slot
242
*/
243
void
244
MM_ReferenceChainWalker::doFieldSlot(GC_SlotObject *slotObject, IDATA type, IDATA index, J9Object *sourceObj)
245
{
246
/* decode the field value into an object pointer */
247
j9object_t fieldValue = slotObject->readReferenceFromSlot();
248
249
doSlot(&fieldValue, type, index, sourceObj);
250
251
/* write the value back into the field in case the callback changed it */
252
slotObject->writeReferenceToSlot(fieldValue);
253
}
254
255
/**
256
* Clears the queue
257
*/
258
void
259
MM_ReferenceChainWalker::clearQueue()
260
{
261
_queueCurrent = _queue;
262
_hasOverflowed = false;
263
}
264
265
/**
266
* Adds the object to the queue for scanning of its slots
267
* @param objectPtr the object to add to the queue
268
*/
269
void
270
MM_ReferenceChainWalker::pushObject(J9Object *objectPtr)
271
{
272
/* only add the object to the queue if it hasn't been scanned and isn't already queued */
273
if (!isMarked(objectPtr)) {
274
/* ensure there is room in the queue */
275
if (_queueCurrent < _queueEnd) {
276
setMarked(objectPtr);
277
*_queueCurrent = objectPtr;
278
_queueCurrent += 1;
279
} else {
280
/* if we overflow, dump half the objects from the queue and tag them for finding later */
281
_hasOverflowed = true;
282
setOverflow(objectPtr);
283
for (UDATA i = _queueSlots / 2; i > 0; i--) {
284
J9Object *objPtr = popObject();
285
setOverflow(objPtr);
286
}
287
}
288
}
289
}
290
291
/**
292
* Get the next object off the queue for processing
293
* @return NULL if the queue is empty
294
*/
295
J9Object *
296
MM_ReferenceChainWalker::popObject()
297
{
298
J9Object *objectPtr;
299
300
if (_queueCurrent == _queue) {
301
/* the queue is empty, check if there are overflow objects */
302
while (_hasOverflowed && !_isProcessingOverflow) {
303
/* We can completely clear out the overflow now. Field ordering has been keep
304
* via the ordering of doSlot calls. This is done here as it keeps the queue
305
* and overflow separate from the scanning.
306
*/
307
308
_isProcessingOverflow = true;
309
310
/* Reset the overflow flag, so we can determine if we overflow again */
311
_hasOverflowed = false;
312
313
findOverflowObjects();
314
315
_isProcessingOverflow = false;
316
}
317
return NULL;
318
}
319
320
_queueCurrent--;
321
objectPtr = *_queueCurrent;
322
return objectPtr;
323
}
324
325
/**
326
* Scan the remaining objects on the queue. On return the queue will be empty.
327
*/
328
void
329
MM_ReferenceChainWalker::completeScan()
330
{
331
J9Object *objectPtr;
332
333
while (NULL != (objectPtr = popObject())) {
334
scanObject(objectPtr);
335
}
336
}
337
338
/**
339
* Scan an object's slots. This will also add the reference to the objects class.
340
* @param objectPtr the object to scan
341
*/
342
void
343
MM_ReferenceChainWalker::scanObject(J9Object *objectPtr)
344
{
345
/* add the object's class for scanning */
346
J9Class* clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, _extensions);
347
doClassSlot(clazz, J9GC_REFERENCE_TYPE_CLASS, -1, objectPtr);
348
349
switch(_extensions->objectModel.getScanType(objectPtr)) {
350
case GC_ObjectModel::SCAN_MIXED_OBJECT_LINKED:
351
case GC_ObjectModel::SCAN_ATOMIC_MARKABLE_REFERENCE_OBJECT:
352
case GC_ObjectModel::SCAN_MIXED_OBJECT:
353
case GC_ObjectModel::SCAN_OWNABLESYNCHRONIZER_OBJECT:
354
case GC_ObjectModel::SCAN_CLASS_OBJECT:
355
case GC_ObjectModel::SCAN_CLASSLOADER_OBJECT:
356
scanMixedObject(objectPtr);
357
break;
358
case GC_ObjectModel::SCAN_POINTER_ARRAY_OBJECT:
359
scanPointerArrayObject((J9IndexableObject *)objectPtr);
360
break;
361
case GC_ObjectModel::SCAN_REFERENCE_MIXED_OBJECT:
362
scanReferenceMixedObject(objectPtr);
363
break;
364
case GC_ObjectModel::SCAN_PRIMITIVE_ARRAY_OBJECT:
365
/* nothing to do */
366
break;
367
default:
368
Assert_MM_unreachable();
369
}
370
371
if (J9GC_IS_INITIALIZED_HEAPCLASS((J9VMThread*)_env->getLanguageVMThread(), objectPtr)) {
372
scanClass(J9VM_J9CLASS_FROM_HEAPCLASS((J9VMThread*)_env->getLanguageVMThread(), objectPtr));
373
}
374
}
375
376
/**
377
* @todo Provide function documentation
378
*/
379
void
380
MM_ReferenceChainWalker::scanMixedObject(J9Object *objectPtr)
381
{
382
GC_MixedObjectDeclarationOrderIterator objectIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm), objectPtr, _shouldPreindexInterfaceFields);
383
384
while(GC_SlotObject *slotObject = objectIterator.nextSlot()) {
385
doFieldSlot(slotObject, J9GC_REFERENCE_TYPE_FIELD, objectIterator.getIndex(), objectPtr);
386
}
387
}
388
389
/**
390
* @todo Provide function documentation
391
*/
392
void
393
MM_ReferenceChainWalker::scanPointerArrayObject(J9IndexableObject *objectPtr)
394
{
395
GC_PointerArrayIterator pointerArrayIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm), (J9Object *)objectPtr);
396
397
while(GC_SlotObject *slotObject = pointerArrayIterator.nextSlot()) {
398
doFieldSlot(slotObject, J9GC_REFERENCE_TYPE_ARRAY, pointerArrayIterator.getIndex(), (J9Object *)objectPtr);
399
}
400
}
401
402
/**
403
* @todo Provide function documentation
404
*/
405
void
406
MM_ReferenceChainWalker::scanReferenceMixedObject(J9Object *objectPtr)
407
{
408
GC_MixedObjectDeclarationOrderIterator objectIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm), objectPtr, _shouldPreindexInterfaceFields);
409
410
while(GC_SlotObject *slotObject = objectIterator.nextSlot()) {
411
doFieldSlot(slotObject, J9GC_REFERENCE_TYPE_WEAK_REFERENCE, objectIterator.getIndex(), objectPtr);
412
}
413
}
414
415
/**
416
* @todo Provide function documentation
417
*/
418
void
419
MM_ReferenceChainWalker::scanClass(J9Class *clazz)
420
{
421
J9Object* referrer = J9VM_J9CLASS_TO_HEAPCLASS(clazz);
422
423
GC_ClassIteratorDeclarationOrder classIterator(static_cast<J9JavaVM*>(_omrVM->_language_vm), clazz, _shouldPreindexInterfaceFields);
424
while(volatile j9object_t *slot = classIterator.nextSlot()) {
425
IDATA refType = classIterator.getSlotReferenceType();
426
IDATA index = classIterator.getIndex();
427
428
/* discard volatile since we must be in stop-the-world mode */
429
doSlot((j9object_t*)slot, refType, index, referrer);
430
}
431
432
GC_ClassIteratorClassSlots classIteratorClassSlots(static_cast<J9JavaVM*>(_omrVM->_language_vm), clazz);
433
while (J9Class *classPtr = classIteratorClassSlots.nextSlot()) {
434
switch (classIteratorClassSlots.getState()) {
435
case classiteratorclassslots_state_constant_pool:
436
doClassSlot(classPtr, J9GC_REFERENCE_TYPE_CONSTANT_POOL, classIteratorClassSlots.getIndex(), referrer);
437
break;
438
case classiteratorclassslots_state_superclasses:
439
doClassSlot(classPtr, J9GC_REFERENCE_TYPE_SUPERCLASS, classIteratorClassSlots.getIndex(), referrer);
440
break;
441
case classiteratorclassslots_state_interfaces:
442
doClassSlot(classPtr, J9GC_REFERENCE_TYPE_INTERFACE, classIteratorClassSlots.getIndex(), referrer);
443
break;
444
case classiteratorclassslots_state_array_class_slots:
445
doClassSlot(classPtr, J9GC_REFERENCE_TYPE_CLASS_ARRAY_CLASS, classIteratorClassSlots.getIndex(), referrer);
446
break;
447
case classiteratorclassslots_state_flattened_class_cache_slots:
448
doClassSlot(classPtr, J9GC_REFERENCE_TYPE_CLASS_FCC, classIteratorClassSlots.getIndex(), referrer);
449
break;
450
default:
451
doClassSlot(classPtr, J9GC_REFERENCE_TYPE_UNKNOWN, classIteratorClassSlots.getIndex(), referrer);
452
break;
453
}
454
}
455
456
/* GC_ClassIteratorDeclarationOrder does not iterate the classLoader slot, we want to report the reference */
457
J9Object **slot = J9GC_J9CLASSLOADER_CLASSLOADEROBJECT_EA(clazz->classLoader);
458
doSlot(slot, J9GC_REFERENCE_TYPE_CLASSLOADER, -1, referrer);
459
}
460
461
/**
462
* Finds objects in the heap that were overflowed, adds them back to the queue, and completes a scan.
463
*/
464
void
465
MM_ReferenceChainWalker::findOverflowObjects()
466
{
467
MM_Heap *heap = _extensions->heap;
468
MM_HeapRegionManager *regionManager = heap->getHeapRegionManager();
469
GC_HeapRegionIterator regionIterator(regionManager);
470
471
MM_HeapRegionDescriptor *region = NULL;
472
while(NULL != (region = regionIterator.nextRegion())) {
473
GC_ObjectHeapBufferedIterator objectHeapIterator(_extensions, region);
474
475
J9Object *object = NULL;
476
while((object = objectHeapIterator.nextObject()) != NULL) {
477
if (isOverflow(object)) {
478
clearOverflow(object);
479
pushObject(object);
480
completeScan();
481
}
482
}
483
}
484
}
485
486
/**
487
* @todo Provide function documentation
488
*/
489
void
490
MM_ReferenceChainWalker::doSlot(J9Object **slotPtr) {
491
doSlot(slotPtr, J9GC_ROOT_TYPE_UNKNOWN, -1, NULL);
492
}
493
494
/**
495
* Process a class slot pointer.
496
* @param slotPtr a pointer to a class slot
497
*/
498
void
499
MM_ReferenceChainWalker::doClassSlot(J9Class *classPtr)
500
{
501
doClassSlot(classPtr, J9GC_ROOT_TYPE_CLASS, -1, NULL);
502
}
503
504
/**
505
* @todo Provide function documentation
506
*/
507
void
508
MM_ReferenceChainWalker::doClass(J9Class *clazz) {
509
doClassSlot(clazz);
510
}
511
512
513
/**
514
* @todo Provide function documentation
515
*/
516
void
517
MM_ReferenceChainWalker::doClassLoader(J9ClassLoader *classLoader)
518
{
519
doSlot(J9GC_J9CLASSLOADER_CLASSLOADEROBJECT_EA(classLoader), J9GC_ROOT_TYPE_CLASSLOADER, -1, NULL);
520
}
521
522
#if defined(J9VM_GC_FINALIZATION)
523
/**
524
* @todo Provide function documentation
525
*/
526
void
527
MM_ReferenceChainWalker::doUnfinalizedObject(J9Object *objectPtr, MM_UnfinalizedObjectList *list)
528
{
529
J9Object *object = objectPtr;
530
doSlot(&object, J9GC_ROOT_TYPE_UNFINALIZED_OBJECT, -1, NULL);
531
}
532
#endif /* J9VM_GC_FINALIZATION */
533
534
void
535
MM_ReferenceChainWalker::doOwnableSynchronizerObject(J9Object *objectPtr, MM_OwnableSynchronizerObjectList *list)
536
{
537
J9Object *object = objectPtr;
538
doSlot(&object, J9GC_ROOT_TYPE_OWNABLE_SYNCHRONIZER_OBJECT, -1, NULL);
539
}
540
541
/**
542
* @todo Provide function documentation
543
*/
544
void
545
MM_ReferenceChainWalker::doMonitorReference(J9ObjectMonitor *objectMonitor, GC_HashTableIterator *monitorReferenceIterator)
546
{
547
J9ThreadAbstractMonitor * monitor = (J9ThreadAbstractMonitor*)objectMonitor->monitor;
548
doSlot((J9Object **)& monitor->userData, J9GC_ROOT_TYPE_MONITOR, -1, NULL);
549
}
550
551
/**
552
* @todo Provide function documentation
553
*/
554
void
555
MM_ReferenceChainWalker::doJNIWeakGlobalReference(J9Object **slotPtr)
556
{
557
doSlot(slotPtr, J9GC_ROOT_TYPE_JNI_WEAK_GLOBAL, -1, NULL);
558
}
559
560
#if defined(J9VM_GC_MODRON_SCAVENGER)
561
/**
562
* @todo Provide function documentation
563
*/
564
void
565
MM_ReferenceChainWalker::doRememberedSetSlot(J9Object **slotPtr, GC_RememberedSetSlotIterator *rememberedSetSlotIterator)
566
{
567
doSlot(slotPtr, J9GC_ROOT_TYPE_REMEMBERED_SET, -1, NULL);
568
}
569
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
570
571
/**
572
* @todo Provide function documentation
573
*/
574
void
575
MM_ReferenceChainWalker::doStringTableSlot(J9Object **slotPtr, GC_StringTableIterator *stringTableIterator)
576
{
577
doSlot(slotPtr, J9GC_ROOT_TYPE_STRING_TABLE, -1, NULL);
578
}
579
580
/**
581
* @todo Provide function documentation
582
*/
583
void
584
MM_ReferenceChainWalker::doVMClassSlot(J9Class *classPtr)
585
{
586
doClassSlot(classPtr, J9GC_ROOT_TYPE_VM_CLASS_SLOT, -1, NULL);
587
}
588
589
/**
590
* @todo Provide function documentation
591
*/
592
void
593
MM_ReferenceChainWalker::doStackSlot(J9Object **slotPtr, void *walkState, const void* stackLocation)
594
{
595
J9Object *slotValue = *slotPtr;
596
597
/* Only report heap objects */
598
599
if (isHeapObject(slotValue) && !_heap->objectIsInGap(slotValue)) {
600
doSlot(slotPtr, J9GC_ROOT_TYPE_STACK_SLOT, -1, (J9Object *)walkState);
601
}
602
}
603
604
#if defined(J9VM_OPT_JVMTI)
605
/**
606
* @todo Provide function documentation
607
*/
608
void
609
MM_ReferenceChainWalker::doJVMTIObjectTagSlot(J9Object **slotPtr, GC_JVMTIObjectTagTableIterator *objectTagTableIterator)
610
{
611
doSlot(slotPtr, J9GC_ROOT_TYPE_JVMTI_TAG_REF, -1, NULL);
612
}
613
#endif /* J9VM_OPT_JVMTI */
614
615
/**
616
* @todo Provide function documentation
617
*/
618
void
619
MM_ReferenceChainWalker::doVMThreadSlot(J9Object **slotPtr, GC_VMThreadIterator *vmThreadIterator)
620
{
621
J9Object *slotValue = *slotPtr;
622
623
switch(vmThreadIterator->getState()) {
624
case vmthreaditerator_state_slots:
625
doSlot(slotPtr, J9GC_ROOT_TYPE_THREAD_SLOT, -1, NULL);
626
break;
627
case vmthreaditerator_state_jni_slots:
628
doSlot(slotPtr, J9GC_ROOT_TYPE_JNI_LOCAL, -1, NULL);
629
break;
630
#if defined(J9VM_INTERP_HOT_CODE_REPLACEMENT)
631
case vmthreaditerator_state_monitor_records:
632
if (isHeapObject(slotValue) && !_heap->objectIsInGap(slotValue)) {
633
doSlot(slotPtr, J9GC_ROOT_TYPE_THREAD_MONITOR, -1, NULL);
634
}
635
break;
636
#endif
637
default:
638
doSlot(slotPtr, J9GC_ROOT_TYPE_UNKNOWN, -1, NULL);
639
break;
640
}
641
}
642
643
#if defined(J9VM_GC_FINALIZATION)
644
/**
645
* @todo Provide function documentation
646
*/
647
void
648
MM_ReferenceChainWalker::doFinalizableObject(J9Object *objectPtr)
649
{
650
J9Object *object = objectPtr;
651
doSlot(&object, J9GC_ROOT_TYPE_FINALIZABLE_OBJECT, -1, NULL);
652
}
653
#endif /* J9VM_GC_FINALIZATION */
654
655
/**
656
* @todo Provide function documentation
657
*/
658
void
659
MM_ReferenceChainWalker::doJNIGlobalReferenceSlot(J9Object **slotPtr, GC_JNIGlobalReferenceIterator *jniGlobalReferenceIterator)
660
{
661
doSlot(slotPtr, J9GC_ROOT_TYPE_JNI_GLOBAL, -1, NULL);
662
}
663
664