Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/ConcurrentMarkingDelegate.hpp
5990 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(CONCURRENTMARKINGDELEGATE_HPP_)
24
#define CONCURRENTMARKINGDELEGATE_HPP_
25
26
#include "j9.h"
27
#include "j9cfg.h"
28
29
#if defined(OMR_GC_MODRON_CONCURRENT_MARK)
30
#include "j9class.h"
31
#include "j9consts.h"
32
#include "j9cp.h"
33
#include "j9modron.h"
34
#include "j9nongenerated.h"
35
#include "j9nonbuilder.h"
36
#include "modron.h"
37
#include "objectdescription.h"
38
#include "omrgcconsts.h"
39
40
#include "ConcurrentSafepointCallbackJava.hpp"
41
#include "EnvironmentBase.hpp"
42
#include "GCExtensionsBase.hpp"
43
#include "MarkingScheme.hpp"
44
#include "ReferenceObjectBuffer.hpp"
45
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
46
#include "ScanClassesMode.hpp"
47
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
48
49
class GC_VMThreadIterator;
50
class MM_ConcurrentGC;
51
class MM_MarkingScheme;
52
53
/**
54
* Provides language-specific support for marking.
55
*/
56
class MM_ConcurrentMarkingDelegate
57
{
58
/*
59
* Data members
60
*/
61
private:
62
63
protected:
64
J9JavaVM *_javaVM;
65
GC_ObjectModel *_objectModel;
66
MM_ConcurrentGC *_collector;
67
MM_MarkingScheme *_markingScheme;
68
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
69
MM_ScanClassesMode _scanClassesMode; /** Support for dynamic class unloading in concurrent mark */
70
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
71
72
public:
73
/* This enum extends ConcurrentStatus with values in the exclusive range (CONCURRENT_ROOT_TRACING,
74
* CONCURRENT_TRACE_ONLY). ConcurrentStatus extensions allow the client language to define discrete
75
* units of work that can be executed in parallel by concurrent threads. ConcurrentGC will call
76
* MM_ConcurrentMarkingDelegate::collectRoots(..., concurrentStatus, ...) only once with each
77
* client-defined status value. The thread that receives the call can check the concurrentStatus
78
* value to select and execute the appropriate unit of work.
79
*
80
* @see ConcurrentStatus (omrgcconsts.h)
81
*/
82
enum {
83
CONCURRENT_ROOT_TRACING1 = CONCURRENT_ROOT_TRACING + 1
84
, CONCURRENT_ROOT_TRACING2 = CONCURRENT_ROOT_TRACING + 2
85
, CONCURRENT_ROOT_TRACING3 = CONCURRENT_ROOT_TRACING + 3
86
, CONCURRENT_ROOT_TRACING4 = CONCURRENT_ROOT_TRACING + 4
87
};
88
89
typedef struct markSchemeStackIteratorData {
90
MM_MarkingScheme *markingScheme;
91
MM_EnvironmentBase *env;
92
} markSchemeStackIteratorData;
93
94
/*
95
* Function members
96
*/
97
private:
98
void collectJNIRoots(MM_EnvironmentBase *env, bool *completedJNIRoots);
99
void collectClassRoots(MM_EnvironmentBase *env, bool *completedClassRoots, bool *classesMarkedAsRoots);
100
void collectFinalizableRoots(MM_EnvironmentBase *env, bool *completedFinalizableRoots);
101
void collectStringRoots(MM_EnvironmentBase *env, bool *completedStringRoots, bool *collectedStringConstants);
102
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
103
uintptr_t concurrentClassMark(MM_EnvironmentBase *env, bool *completedClassMark);
104
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
105
106
protected:
107
108
public:
109
/**
110
* Initialize the delegate.
111
*
112
* @param env environment for calling thread
113
* @return true if delegate initialized successfully
114
*/
115
bool initialize(MM_EnvironmentBase *env, MM_ConcurrentGC *collector);
116
117
/**
118
* In the case of Weak Consistency platforms we require this method to bring mutator threads to a safe point. A safe
119
* point is a point at which a GC may occur.
120
*
121
* @param[in] env The environment for the calling thread.
122
* @return An instance of a MM_ConcurrentSafepointCallback instance that can signal all mutator threads and cause them
123
* to synchronize at a safe point
124
* @see MM_ConcurrentSafepointCallback
125
*/
126
MMINLINE MM_ConcurrentSafepointCallback*
127
createSafepointCallback(MM_EnvironmentBase *env)
128
{
129
return MM_ConcurrentSafepointCallbackJava::newInstance(env);
130
}
131
132
/**
133
* Concurrent marking component maintains a background helper thread to assist with concurrent marking
134
* tasks. The delegate may provide a specialized signal handler (and associated argument) to process
135
* signals raised from this thread.
136
*
137
* @param[out] signalHandlerArg receives (nullable) pointer to argument to be passed to signal handler when invoked
138
* @return a pointer to the signal handler function (or NULL if no signal handler)
139
*/
140
MMINLINE omrsig_handler_fn
141
getProtectedSignalHandler(void **signalHandlerArg)
142
{
143
*signalHandlerArg = (void *)_javaVM;
144
return (omrsig_handler_fn)_javaVM->internalVMFunctions->structuredSignalHandlerVM;
145
}
146
147
/**
148
* Test whether a GC can be started. Under some circumstances it may be desirable to circumvent continued
149
* concurrent marking and allow a GC to kick off immediately. In that case this method should return true
150
* and set the kick off reason.
151
*
152
* If this method returns false, the GC cycle may be started immediately. Otherwise, concurrent marking
153
* will kick off and the GC cycle will be deferred until concurrent marking completes.
154
*
155
* @param env the calling thread environment
156
* @param gcCode the GC code identifying the cause of the GC request
157
* @param languageKickoffReason set this to the value to be reported as kickoff reson in verbose GC log
158
* @see J9MMCONSTANT_* (j9nonbuilder.h) for gcCode values
159
* @return true if Kickoff can be forced
160
*/
161
MMINLINE bool
162
canForceConcurrentKickoff(MM_EnvironmentBase *env, uintptr_t gcCode, uintptr_t *languageKickoffReason)
163
{
164
if (J9MMCONSTANT_IMPLICIT_GC_PERCOLATE_UNLOADING_CLASSES == gcCode) {
165
*languageKickoffReason = FORCED_UNLOADING_CLASSES;
166
return true;
167
}
168
return false;
169
}
170
171
MMINLINE uintptr_t
172
getNextTracingMode(uintptr_t executionMode)
173
{
174
uintptr_t nextExecutionMode = CONCURRENT_TRACE_ONLY;
175
176
switch (executionMode) {
177
case CONCURRENT_ROOT_TRACING:
178
nextExecutionMode = CONCURRENT_ROOT_TRACING1;
179
break;
180
case CONCURRENT_ROOT_TRACING1:
181
nextExecutionMode = CONCURRENT_ROOT_TRACING2;
182
break;
183
case CONCURRENT_ROOT_TRACING2:
184
nextExecutionMode = CONCURRENT_ROOT_TRACING3;
185
break;
186
case CONCURRENT_ROOT_TRACING3:
187
nextExecutionMode = CONCURRENT_ROOT_TRACING4;
188
break;
189
case CONCURRENT_ROOT_TRACING4:
190
nextExecutionMode = CONCURRENT_TRACE_ONLY;
191
break;
192
default:
193
Assert_MM_unreachable();
194
}
195
196
return nextExecutionMode;
197
}
198
199
MMINLINE uintptr_t
200
collectRoots(MM_EnvironmentBase *env, uintptr_t concurrentStatus, bool *collectedRoots, bool *paidTax)
201
{
202
uintptr_t bytesScanned = 0;
203
*collectedRoots = true;
204
*paidTax = true;
205
206
switch (concurrentStatus) {
207
case CONCURRENT_ROOT_TRACING1:
208
collectJNIRoots(env, collectedRoots);
209
break;
210
case CONCURRENT_ROOT_TRACING2:
211
collectClassRoots(env, paidTax, collectedRoots);
212
break;
213
case CONCURRENT_ROOT_TRACING3:
214
collectFinalizableRoots(env, collectedRoots);
215
break;
216
case CONCURRENT_ROOT_TRACING4:
217
collectStringRoots(env, paidTax, collectedRoots);
218
break;
219
default:
220
Assert_MM_unreachable();
221
}
222
223
return bytesScanned;
224
}
225
226
MMINLINE void
227
concurrentInitializationComplete(MM_EnvironmentBase *env)
228
{
229
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
230
_scanClassesMode.setScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_DISABLED); /* disable concurrent classes scan - default state */
231
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
232
}
233
234
MMINLINE void cardCleaningStarted(MM_EnvironmentBase *env)
235
{
236
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
237
/* If scanning of classes is enabled and was completed in CONCURRENT_TRACE_ONLY state - start it again*/
238
_scanClassesMode.switchScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_COMPLETE, MM_ScanClassesMode::SCAN_CLASSES_NEED_TO_BE_EXECUTED);
239
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
240
}
241
242
/**
243
* Signal all threads for call back. Iterate over all threads and signal each to call scanThread()
244
* so we can scan their stacks for roots.
245
*/
246
void signalThreadsToTraceStacks(MM_EnvironmentBase *env);
247
248
void signalThreadsToActivateWriteBarrier(MM_EnvironmentBase *env);
249
250
void signalThreadsToDeactivateWriteBarrier(MM_EnvironmentBase *env);
251
252
/**
253
* This method is called during card cleaning for each object associated with an uncleaned, dirty card in the card
254
* table. No client actions are necessary but this method may be overridden if desired to hook into card cleaning.
255
*
256
* @param[in] env The environment for the calling thread.
257
* @param[in] objectPtr Reference to an object associated with an uncleaned, dirty card.
258
*/
259
MMINLINE void
260
processItem(MM_EnvironmentBase *env, omrobjectptr_t objectPtr)
261
{
262
if (GC_ObjectModel::SCAN_REFERENCE_MIXED_OBJECT == _objectModel->getScanType(objectPtr)) {
263
/* since we popped this object from the work packet, it is our responsibility to record it in the list of reference objects */
264
/* we know that the object must be in the collection set because it was on a work packet */
265
/* we don't need to process cleared or enqueued references */
266
if (GC_ObjectModel::REF_STATE_INITIAL == J9GC_J9VMJAVALANGREFERENCE_STATE(env, objectPtr)) {
267
env->getGCEnvironment()->_referenceObjectBuffer->add(env, objectPtr);
268
}
269
}
270
}
271
272
/**
273
* Scan a thread structure and stack frames for roots. Implementation must call
274
* MM_MarkingScheme::markObject(MM_EnvironmentBase *, omrobjectptr_t) for
275
* each heap object reference found on the thread's stack or in thread structure.
276
*
277
* @param env the thread environment for the thread to be scanned
278
* @return true if the thread was scanned successfully
279
*/
280
bool scanThreadRoots(MM_EnvironmentBase *env);
281
282
/**
283
* Flush any roots held in thread local buffers.
284
*
285
* @param env the thread environment for the thread to be flushed
286
* @return true if any data were flushed, false otherwise
287
*/
288
MMINLINE bool
289
flushThreadRoots(MM_EnvironmentBase *env)
290
{
291
bool wasEmpty = env->getGCEnvironment()->_referenceObjectBuffer->isEmpty();
292
env->getGCEnvironment()->_referenceObjectBuffer->flush(env);
293
return !wasEmpty;
294
}
295
296
void abortCollection(MM_EnvironmentBase *env);
297
298
/**
299
*
300
*/
301
MMINLINE bool
302
startConcurrentScanning(MM_EnvironmentBase *env, uintptr_t *bytesTraced, bool *collectedRoots)
303
{
304
*bytesTraced = 0;
305
*collectedRoots = false;
306
bool started = false;
307
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
308
if (_scanClassesMode.switchScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_NEED_TO_BE_EXECUTED, MM_ScanClassesMode::SCAN_CLASSES_CURRENTLY_ACTIVE)) { /* currently not running */
309
*bytesTraced = concurrentClassMark(env, collectedRoots);
310
started = true;
311
}
312
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
313
return started;
314
}
315
316
MMINLINE void
317
concurrentScanningStarted(MM_EnvironmentBase *env, uintptr_t bytesTraced)
318
{
319
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
320
if (0 != bytesTraced) {
321
setConcurrentScanning(env);/* need more iterations */
322
} else {
323
_scanClassesMode.setScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_COMPLETE); /* complete for now */
324
}
325
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
326
}
327
328
MMINLINE void
329
setConcurrentScanning(MM_EnvironmentBase *env)
330
{
331
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
332
_scanClassesMode.setScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_NEED_TO_BE_EXECUTED);
333
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
334
}
335
336
MMINLINE bool
337
isConcurrentScanningComplete(MM_EnvironmentBase *env)
338
{
339
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
340
return !_scanClassesMode.isPendingOrActiveMode();
341
#else
342
return true;
343
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
344
}
345
346
MMINLINE uintptr_t
347
reportConcurrentScanningMode(MM_EnvironmentBase *env)
348
{
349
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
350
return _scanClassesMode.getScanClassesMode();
351
#else
352
return 0;
353
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
354
}
355
356
bool setupClassScanning(MM_EnvironmentBase *env);
357
358
/**
359
* Constructor.
360
*/
361
MMINLINE MM_ConcurrentMarkingDelegate()
362
: _javaVM(NULL)
363
, _objectModel(NULL)
364
, _collector(NULL)
365
, _markingScheme(NULL)
366
{ }
367
};
368
369
#endif /* defined(OMR_GC_MODRON_CONCURRENT_MARK) */
370
#endif /* CONCURRENTMARKINGDELEGATE_HPP_ */
371
372