Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/share/gc/z/zDriver.cpp
66644 views
1
/*
2
* Copyright (c) 2015, 2021, 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
ZDriverRequest::ZDriverRequest() :
58
ZDriverRequest(GCCause::_no_gc) {}
59
60
ZDriverRequest::ZDriverRequest(GCCause::Cause cause) :
61
ZDriverRequest(cause, ConcGCThreads) {}
62
63
ZDriverRequest::ZDriverRequest(GCCause::Cause cause, uint nworkers) :
64
_cause(cause),
65
_nworkers(nworkers) {}
66
67
bool ZDriverRequest::operator==(const ZDriverRequest& other) const {
68
return _cause == other._cause;
69
}
70
71
GCCause::Cause ZDriverRequest::cause() const {
72
return _cause;
73
}
74
75
uint ZDriverRequest::nworkers() const {
76
return _nworkers;
77
}
78
79
class VM_ZOperation : public VM_Operation {
80
private:
81
const uint _gc_id;
82
bool _gc_locked;
83
bool _success;
84
85
public:
86
VM_ZOperation() :
87
_gc_id(GCId::current()),
88
_gc_locked(false),
89
_success(false) {}
90
91
virtual bool needs_inactive_gc_locker() const {
92
// An inactive GC locker is needed in operations where we change the bad
93
// mask or move objects. Changing the bad mask will invalidate all oops,
94
// which makes it conceptually the same thing as moving all objects.
95
return false;
96
}
97
98
virtual bool skip_thread_oop_barriers() const {
99
return true;
100
}
101
102
virtual bool do_operation() = 0;
103
104
virtual bool doit_prologue() {
105
Heap_lock->lock();
106
return true;
107
}
108
109
virtual void doit() {
110
// Abort if GC locker state is incompatible
111
if (needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) {
112
_gc_locked = true;
113
return;
114
}
115
116
// Setup GC id and active marker
117
GCIdMark gc_id_mark(_gc_id);
118
IsGCActiveMark gc_active_mark;
119
120
// Verify before operation
121
ZVerify::before_zoperation();
122
123
// Execute operation
124
_success = do_operation();
125
126
// Update statistics
127
ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads());
128
}
129
130
virtual void doit_epilogue() {
131
Heap_lock->unlock();
132
}
133
134
bool gc_locked() const {
135
return _gc_locked;
136
}
137
138
bool success() const {
139
return _success;
140
}
141
};
142
143
class VM_ZMarkStart : public VM_ZOperation {
144
public:
145
virtual VMOp_Type type() const {
146
return VMOp_ZMarkStart;
147
}
148
149
virtual bool needs_inactive_gc_locker() const {
150
return true;
151
}
152
153
virtual bool do_operation() {
154
ZStatTimer timer(ZPhasePauseMarkStart);
155
ZServiceabilityPauseTracer tracer;
156
157
ZCollectedHeap::heap()->increment_total_collections(true /* full */);
158
159
ZHeap::heap()->mark_start();
160
return true;
161
}
162
};
163
164
class VM_ZMarkEnd : public VM_ZOperation {
165
public:
166
virtual VMOp_Type type() const {
167
return VMOp_ZMarkEnd;
168
}
169
170
virtual bool do_operation() {
171
ZStatTimer timer(ZPhasePauseMarkEnd);
172
ZServiceabilityPauseTracer tracer;
173
return ZHeap::heap()->mark_end();
174
}
175
};
176
177
class VM_ZRelocateStart : public VM_ZOperation {
178
public:
179
virtual VMOp_Type type() const {
180
return VMOp_ZRelocateStart;
181
}
182
183
virtual bool needs_inactive_gc_locker() const {
184
return true;
185
}
186
187
virtual bool do_operation() {
188
ZStatTimer timer(ZPhasePauseRelocateStart);
189
ZServiceabilityPauseTracer tracer;
190
ZHeap::heap()->relocate_start();
191
return true;
192
}
193
};
194
195
class VM_ZVerify : public VM_Operation {
196
public:
197
virtual VMOp_Type type() const {
198
return VMOp_ZVerify;
199
}
200
201
virtual bool skip_thread_oop_barriers() const {
202
return true;
203
}
204
205
virtual void doit() {
206
ZVerify::after_weak_processing();
207
}
208
};
209
210
ZDriver::ZDriver() :
211
_gc_cycle_port(),
212
_gc_locker_port() {
213
set_name("ZDriver");
214
create_and_start();
215
}
216
217
bool ZDriver::is_busy() const {
218
return _gc_cycle_port.is_busy();
219
}
220
221
void ZDriver::collect(const ZDriverRequest& request) {
222
switch (request.cause()) {
223
case GCCause::_wb_young_gc:
224
case GCCause::_wb_conc_mark:
225
case GCCause::_wb_full_gc:
226
case GCCause::_dcmd_gc_run:
227
case GCCause::_java_lang_system_gc:
228
case GCCause::_full_gc_alot:
229
case GCCause::_scavenge_alot:
230
case GCCause::_jvmti_force_gc:
231
case GCCause::_metadata_GC_clear_soft_refs:
232
// Start synchronous GC
233
_gc_cycle_port.send_sync(request);
234
break;
235
236
case GCCause::_z_timer:
237
case GCCause::_z_warmup:
238
case GCCause::_z_allocation_rate:
239
case GCCause::_z_allocation_stall:
240
case GCCause::_z_proactive:
241
case GCCause::_z_high_usage:
242
case GCCause::_metadata_GC_threshold:
243
// Start asynchronous GC
244
_gc_cycle_port.send_async(request);
245
break;
246
247
case GCCause::_gc_locker:
248
// Restart VM operation previously blocked by the GC locker
249
_gc_locker_port.signal();
250
break;
251
252
case GCCause::_wb_breakpoint:
253
ZBreakpoint::start_gc();
254
_gc_cycle_port.send_async(request);
255
break;
256
257
default:
258
// Other causes not supported
259
fatal("Unsupported GC cause (%s)", GCCause::to_string(request.cause()));
260
break;
261
}
262
}
263
264
template <typename T>
265
bool ZDriver::pause() {
266
for (;;) {
267
T op;
268
VMThread::execute(&op);
269
if (op.gc_locked()) {
270
// Wait for GC to become unlocked and restart the VM operation
271
ZStatTimer timer(ZCriticalPhaseGCLockerStall);
272
_gc_locker_port.wait();
273
continue;
274
}
275
276
// Notify VM operation completed
277
_gc_locker_port.ack();
278
279
return op.success();
280
}
281
}
282
283
void ZDriver::pause_mark_start() {
284
pause<VM_ZMarkStart>();
285
}
286
287
void ZDriver::concurrent_mark() {
288
ZStatTimer timer(ZPhaseConcurrentMark);
289
ZBreakpoint::at_after_marking_started();
290
ZHeap::heap()->mark(true /* initial */);
291
ZBreakpoint::at_before_marking_completed();
292
}
293
294
bool ZDriver::pause_mark_end() {
295
return pause<VM_ZMarkEnd>();
296
}
297
298
void ZDriver::concurrent_mark_continue() {
299
ZStatTimer timer(ZPhaseConcurrentMarkContinue);
300
ZHeap::heap()->mark(false /* initial */);
301
}
302
303
void ZDriver::concurrent_mark_free() {
304
ZStatTimer timer(ZPhaseConcurrentMarkFree);
305
ZHeap::heap()->mark_free();
306
}
307
308
void ZDriver::concurrent_process_non_strong_references() {
309
ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences);
310
ZBreakpoint::at_after_reference_processing_started();
311
ZHeap::heap()->process_non_strong_references();
312
}
313
314
void ZDriver::concurrent_reset_relocation_set() {
315
ZStatTimer timer(ZPhaseConcurrentResetRelocationSet);
316
ZHeap::heap()->reset_relocation_set();
317
}
318
319
void ZDriver::pause_verify() {
320
if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
321
// Full verification
322
VM_Verify op;
323
VMThread::execute(&op);
324
} else if (ZVerifyRoots || ZVerifyObjects) {
325
// Limited verification
326
VM_ZVerify op;
327
VMThread::execute(&op);
328
}
329
}
330
331
void ZDriver::concurrent_select_relocation_set() {
332
ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet);
333
ZHeap::heap()->select_relocation_set();
334
}
335
336
void ZDriver::pause_relocate_start() {
337
pause<VM_ZRelocateStart>();
338
}
339
340
void ZDriver::concurrent_relocate() {
341
ZStatTimer timer(ZPhaseConcurrentRelocated);
342
ZHeap::heap()->relocate();
343
}
344
345
void ZDriver::check_out_of_memory() {
346
ZHeap::heap()->check_out_of_memory();
347
}
348
349
static bool should_clear_soft_references(const ZDriverRequest& request) {
350
// Clear soft references if implied by the GC cause
351
if (request.cause() == GCCause::_wb_full_gc ||
352
request.cause() == GCCause::_metadata_GC_clear_soft_refs ||
353
request.cause() == GCCause::_z_allocation_stall) {
354
// Clear
355
return true;
356
}
357
358
// Don't clear
359
return false;
360
}
361
362
static uint select_active_worker_threads_dynamic(const ZDriverRequest& request) {
363
// Use requested number of worker threads
364
return request.nworkers();
365
}
366
367
static uint select_active_worker_threads_static(const ZDriverRequest& request) {
368
const GCCause::Cause cause = request.cause();
369
const uint nworkers = request.nworkers();
370
371
// Boost number of worker threads if implied by the GC cause
372
if (cause == GCCause::_wb_full_gc ||
373
cause == GCCause::_java_lang_system_gc ||
374
cause == GCCause::_metadata_GC_clear_soft_refs ||
375
cause == GCCause::_z_allocation_stall) {
376
// Boost
377
const uint boosted_nworkers = MAX2(nworkers, ParallelGCThreads);
378
return boosted_nworkers;
379
}
380
381
// Use requested number of worker threads
382
return nworkers;
383
}
384
385
static uint select_active_worker_threads(const ZDriverRequest& request) {
386
if (UseDynamicNumberOfGCThreads) {
387
return select_active_worker_threads_dynamic(request);
388
} else {
389
return select_active_worker_threads_static(request);
390
}
391
}
392
393
class ZDriverGCScope : public StackObj {
394
private:
395
GCIdMark _gc_id;
396
GCCause::Cause _gc_cause;
397
GCCauseSetter _gc_cause_setter;
398
ZStatTimer _timer;
399
ZServiceabilityCycleTracer _tracer;
400
401
public:
402
ZDriverGCScope(const ZDriverRequest& request) :
403
_gc_id(),
404
_gc_cause(request.cause()),
405
_gc_cause_setter(ZCollectedHeap::heap(), _gc_cause),
406
_timer(ZPhaseCycle),
407
_tracer() {
408
// Update statistics
409
ZStatCycle::at_start();
410
411
// Set up soft reference policy
412
const bool clear = should_clear_soft_references(request);
413
ZHeap::heap()->set_soft_reference_policy(clear);
414
415
// Select number of worker threads to use
416
const uint nworkers = select_active_worker_threads(request);
417
ZHeap::heap()->set_active_workers(nworkers);
418
}
419
420
~ZDriverGCScope() {
421
// Update statistics
422
ZStatCycle::at_end(_gc_cause, ZHeap::heap()->active_workers());
423
424
// Update data used by soft reference policy
425
Universe::heap()->update_capacity_and_used_at_gc();
426
427
// Signal that we have completed a visit to all live objects
428
Universe::heap()->record_whole_heap_examined_timestamp();
429
}
430
};
431
432
// Macro to execute a termination check after a concurrent phase. Note
433
// that it's important that the termination check comes after the call
434
// to the function f, since we can't abort between pause_relocate_start()
435
// and concurrent_relocate(). We need to let concurrent_relocate() call
436
// abort_page() on the remaining entries in the relocation set.
437
#define concurrent(f) \
438
do { \
439
concurrent_##f(); \
440
if (should_terminate()) { \
441
return; \
442
} \
443
} while (false)
444
445
void ZDriver::gc(const ZDriverRequest& request) {
446
ZDriverGCScope scope(request);
447
448
// Phase 1: Pause Mark Start
449
pause_mark_start();
450
451
// Phase 2: Concurrent Mark
452
concurrent(mark);
453
454
// Phase 3: Pause Mark End
455
while (!pause_mark_end()) {
456
// Phase 3.5: Concurrent Mark Continue
457
concurrent(mark_continue);
458
}
459
460
// Phase 4: Concurrent Mark Free
461
concurrent(mark_free);
462
463
// Phase 5: Concurrent Process Non-Strong References
464
concurrent(process_non_strong_references);
465
466
// Phase 6: Concurrent Reset Relocation Set
467
concurrent(reset_relocation_set);
468
469
// Phase 7: Pause Verify
470
pause_verify();
471
472
// Phase 8: Concurrent Select Relocation Set
473
concurrent(select_relocation_set);
474
475
// Phase 9: Pause Relocate Start
476
pause_relocate_start();
477
478
// Phase 10: Concurrent Relocate
479
concurrent(relocate);
480
}
481
482
void ZDriver::run_service() {
483
// Main loop
484
while (!should_terminate()) {
485
// Wait for GC request
486
const ZDriverRequest request = _gc_cycle_port.receive();
487
if (request.cause() == GCCause::_no_gc) {
488
continue;
489
}
490
491
ZBreakpoint::at_before_gc();
492
493
// Run GC
494
gc(request);
495
496
// Notify GC completed
497
_gc_cycle_port.ack();
498
499
// Check for out of memory condition
500
check_out_of_memory();
501
502
ZBreakpoint::at_after_gc();
503
}
504
}
505
506
void ZDriver::stop_service() {
507
ZAbort::abort();
508
_gc_cycle_port.send_async(GCCause::_no_gc);
509
}
510
511