Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/MarkingSchemeRootClearer.cpp
5985 views
1
2
/*******************************************************************************
3
* Copyright (c) 1991, 2020 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* 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
22
*******************************************************************************/
23
24
#include "j9.h"
25
#include "j9cfg.h"
26
#include "j9consts.h"
27
28
#if defined(J9VM_GC_FINALIZATION)
29
#include "CollectorLanguageInterfaceImpl.hpp"
30
#endif /* defined(J9VM_GC_FINALIZATION) */
31
#include "ConfigurationDelegate.hpp"
32
#include "EnvironmentBase.hpp"
33
#include "FinalizableObjectBuffer.hpp"
34
#include "FinalizableReferenceBuffer.hpp"
35
#include "GlobalCollector.hpp"
36
#include "Heap.hpp"
37
#include "HeapRegionDescriptorStandard.hpp"
38
#include "HeapRegionIteratorStandard.hpp"
39
#include "HeapRegionManager.hpp"
40
#include "MarkingScheme.hpp"
41
#include "MarkingSchemeRootClearer.hpp"
42
#include "ModronAssertions.h"
43
#include "OwnableSynchronizerObjectBuffer.hpp"
44
#include "ParallelDispatcher.hpp"
45
#include "ReferenceObjectBuffer.hpp"
46
#include "ReferenceStats.hpp"
47
#include "RootScanner.hpp"
48
#include "StackSlotValidator.hpp"
49
#include "UnfinalizedObjectBuffer.hpp"
50
51
void
52
MM_MarkingSchemeRootClearer::doSlot(omrobjectptr_t *slotPtr)
53
{
54
Assert_MM_unreachable();
55
}
56
57
void
58
MM_MarkingSchemeRootClearer::doClass(J9Class *clazz)
59
{
60
Assert_MM_unreachable();
61
}
62
63
void
64
MM_MarkingSchemeRootClearer::doFinalizableObject(omrobjectptr_t object)
65
{
66
Assert_MM_unreachable();
67
}
68
69
void
70
MM_MarkingSchemeRootClearer::scanWeakReferenceObjects(MM_EnvironmentBase *env)
71
{
72
reportScanningStarted(RootScannerEntity_WeakReferenceObjects);
73
GC_Environment *gcEnv = env->getGCEnvironment();
74
Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());
75
76
MM_HeapRegionDescriptorStandard *region = NULL;
77
GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());
78
while (NULL != (region = regionIterator.nextRegion())) {
79
MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);
80
/* NOTE: we can't look at the list to determine if there's work to do since another thread may have already processed it and deleted everything */
81
for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {
82
if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {
83
MM_ReferenceObjectList *list = &regionExtension->_referenceObjectLists[i];
84
list->startWeakReferenceProcessing();
85
if (!list->wasWeakListEmpty()) {
86
_markingDelegate->processReferenceList(env, region, list->getPriorWeakList(), &gcEnv->_markJavaStats._weakReferenceStats);
87
}
88
}
89
}
90
}
91
92
Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());
93
reportScanningEnded(RootScannerEntity_WeakReferenceObjects);
94
}
95
96
MM_RootScanner::CompletePhaseCode
97
MM_MarkingSchemeRootClearer::scanWeakReferencesComplete(MM_EnvironmentBase *env)
98
{
99
/* No new objects could have been discovered by soft / weak reference processing,
100
* but we must complete this phase prior to unfinalized processing to ensure that
101
* finalizable referents get cleared */
102
env->_currentTask->synchronizeGCThreads(env, UNIQUE_ID);
103
return complete_phase_OK;
104
}
105
106
void
107
MM_MarkingSchemeRootClearer::scanSoftReferenceObjects(MM_EnvironmentBase *env)
108
{
109
reportScanningStarted(RootScannerEntity_SoftReferenceObjects);
110
GC_Environment *gcEnv = env->getGCEnvironment();
111
Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());
112
113
MM_HeapRegionDescriptorStandard *region = NULL;
114
GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());
115
while (NULL != (region = regionIterator.nextRegion())) {
116
MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);
117
/* NOTE: we can't look at the list to determine if there's work to do since another thread may have already processed it and deleted everything */
118
for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {
119
if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {
120
MM_ReferenceObjectList *list = &regionExtension->_referenceObjectLists[i];
121
list->startSoftReferenceProcessing();
122
if (!list->wasSoftListEmpty()) {
123
_markingDelegate->processReferenceList(env, region, list->getPriorSoftList(), &gcEnv->_markJavaStats._softReferenceStats);
124
}
125
}
126
}
127
}
128
129
Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());
130
reportScanningEnded(RootScannerEntity_SoftReferenceObjects);
131
}
132
133
MM_RootScanner::CompletePhaseCode
134
MM_MarkingSchemeRootClearer::scanSoftReferencesComplete(MM_EnvironmentBase *env)
135
{
136
/* do nothing -- no new objects could have been discovered by soft reference processing */
137
return complete_phase_OK;
138
}
139
140
void
141
MM_MarkingSchemeRootClearer::scanPhantomReferenceObjects(MM_EnvironmentBase *env)
142
{
143
reportScanningStarted(RootScannerEntity_PhantomReferenceObjects);
144
145
/* ensure that all _referenceObjectBuffers are flushed before phantom references
146
* are processed since scanning unfinalizedObjects may resurrect a phantom reference
147
*/
148
GC_Environment *gcEnv = env->getGCEnvironment();
149
gcEnv->_referenceObjectBuffer->flush(env);
150
env->_currentTask->synchronizeGCThreads(env, UNIQUE_ID);
151
152
MM_HeapRegionDescriptorStandard *region = NULL;
153
GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());
154
while (NULL != (region = regionIterator.nextRegion())) {
155
MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);
156
/* NOTE: we can't look at the list to determine if there's work to do since another thread may have already processed it and deleted everything */
157
for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {
158
if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {
159
MM_ReferenceObjectList *list = &regionExtension->_referenceObjectLists[i];
160
list->startPhantomReferenceProcessing();
161
if (!list->wasPhantomListEmpty()) {
162
_markingDelegate->processReferenceList(env, region, list->getPriorPhantomList(), &gcEnv->_markJavaStats._phantomReferenceStats);
163
}
164
}
165
}
166
}
167
168
Assert_MM_true(gcEnv->_referenceObjectBuffer->isEmpty());
169
reportScanningEnded(RootScannerEntity_PhantomReferenceObjects);
170
}
171
172
MM_RootScanner::CompletePhaseCode
173
MM_MarkingSchemeRootClearer::scanPhantomReferencesComplete(MM_EnvironmentBase *env)
174
{
175
reportScanningStarted(RootScannerEntity_PhantomReferenceObjectsComplete);
176
if (env->_currentTask->synchronizeGCThreadsAndReleaseSingleThread(env, UNIQUE_ID)) {
177
env->_cycleState->_referenceObjectOptions |= MM_CycleState::references_clear_phantom;
178
env->_currentTask->releaseSynchronizedGCThreads(env);
179
}
180
/* phantom reference processing may resurrect objects - scan them now */
181
_markingScheme->completeMarking(env);
182
reportScanningEnded(RootScannerEntity_PhantomReferenceObjectsComplete);
183
return complete_phase_OK;
184
}
185
186
void
187
MM_MarkingSchemeRootClearer::scanUnfinalizedObjects(MM_EnvironmentBase *env)
188
{
189
if (_markingDelegate->shouldScanUnfinalizedObjects()) {
190
/* allow the marking scheme to handle this */
191
reportScanningStarted(RootScannerEntity_UnfinalizedObjects);
192
GC_Environment *gcEnv = env->getGCEnvironment();
193
GC_FinalizableObjectBuffer buffer(_extensions);
194
#if defined(J9VM_GC_FINALIZATION)
195
bool finalizationRequired = false;
196
#endif /* defined(J9VM_GC_FINALIZATION) */
197
198
MM_HeapRegionDescriptorStandard *region = NULL;
199
GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());
200
while (NULL != (region = regionIterator.nextRegion())) {
201
MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);
202
for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {
203
MM_UnfinalizedObjectList *list = &regionExtension->_unfinalizedObjectLists[i];
204
if (!list->wasEmpty()) {
205
if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {
206
omrobjectptr_t object = list->getPriorList();
207
while (NULL != object) {
208
gcEnv->_markJavaStats._unfinalizedCandidates += 1;
209
omrobjectptr_t next = _extensions->accessBarrier->getFinalizeLink(object);
210
if (_markingScheme->inlineMarkObject(env, object)) {
211
/* object was not previously marked -- it is now finalizable so push it to the local buffer */
212
buffer.add(env, object);
213
gcEnv->_markJavaStats._unfinalizedEnqueued += 1;
214
#if defined(J9VM_GC_FINALIZATION)
215
/* inform global GC if finalization is required */
216
if (!finalizationRequired) {
217
MM_GlobalCollector *globalCollector = (MM_GlobalCollector *)_extensions->getGlobalCollector();
218
globalCollector->getGlobalCollectorDelegate()->setFinalizationRequired();
219
finalizationRequired = true;
220
}
221
#endif /* defined(J9VM_GC_FINALIZATION) */
222
} else {
223
/* object was already marked. It is still unfinalized */
224
gcEnv->_unfinalizedObjectBuffer->add(env, object);
225
}
226
object = next;
227
}
228
}
229
}
230
}
231
}
232
233
/* Flush the local buffer of finalizable objects to the global list */
234
buffer.flush(env);
235
236
/* restore everything to a flushed state before exiting */
237
gcEnv->_unfinalizedObjectBuffer->flush(env);
238
239
reportScanningEnded(RootScannerEntity_UnfinalizedObjects);
240
}
241
}
242
243
MM_RootScanner::CompletePhaseCode
244
MM_MarkingSchemeRootClearer::scanUnfinalizedObjectsComplete(MM_EnvironmentBase *env)
245
{
246
if (_markingDelegate->shouldScanUnfinalizedObjects()) {
247
reportScanningStarted(RootScannerEntity_UnfinalizedObjectsComplete);
248
/* ensure that all unfinalized processing is complete before we start marking additional objects */
249
env->_currentTask->synchronizeGCThreads(env, UNIQUE_ID);
250
/* TODO: consider relaxing completeMarking into completeScan (which will skip over 'complete class marking' step).
251
* This is to avoid potentially unnecessary sync point in class marking step. The class marking step that we do after
252
* phantom processing might be sufficient.
253
*/
254
_markingScheme->completeMarking(env);
255
reportScanningEnded(RootScannerEntity_UnfinalizedObjectsComplete);
256
}
257
return complete_phase_OK;
258
}
259
260
void
261
MM_MarkingSchemeRootClearer::scanOwnableSynchronizerObjects(MM_EnvironmentBase *env)
262
{
263
if (_markingDelegate->shouldScanOwnableSynchronizerObjects()) {
264
/* allow the marking scheme to handle this */
265
reportScanningStarted(RootScannerEntity_OwnableSynchronizerObjects);
266
GC_Environment *gcEnv = env->getGCEnvironment();
267
268
MM_HeapRegionDescriptorStandard *region = NULL;
269
GC_HeapRegionIteratorStandard regionIterator(_extensions->heap->getHeapRegionManager());
270
while (NULL != (region = regionIterator.nextRegion())) {
271
MM_HeapRegionDescriptorStandardExtension *regionExtension = MM_ConfigurationDelegate::getHeapRegionDescriptorStandardExtension(env, region);
272
for (UDATA i = 0; i < regionExtension->_maxListIndex; i++) {
273
MM_OwnableSynchronizerObjectList *list = &regionExtension->_ownableSynchronizerObjectLists[i];
274
if (!list->wasEmpty()) {
275
if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {
276
omrobjectptr_t object = list->getPriorList();
277
while (NULL != object) {
278
gcEnv->_markJavaStats._ownableSynchronizerCandidates += 1;
279
omrobjectptr_t next = _extensions->accessBarrier->getOwnableSynchronizerLink(object);
280
if (_markingScheme->isMarked(object)) {
281
/* object was already marked. */
282
gcEnv->_ownableSynchronizerObjectBuffer->add(env, object);
283
} else {
284
/* object was not previously marked */
285
gcEnv->_markJavaStats._ownableSynchronizerCleared += 1;
286
}
287
object = next;
288
}
289
}
290
}
291
}
292
#if defined(J9VM_GC_MODRON_SCAVENGER)
293
/* correct scavenger statistics for ownableSynchronizerObjects, adjust survived ownableSynchronizerObject count in Nursery, only in generational gc */
294
if (_extensions->scavengerEnabled && (MEMORY_TYPE_NEW == (region->getTypeFlags() & MEMORY_TYPE_NEW))) {
295
gcEnv->_scavengerJavaStats.updateOwnableSynchronizerNurseryCounts(gcEnv->_markJavaStats._ownableSynchronizerCandidates - gcEnv->_markJavaStats._ownableSynchronizerCleared);
296
}
297
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
298
}
299
300
/* restore everything to a flushed state before exiting */
301
gcEnv->_ownableSynchronizerObjectBuffer->flush(env);
302
reportScanningEnded(RootScannerEntity_OwnableSynchronizerObjects);
303
}
304
}
305
306
void
307
MM_MarkingSchemeRootClearer::doMonitorReference(J9ObjectMonitor *objectMonitor, GC_HashTableIterator *monitorReferenceIterator)
308
{
309
J9ThreadAbstractMonitor * monitor = (J9ThreadAbstractMonitor*)objectMonitor->monitor;
310
_env->getGCEnvironment()->_markJavaStats._monitorReferenceCandidates += 1;
311
312
if(!_markingScheme->isMarked((omrobjectptr_t )monitor->userData)) {
313
monitorReferenceIterator->removeSlot();
314
_env->getGCEnvironment()->_markJavaStats._monitorReferenceCleared += 1;
315
/* We must call objectMonitorDestroy (as opposed to omrthread_monitor_destroy) when the
316
* monitor is not internal to the GC */
317
static_cast<J9JavaVM*>(_omrVM->_language_vm)->internalVMFunctions->objectMonitorDestroy(static_cast<J9JavaVM*>(_omrVM->_language_vm), (J9VMThread *)_env->getLanguageVMThread(), (omrthread_monitor_t)monitor);
318
}
319
}
320
321
MM_RootScanner::CompletePhaseCode
322
MM_MarkingSchemeRootClearer::scanMonitorReferencesComplete(MM_EnvironmentBase *env)
323
{
324
J9JavaVM *javaVM = (J9JavaVM *)env->getLanguageVM();
325
reportScanningStarted(RootScannerEntity_MonitorReferenceObjectsComplete);
326
javaVM->internalVMFunctions->objectMonitorDestroyComplete(javaVM, (J9VMThread *)env->getLanguageVMThread());
327
reportScanningEnded(RootScannerEntity_MonitorReferenceObjectsComplete);
328
return complete_phase_OK;
329
}
330
331
void
332
MM_MarkingSchemeRootClearer::doJNIWeakGlobalReference(omrobjectptr_t *slotPtr)
333
{
334
omrobjectptr_t objectPtr = *slotPtr;
335
if ((NULL != objectPtr) && !_markingScheme->isMarked(objectPtr)) {
336
*slotPtr = NULL;
337
}
338
}
339
340
void
341
MM_MarkingSchemeRootClearer::doRememberedSetSlot(omrobjectptr_t *slotPtr, GC_RememberedSetSlotIterator *rememberedSetSlotIterator)
342
{
343
omrobjectptr_t objectPtr = *slotPtr;
344
if (objectPtr == NULL) {
345
rememberedSetSlotIterator->removeSlot();
346
} else if (!_markingScheme->isMarked(objectPtr)) {
347
_extensions->objectModel.clearRemembered(objectPtr);
348
rememberedSetSlotIterator->removeSlot();
349
}
350
}
351
352
void
353
MM_MarkingSchemeRootClearer::doStringTableSlot(omrobjectptr_t *slotPtr, GC_StringTableIterator *stringTableIterator)
354
{
355
_env->getGCEnvironment()->_markJavaStats._stringConstantsCandidates += 1;
356
if(!_markingScheme->isMarked(*slotPtr)) {
357
_env->getGCEnvironment()->_markJavaStats._stringConstantsCleared += 1;
358
stringTableIterator->removeSlot();
359
}
360
}
361
362
/**
363
* @Clear the string table cache slot if the object is not marked
364
*/
365
void
366
MM_MarkingSchemeRootClearer::doStringCacheTableSlot(omrobjectptr_t *slotPtr)
367
{
368
omrobjectptr_t objectPtr = *slotPtr;
369
if((NULL != objectPtr) && (!_markingScheme->isMarked(*slotPtr))) {
370
*slotPtr = NULL;
371
}
372
}
373
374
void
375
MM_MarkingSchemeRootClearer::doJVMTIObjectTagSlot(omrobjectptr_t *slotPtr, GC_JVMTIObjectTagTableIterator *objectTagTableIterator)
376
{
377
if(!_markingScheme->isMarked(*slotPtr)) {
378
objectTagTableIterator->removeSlot();
379
}
380
}
381
382