Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/gc/z/zDriver.cpp
40961 views
1
/*
2
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
#include "precompiled.hpp"
25
#include "gc/shared/gcId.hpp"
26
#include "gc/shared/gcLocker.hpp"
27
#include "gc/shared/gcVMOperations.hpp"
28
#include "gc/shared/isGCActiveMark.hpp"
29
#include "gc/z/zAbort.inline.hpp"
30
#include "gc/z/zBreakpoint.hpp"
31
#include "gc/z/zCollectedHeap.hpp"
32
#include "gc/z/zDriver.hpp"
33
#include "gc/z/zHeap.inline.hpp"
34
#include "gc/z/zMessagePort.inline.hpp"
35
#include "gc/z/zServiceability.hpp"
36
#include "gc/z/zStat.hpp"
37
#include "gc/z/zVerify.hpp"
38
#include "logging/log.hpp"
39
#include "memory/universe.hpp"
40
#include "runtime/vmOperations.hpp"
41
#include "runtime/vmThread.hpp"
42
43
static const ZStatPhaseCycle ZPhaseCycle("Garbage Collection Cycle");
44
static const ZStatPhasePause ZPhasePauseMarkStart("Pause Mark Start");
45
static const ZStatPhaseConcurrent ZPhaseConcurrentMark("Concurrent Mark");
46
static const ZStatPhaseConcurrent ZPhaseConcurrentMarkContinue("Concurrent Mark Continue");
47
static const ZStatPhaseConcurrent ZPhaseConcurrentMarkFree("Concurrent Mark Free");
48
static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End");
49
static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References");
50
static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set");
51
static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set");
52
static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start");
53
static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate");
54
static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */);
55
static const ZStatSampler ZSamplerJavaThreads("System", "Java Threads", ZStatUnitThreads);
56
57
class VM_ZOperation : public VM_Operation {
58
private:
59
const uint _gc_id;
60
bool _gc_locked;
61
bool _success;
62
63
public:
64
VM_ZOperation() :
65
_gc_id(GCId::current()),
66
_gc_locked(false),
67
_success(false) {}
68
69
virtual bool needs_inactive_gc_locker() const {
70
// An inactive GC locker is needed in operations where we change the bad
71
// mask or move objects. Changing the bad mask will invalidate all oops,
72
// which makes it conceptually the same thing as moving all objects.
73
return false;
74
}
75
76
virtual bool skip_thread_oop_barriers() const {
77
return true;
78
}
79
80
virtual bool do_operation() = 0;
81
82
virtual bool doit_prologue() {
83
Heap_lock->lock();
84
return true;
85
}
86
87
virtual void doit() {
88
// Abort if GC locker state is incompatible
89
if (needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) {
90
_gc_locked = true;
91
return;
92
}
93
94
// Setup GC id and active marker
95
GCIdMark gc_id_mark(_gc_id);
96
IsGCActiveMark gc_active_mark;
97
98
// Verify before operation
99
ZVerify::before_zoperation();
100
101
// Execute operation
102
_success = do_operation();
103
104
// Update statistics
105
ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads());
106
}
107
108
virtual void doit_epilogue() {
109
Heap_lock->unlock();
110
}
111
112
bool gc_locked() const {
113
return _gc_locked;
114
}
115
116
bool success() const {
117
return _success;
118
}
119
};
120
121
static bool should_clear_soft_references() {
122
// Clear if one or more allocations have stalled
123
const bool stalled = ZHeap::heap()->is_alloc_stalled();
124
if (stalled) {
125
// Clear
126
return true;
127
}
128
129
// Clear if implied by the GC cause
130
const GCCause::Cause cause = ZCollectedHeap::heap()->gc_cause();
131
if (cause == GCCause::_wb_full_gc ||
132
cause == GCCause::_metadata_GC_clear_soft_refs) {
133
// Clear
134
return true;
135
}
136
137
// Don't clear
138
return false;
139
}
140
141
static bool should_boost_worker_threads() {
142
// Boost worker threads if one or more allocations have stalled
143
const bool stalled = ZHeap::heap()->is_alloc_stalled();
144
if (stalled) {
145
// Boost
146
return true;
147
}
148
149
// Boost worker threads if implied by the GC cause
150
const GCCause::Cause cause = ZCollectedHeap::heap()->gc_cause();
151
if (cause == GCCause::_wb_full_gc ||
152
cause == GCCause::_java_lang_system_gc ||
153
cause == GCCause::_metadata_GC_clear_soft_refs) {
154
// Boost
155
return true;
156
}
157
158
// Don't boost
159
return false;
160
}
161
162
class VM_ZMarkStart : public VM_ZOperation {
163
public:
164
virtual VMOp_Type type() const {
165
return VMOp_ZMarkStart;
166
}
167
168
virtual bool needs_inactive_gc_locker() const {
169
return true;
170
}
171
172
virtual bool do_operation() {
173
ZStatTimer timer(ZPhasePauseMarkStart);
174
ZServiceabilityPauseTracer tracer;
175
176
// Set up soft reference policy
177
const bool clear = should_clear_soft_references();
178
ZHeap::heap()->set_soft_reference_policy(clear);
179
180
// Set up boost mode
181
const bool boost = should_boost_worker_threads();
182
ZHeap::heap()->set_boost_worker_threads(boost);
183
184
ZCollectedHeap::heap()->increment_total_collections(true /* full */);
185
186
ZHeap::heap()->mark_start();
187
return true;
188
}
189
};
190
191
class VM_ZMarkEnd : public VM_ZOperation {
192
public:
193
virtual VMOp_Type type() const {
194
return VMOp_ZMarkEnd;
195
}
196
197
virtual bool do_operation() {
198
ZStatTimer timer(ZPhasePauseMarkEnd);
199
ZServiceabilityPauseTracer tracer;
200
return ZHeap::heap()->mark_end();
201
}
202
};
203
204
class VM_ZRelocateStart : public VM_ZOperation {
205
public:
206
virtual VMOp_Type type() const {
207
return VMOp_ZRelocateStart;
208
}
209
210
virtual bool needs_inactive_gc_locker() const {
211
return true;
212
}
213
214
virtual bool do_operation() {
215
ZStatTimer timer(ZPhasePauseRelocateStart);
216
ZServiceabilityPauseTracer tracer;
217
ZHeap::heap()->relocate_start();
218
return true;
219
}
220
};
221
222
class VM_ZVerify : public VM_Operation {
223
public:
224
virtual VMOp_Type type() const {
225
return VMOp_ZVerify;
226
}
227
228
virtual bool skip_thread_oop_barriers() const {
229
return true;
230
}
231
232
virtual void doit() {
233
ZVerify::after_weak_processing();
234
}
235
};
236
237
ZDriver::ZDriver() :
238
_gc_cycle_port(),
239
_gc_locker_port() {
240
set_name("ZDriver");
241
create_and_start();
242
}
243
244
void ZDriver::collect(GCCause::Cause cause) {
245
switch (cause) {
246
case GCCause::_wb_young_gc:
247
case GCCause::_wb_conc_mark:
248
case GCCause::_wb_full_gc:
249
case GCCause::_dcmd_gc_run:
250
case GCCause::_java_lang_system_gc:
251
case GCCause::_full_gc_alot:
252
case GCCause::_scavenge_alot:
253
case GCCause::_jvmti_force_gc:
254
case GCCause::_metadata_GC_clear_soft_refs:
255
// Start synchronous GC
256
_gc_cycle_port.send_sync(cause);
257
break;
258
259
case GCCause::_z_timer:
260
case GCCause::_z_warmup:
261
case GCCause::_z_allocation_rate:
262
case GCCause::_z_allocation_stall:
263
case GCCause::_z_proactive:
264
case GCCause::_z_high_usage:
265
case GCCause::_metadata_GC_threshold:
266
// Start asynchronous GC
267
_gc_cycle_port.send_async(cause);
268
break;
269
270
case GCCause::_gc_locker:
271
// Restart VM operation previously blocked by the GC locker
272
_gc_locker_port.signal();
273
break;
274
275
case GCCause::_wb_breakpoint:
276
ZBreakpoint::start_gc();
277
_gc_cycle_port.send_async(cause);
278
break;
279
280
default:
281
// Other causes not supported
282
fatal("Unsupported GC cause (%s)", GCCause::to_string(cause));
283
break;
284
}
285
}
286
287
template <typename T>
288
bool ZDriver::pause() {
289
for (;;) {
290
T op;
291
VMThread::execute(&op);
292
if (op.gc_locked()) {
293
// Wait for GC to become unlocked and restart the VM operation
294
ZStatTimer timer(ZCriticalPhaseGCLockerStall);
295
_gc_locker_port.wait();
296
continue;
297
}
298
299
// Notify VM operation completed
300
_gc_locker_port.ack();
301
302
return op.success();
303
}
304
}
305
306
void ZDriver::pause_mark_start() {
307
pause<VM_ZMarkStart>();
308
}
309
310
void ZDriver::concurrent_mark() {
311
ZStatTimer timer(ZPhaseConcurrentMark);
312
ZBreakpoint::at_after_marking_started();
313
ZHeap::heap()->mark(true /* initial */);
314
ZBreakpoint::at_before_marking_completed();
315
}
316
317
bool ZDriver::pause_mark_end() {
318
return pause<VM_ZMarkEnd>();
319
}
320
321
void ZDriver::concurrent_mark_continue() {
322
ZStatTimer timer(ZPhaseConcurrentMarkContinue);
323
ZHeap::heap()->mark(false /* initial */);
324
}
325
326
void ZDriver::concurrent_mark_free() {
327
ZStatTimer timer(ZPhaseConcurrentMarkFree);
328
ZHeap::heap()->mark_free();
329
}
330
331
void ZDriver::concurrent_process_non_strong_references() {
332
ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences);
333
ZBreakpoint::at_after_reference_processing_started();
334
ZHeap::heap()->process_non_strong_references();
335
}
336
337
void ZDriver::concurrent_reset_relocation_set() {
338
ZStatTimer timer(ZPhaseConcurrentResetRelocationSet);
339
ZHeap::heap()->reset_relocation_set();
340
}
341
342
void ZDriver::pause_verify() {
343
if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
344
// Full verification
345
VM_Verify op;
346
VMThread::execute(&op);
347
} else if (ZVerifyRoots || ZVerifyObjects) {
348
// Limited verification
349
VM_ZVerify op;
350
VMThread::execute(&op);
351
}
352
}
353
354
void ZDriver::concurrent_select_relocation_set() {
355
ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet);
356
ZHeap::heap()->select_relocation_set();
357
}
358
359
void ZDriver::pause_relocate_start() {
360
pause<VM_ZRelocateStart>();
361
}
362
363
void ZDriver::concurrent_relocate() {
364
ZStatTimer timer(ZPhaseConcurrentRelocated);
365
ZHeap::heap()->relocate();
366
}
367
368
void ZDriver::check_out_of_memory() {
369
ZHeap::heap()->check_out_of_memory();
370
}
371
372
class ZDriverGCScope : public StackObj {
373
private:
374
GCIdMark _gc_id;
375
GCCause::Cause _gc_cause;
376
GCCauseSetter _gc_cause_setter;
377
ZStatTimer _timer;
378
ZServiceabilityCycleTracer _tracer;
379
380
public:
381
ZDriverGCScope(GCCause::Cause cause) :
382
_gc_id(),
383
_gc_cause(cause),
384
_gc_cause_setter(ZCollectedHeap::heap(), cause),
385
_timer(ZPhaseCycle),
386
_tracer() {
387
// Update statistics
388
ZStatCycle::at_start();
389
}
390
391
~ZDriverGCScope() {
392
// Calculate boost factor
393
const double boost_factor = (double)ZHeap::heap()->nconcurrent_worker_threads() /
394
(double)ZHeap::heap()->nconcurrent_no_boost_worker_threads();
395
396
// Update statistics
397
ZStatCycle::at_end(_gc_cause, boost_factor);
398
399
// Update data used by soft reference policy
400
Universe::heap()->update_capacity_and_used_at_gc();
401
402
// Signal that we have completed a visit to all live objects
403
Universe::heap()->record_whole_heap_examined_timestamp();
404
}
405
};
406
407
// Macro to execute a termination check after a concurrent phase. Note
408
// that it's important that the termination check comes after the call
409
// to the function f, since we can't abort between pause_relocate_start()
410
// and concurrent_relocate(). We need to let concurrent_relocate() call
411
// abort_page() on the remaining entries in the relocation set.
412
#define concurrent(f) \
413
do { \
414
concurrent_##f(); \
415
if (should_terminate()) { \
416
return; \
417
} \
418
} while (false)
419
420
void ZDriver::gc(GCCause::Cause cause) {
421
ZDriverGCScope scope(cause);
422
423
// Phase 1: Pause Mark Start
424
pause_mark_start();
425
426
// Phase 2: Concurrent Mark
427
concurrent(mark);
428
429
// Phase 3: Pause Mark End
430
while (!pause_mark_end()) {
431
// Phase 3.5: Concurrent Mark Continue
432
concurrent(mark_continue);
433
}
434
435
// Phase 4: Concurrent Mark Free
436
concurrent(mark_free);
437
438
// Phase 5: Concurrent Process Non-Strong References
439
concurrent(process_non_strong_references);
440
441
// Phase 6: Concurrent Reset Relocation Set
442
concurrent(reset_relocation_set);
443
444
// Phase 7: Pause Verify
445
pause_verify();
446
447
// Phase 8: Concurrent Select Relocation Set
448
concurrent(select_relocation_set);
449
450
// Phase 9: Pause Relocate Start
451
pause_relocate_start();
452
453
// Phase 10: Concurrent Relocate
454
concurrent(relocate);
455
}
456
457
void ZDriver::run_service() {
458
// Main loop
459
while (!should_terminate()) {
460
// Wait for GC request
461
const GCCause::Cause cause = _gc_cycle_port.receive();
462
if (cause == GCCause::_no_gc) {
463
continue;
464
}
465
466
ZBreakpoint::at_before_gc();
467
468
// Run GC
469
gc(cause);
470
471
// Notify GC completed
472
_gc_cycle_port.ack();
473
474
// Check for out of memory condition
475
check_out_of_memory();
476
477
ZBreakpoint::at_after_gc();
478
}
479
}
480
481
void ZDriver::stop_service() {
482
ZAbort::abort();
483
_gc_cycle_port.send_async(GCCause::_no_gc);
484
}
485
486