Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_base/ReferenceChainWalker.hpp
5985 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
#if !defined(REFERENCECHAINWALKER_HPP_)
24
#define REFERENCECHAINWALKER_HPP_
25
26
#include "j9accessbarrier.h"
27
#include "j9cfg.h"
28
#include "j9comp.h"
29
#include "j9modron.h"
30
#include "modronbase.h"
31
32
#include "ModronTypes.hpp"
33
#include "ReferenceChainWalkerMarkMap.hpp"
34
#include "RootScanner.hpp"
35
#include "RootScannerTypes.h"
36
37
class GC_HashTableIterator;
38
class GC_JVMTIObjectTagTableIterator;
39
class GC_SlotObject;
40
class GC_VMClassSlotIterator;
41
class GC_VMThreadIterator;
42
class MM_EnvironmentBase;
43
class MM_Heap;
44
class MM_OwnableSynchronizerObjectList;
45
class MM_UnfinalizedObjectList;
46
47
/**
48
* Interface for walking reference chains in the system starting either at the root set or a specified object.
49
*
50
* MM_ReferenceChainWalker makes use of the general MM_RootScanner for walking the root set. It uses a user
51
* callback to provide the function to be done on all references and roots. The type of reference is reported back
52
* to the callback functions.
53
*
54
* The objects are queued in a stack that makes use of the OBJECT_HEADER_COLOR_MASK bits of the object header
55
* flags to indicate whether an object has been queued, or overflowed. The stack is allocated as an array of slots
56
* of the size passed in to the constructor. When the stack runs out of space, half of the objects are removed
57
* and have their overflow flag set. These objects are scanned for when the stack next becomes empty.
58
*
59
* @note You must use <code>initialize</code> and <code>kill</code> to allocate and deallocate the internal structures.
60
* @note Does not handle overflowing stack allocated objects.
61
* @ingroup GC_Base
62
*/
63
class MM_ReferenceChainWalker : public MM_RootScanner
64
{
65
private:
66
J9Object **_queue; /**< Main queue used for queuing objects */
67
J9Object **_queueEnd; /**< End of the queue used for queuing objects */
68
J9Object **_queueCurrent; /**< Current position of the queue used for queuing objects */
69
UDATA _queueSlots; /**< Size of the queue before overflow occurs */
70
J9MODRON_REFERENCE_CHAIN_WALKER_CALLBACK *_userCallback; /**< User callback function to be called on every reachable slot */
71
void *_userData; /**< User data to be passed to the user callback function */
72
bool _hasOverflowed; /**< Set when the queue has overflowed */
73
bool _isProcessingOverflow; /**< Set when the queue is currently processing the overflow */
74
bool _isTerminating; /**< Set when no more callbacks should be queued */
75
bool _shouldPreindexInterfaceFields; /**< if true, indexes interface fields of the class being visited before class and superclass fields, otherwise, returns them in the order they appear in an object instance (CMVC 142897) */
76
MM_ReferenceChainWalkerMarkMap *_markMap; /**< Mark Map created for Reference Chain Walker */
77
MM_Heap *_heap; /**< Cached pointer to the heap */
78
void *_heapBase; /**< Cached value of the heap base */
79
void *_heapTop; /**< Cached value of the heap top */
80
81
void clearQueue();
82
void pushObject(J9Object *obj);
83
J9Object *popObject();
84
85
void findOverflowObjects();
86
87
virtual void scanClass(J9Class *clazz);
88
virtual void scanObject(J9Object *objectPtr);
89
virtual void scanMixedObject(J9Object *objectPtr);
90
virtual void scanPointerArrayObject(J9IndexableObject *objectPtr);
91
virtual void scanReferenceMixedObject(J9Object *objectPtr);
92
93
virtual void doClassLoader(J9ClassLoader *classLoader);
94
95
#if defined(J9VM_GC_FINALIZATION)
96
virtual void doUnfinalizedObject(J9Object *objectPtr, MM_UnfinalizedObjectList *list);
97
virtual void doFinalizableObject(J9Object *objectPtr);
98
#endif /* J9VM_GC_FINALIZATION */
99
100
/**
101
* @todo Provide function documentation
102
*/
103
virtual void doOwnableSynchronizerObject(J9Object *objectPtr, MM_OwnableSynchronizerObjectList *list);
104
105
virtual void doJNIWeakGlobalReference(J9Object **slotPtr);
106
virtual void doJNIGlobalReferenceSlot(J9Object **slotPtr, GC_JNIGlobalReferenceIterator *jniGlobalReferenceIterator);
107
108
#if defined(J9VM_GC_MODRON_SCAVENGER)
109
virtual void doRememberedSetSlot(J9Object **slotPtr, GC_RememberedSetSlotIterator *rememberedSetSlotIterator);
110
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
111
112
#if defined(J9VM_OPT_JVMTI)
113
virtual void doJVMTIObjectTagSlot(J9Object **slotPtr, GC_JVMTIObjectTagTableIterator *objectTagTableIterator);
114
#endif /* J9VM_OPT_JVMTI */
115
116
virtual void doMonitorReference(J9ObjectMonitor *objectMonitor, GC_HashTableIterator *monitorReferenceIterator);
117
virtual void doStringTableSlot(J9Object **slotPtr, GC_StringTableIterator *stringTableIterator);
118
virtual void doVMClassSlot(J9Class *classPtr);
119
virtual void doVMThreadSlot(J9Object **slotPtr, GC_VMThreadIterator *vmThreadIterator);
120
virtual void doStackSlot(J9Object **slotPtr, void *walkState, const void* stackLocation);
121
virtual void doSlot(J9Object **slotPtr);
122
virtual void doClassSlot(J9Class *classPtr);
123
virtual void doClass(J9Class *clazz);
124
virtual void doSlot(J9Object **slotPtr, IDATA type, IDATA index, J9Object *sourceObj);
125
virtual void doClassSlot(J9Class *classPtr, IDATA type, IDATA index, J9Object *sourceObj);
126
using MM_RootScanner::doFieldSlot;
127
virtual void doFieldSlot(GC_SlotObject *slotObject, IDATA type, IDATA index, J9Object *sourceObj);
128
129
MMINLINE virtual CompletePhaseCode scanClassesComplete(MM_EnvironmentBase *env) {
130
reportScanningStarted(RootScannerEntity_ClassesComplete);
131
completeScan();
132
reportScanningEnded(RootScannerEntity_ClassesComplete);
133
return complete_phase_OK;
134
}
135
136
MMINLINE virtual CompletePhaseCode scanWeakReferencesComplete(MM_EnvironmentBase *env) {
137
return complete_phase_OK;
138
}
139
MMINLINE virtual CompletePhaseCode scanSoftReferencesComplete(MM_EnvironmentBase *env) {
140
return complete_phase_OK;
141
}
142
143
MMINLINE virtual CompletePhaseCode scanPhantomReferencesComplete(MM_EnvironmentBase *env) {
144
return complete_phase_OK;
145
}
146
147
#if defined(J9VM_GC_FINALIZATION)
148
MMINLINE virtual CompletePhaseCode scanUnfinalizedObjectsComplete(MM_EnvironmentBase *env) {
149
reportScanningStarted(RootScannerEntity_UnfinalizedObjectsComplete);
150
completeScan();
151
reportScanningEnded(RootScannerEntity_UnfinalizedObjectsComplete);
152
return complete_phase_OK;
153
}
154
#endif /* J9VM_GC_FINALIZATION */
155
156
virtual CompletePhaseCode scanMonitorReferencesComplete(MM_EnvironmentBase *env) {
157
return complete_phase_OK;
158
}
159
160
void completeScan();
161
162
163
MMINLINE bool isHeapObject(J9Object* objectPtr)
164
{
165
return ((_heapBase <= (U_8 *)objectPtr) && (_heapTop > (U_8 *)objectPtr));
166
}
167
168
169
MMINLINE bool isMarked(J9Object *object)
170
{
171
if (isHeapObject(object)) {
172
/* check one bit in mark map only - return true if 10 or 11 */
173
return _markMap->isBitSet(object);
174
} else {
175
return true;
176
}
177
}
178
179
MMINLINE void setMarked(J9Object * object)
180
{
181
if (isHeapObject(object)) {
182
/* mark one bit only (next one has to be 0) - set 10 */
183
_markMap->setBit(object);
184
}
185
}
186
187
MMINLINE void setOverflow(J9Object *object)
188
{
189
if (isHeapObject(object)) {
190
UDATA referenceSize = _env->compressObjectReferences() ? sizeof(uint32_t) : sizeof(uintptr_t);
191
/* set both mark bits - set 11 */
192
_markMap->setBit(object);
193
_markMap->setBit((J9Object *)((UDATA)object + referenceSize));
194
}
195
}
196
197
MMINLINE bool isOverflow(J9Object * object)
198
{
199
if (isHeapObject(object)) {
200
UDATA referenceSize = _env->compressObjectReferences() ? sizeof(uint32_t) : sizeof(uintptr_t);
201
/* check both bits in mark map - return true if 11 */
202
return (_markMap->isBitSet(object) && _markMap->isBitSet((J9Object *)((UDATA)object + referenceSize)));
203
} else {
204
return false;
205
}
206
}
207
208
MMINLINE void clearOverflow(J9Object * object)
209
{
210
if (isHeapObject(object)) {
211
UDATA referenceSize = _env->compressObjectReferences() ? sizeof(uint32_t) : sizeof(uintptr_t);
212
/* clear both mark bits - set 00 */
213
_markMap->clearBit(object);
214
_markMap->clearBit((J9Object *)((UDATA)object + referenceSize));
215
}
216
}
217
218
protected:
219
220
public:
221
MM_ReferenceChainWalker(MM_EnvironmentBase *env, UDATA queueSlots, J9MODRON_REFERENCE_CHAIN_WALKER_CALLBACK *userCallback, void *userData) :
222
MM_RootScanner(env, true),
223
_queue(NULL),
224
_queueEnd(NULL),
225
_queueCurrent(NULL),
226
_queueSlots(queueSlots),
227
_userCallback(userCallback),
228
_userData(userData),
229
_hasOverflowed(false),
230
_isProcessingOverflow(false),
231
_isTerminating(false),
232
_shouldPreindexInterfaceFields(true), /* default to behaviour required for Java6/heap11 */
233
_markMap(NULL),
234
_heap(NULL),
235
_heapBase(NULL),
236
_heapTop(NULL)
237
{
238
_typeId = __FUNCTION__;
239
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
240
setClassDataAsRoots(false);
241
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
242
};
243
244
bool initialize(MM_EnvironmentBase *env);
245
void tearDown(MM_EnvironmentBase *env);
246
247
void scanReachableObjects(MM_EnvironmentBase *env) {
248
scanAllSlots(env);
249
completeScan();
250
}
251
252
void scanReachableFromObject(MM_EnvironmentBase *env, J9Object *objectPtr) {
253
pushObject(objectPtr);
254
completeScan();
255
}
256
257
/**
258
* Added to support bi-modal interface indexing in JVMTI (CMVC 142897).
259
* Detail: heap10 requires no pre-indexing in order to preserve Java5 behaviour but heap11 requires pre-indexing to pass a Java6 JCK
260
*/
261
void setPreindexInterfaceFields(bool shouldPreindexInterfaceFields) { _shouldPreindexInterfaceFields = shouldPreindexInterfaceFields; }
262
};
263
264
#endif /* REFERENCECHAINWALKER_HPP_ */
265
266
267