Skip to content

Commit 34eb8b3

Browse files
committedJan 21, 2021
8255765: Shenandoah: Isolate concurrent, degenerated and full GC
Reviewed-by: rkennke, shade
1 parent c3c6662 commit 34eb8b3

20 files changed

+1938
-1416
lines changed
 

‎src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
2+
* Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
2525
#include "precompiled.hpp"
2626

2727
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
28+
#include "gc/shenandoah/shenandoahGC.hpp"
2829
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
2930
#include "runtime/os.hpp"
3031

@@ -41,7 +42,7 @@ ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() :
4142
_implicit_full(0),
4243
_cycle_counter(0) {
4344

44-
Copy::zero_to_bytes(_degen_points, sizeof(size_t) * ShenandoahHeap::_DEGENERATED_LIMIT);
45+
Copy::zero_to_bytes(_degen_points, sizeof(size_t) * ShenandoahGC::_DEGENERATED_LIMIT);
4546

4647
_tracer = new (ResourceObj::C_HEAP, mtGC) ShenandoahTracer();
4748

@@ -67,8 +68,8 @@ void ShenandoahCollectorPolicy::record_alloc_failure_to_full() {
6768
_alloc_failure_full++;
6869
}
6970

70-
void ShenandoahCollectorPolicy::record_alloc_failure_to_degenerated(ShenandoahHeap::ShenandoahDegenPoint point) {
71-
assert(point < ShenandoahHeap::_DEGENERATED_LIMIT, "sanity");
71+
void ShenandoahCollectorPolicy::record_alloc_failure_to_degenerated(ShenandoahGC::ShenandoahDegenPoint point) {
72+
assert(point < ShenandoahGC::_DEGENERATED_LIMIT, "sanity");
7273
_alloc_failure_degenerated++;
7374
_degen_points[point]++;
7475
}
@@ -119,9 +120,9 @@ void ShenandoahCollectorPolicy::print_gc_stats(outputStream* out) const {
119120

120121
out->print_cr(SIZE_FORMAT_W(5) " Degenerated GCs", _success_degenerated_gcs);
121122
out->print_cr(" " SIZE_FORMAT_W(5) " caused by allocation failure", _alloc_failure_degenerated);
122-
for (int c = 0; c < ShenandoahHeap::_DEGENERATED_LIMIT; c++) {
123+
for (int c = 0; c < ShenandoahGC::_DEGENERATED_LIMIT; c++) {
123124
if (_degen_points[c] > 0) {
124-
const char* desc = ShenandoahHeap::degen_point_to_string((ShenandoahHeap::ShenandoahDegenPoint)c);
125+
const char* desc = ShenandoahGC::degen_point_to_string((ShenandoahGC::ShenandoahDegenPoint)c);
125126
out->print_cr(" " SIZE_FORMAT_W(5) " happened at %s", _degen_points[c], desc);
126127
}
127128
}

‎src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.hpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
2+
* Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,8 @@
2626
#define SHARE_GC_SHENANDOAH_SHENANDOAHCOLLECTORPOLICY_HPP
2727

2828
#include "gc/shared/gcTrace.hpp"
29-
#include "gc/shenandoah/shenandoahHeap.hpp"
29+
#include "gc/shenandoah/shenandoahGC.hpp"
30+
#include "gc/shenandoah/shenandoahSharedVariables.hpp"
3031
#include "memory/allocation.hpp"
3132
#include "utilities/ostream.hpp"
3233

@@ -47,7 +48,7 @@ class ShenandoahCollectorPolicy : public CHeapObj<mtGC> {
4748
size_t _explicit_full;
4849
size_t _implicit_concurrent;
4950
size_t _implicit_full;
50-
size_t _degen_points[ShenandoahHeap::_DEGENERATED_LIMIT];
51+
size_t _degen_points[ShenandoahGC::_DEGENERATED_LIMIT];
5152

5253
ShenandoahSharedFlag _in_shutdown;
5354

@@ -65,7 +66,7 @@ class ShenandoahCollectorPolicy : public CHeapObj<mtGC> {
6566
void record_success_concurrent();
6667
void record_success_degenerated();
6768
void record_success_full();
68-
void record_alloc_failure_to_degenerated(ShenandoahHeap::ShenandoahDegenPoint point);
69+
void record_alloc_failure_to_degenerated(ShenandoahGC::ShenandoahDegenPoint point);
6970
void record_alloc_failure_to_full();
7071
void record_degenerated_upgrade_to_full();
7172
void record_explicit_to_concurrent();

‎src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp

+954
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright (c) 2021, Red Hat, Inc. 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+
25+
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTGC_HPP
26+
#define SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTGC_HPP
27+
28+
#include "gc/shared/gcCause.hpp"
29+
#include "gc/shenandoah/shenandoahConcurrentMark.hpp"
30+
#include "gc/shenandoah/shenandoahGC.hpp"
31+
#include "gc/shenandoah/shenandoahHeap.hpp"
32+
33+
class VM_ShenandoahInitMark;
34+
class VM_ShenandoahFinalMarkStartEvac;
35+
class VM_ShenandoahInitUpdateRefs;
36+
class VM_ShenandoahFinalUpdateRefs;
37+
38+
class ShenandoahConcurrentGC : public ShenandoahGC {
39+
friend class VM_ShenandoahInitMark;
40+
friend class VM_ShenandoahFinalMarkStartEvac;
41+
friend class VM_ShenandoahInitUpdateRefs;
42+
friend class VM_ShenandoahFinalUpdateRefs;
43+
44+
private:
45+
ShenandoahConcurrentMark _mark;
46+
ShenandoahDegenPoint _degen_point;
47+
48+
public:
49+
ShenandoahConcurrentGC();
50+
bool collect(GCCause::Cause cause);
51+
ShenandoahDegenPoint degen_point() const;
52+
53+
// Cancel ongoing concurrent GC
54+
static void cancel();
55+
private:
56+
// Entry points to STW GC operations, these cause a related safepoint, that then
57+
// call the entry method below
58+
void vmop_entry_init_mark();
59+
void vmop_entry_final_mark();
60+
void vmop_entry_init_updaterefs();
61+
void vmop_entry_final_updaterefs();
62+
63+
// Entry methods to normally STW GC operations. These set up logging, monitoring
64+
// and workers for net VM operation
65+
void entry_init_mark();
66+
void entry_final_mark();
67+
void entry_init_updaterefs();
68+
void entry_final_updaterefs();
69+
70+
// Entry methods to normally concurrent GC operations. These set up logging, monitoring
71+
// for concurrent operation.
72+
void entry_reset();
73+
void entry_mark_roots();
74+
void entry_mark();
75+
void entry_weak_refs();
76+
void entry_weak_roots();
77+
void entry_class_unloading();
78+
void entry_strong_roots();
79+
void entry_cleanup_early();
80+
void entry_rendezvous_roots();
81+
void entry_evacuate();
82+
void entry_update_thread_roots();
83+
void entry_updaterefs();
84+
void entry_cleanup_complete();
85+
86+
// Actual work for the phases
87+
void op_reset();
88+
void op_init_mark();
89+
void op_mark_roots();
90+
void op_mark();
91+
void op_final_mark();
92+
void op_weak_refs();
93+
void op_weak_roots();
94+
void op_class_unloading();
95+
void op_strong_roots();
96+
void op_cleanup_early();
97+
void op_rendezvous_roots();
98+
void op_evacuate();
99+
void op_init_updaterefs();
100+
void op_updaterefs();
101+
void op_update_thread_roots();
102+
void op_final_updaterefs();
103+
void op_cleanup_complete();
104+
105+
// Messages for GC trace events, they have to be immortal for
106+
// passing around the logging/tracing systems
107+
const char* init_mark_event_message() const;
108+
const char* final_mark_event_message() const;
109+
const char* conc_mark_event_message() const;
110+
111+
// Check GC cancellation and abort concurrent GC
112+
bool check_cancellation_and_abort(ShenandoahDegenPoint point);
113+
};
114+
115+
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTGC_HPP

‎src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp

+5-67
Original file line numberDiff line numberDiff line change
@@ -223,72 +223,6 @@ void ShenandoahConcurrentMark::mark_stw_roots() {
223223
workers->run_task(&mark_roots);
224224
}
225225

226-
void ShenandoahConcurrentMark::update_roots(ShenandoahPhaseTimings::Phase root_phase) {
227-
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
228-
assert(root_phase == ShenandoahPhaseTimings::full_gc_update_roots ||
229-
root_phase == ShenandoahPhaseTimings::degen_gc_update_roots,
230-
"Only for these phases");
231-
232-
ShenandoahGCPhase phase(root_phase);
233-
234-
bool check_alive = root_phase == ShenandoahPhaseTimings::degen_gc_update_roots;
235-
236-
#if COMPILER2_OR_JVMCI
237-
DerivedPointerTable::clear();
238-
#endif
239-
240-
ShenandoahHeap* const heap = ShenandoahHeap::heap();
241-
WorkGang* workers = heap->workers();
242-
uint nworkers = workers->active_workers();
243-
244-
ShenandoahRootUpdater root_updater(nworkers, root_phase);
245-
ShenandoahUpdateRootsTask update_roots(&root_updater, check_alive);
246-
workers->run_task(&update_roots);
247-
248-
#if COMPILER2_OR_JVMCI
249-
DerivedPointerTable::update_pointers();
250-
#endif
251-
}
252-
253-
class ShenandoahUpdateThreadRootsTask : public AbstractGangTask {
254-
private:
255-
ShenandoahThreadRoots _thread_roots;
256-
ShenandoahPhaseTimings::Phase _phase;
257-
ShenandoahGCWorkerPhase _worker_phase;
258-
public:
259-
ShenandoahUpdateThreadRootsTask(bool is_par, ShenandoahPhaseTimings::Phase phase) :
260-
AbstractGangTask("Shenandoah Update Thread Roots"),
261-
_thread_roots(phase, is_par),
262-
_phase(phase),
263-
_worker_phase(phase) {}
264-
265-
void work(uint worker_id) {
266-
ShenandoahParallelWorkerSession worker_session(worker_id);
267-
ShenandoahUpdateRefsClosure cl;
268-
_thread_roots.oops_do(&cl, NULL, worker_id);
269-
}
270-
};
271-
272-
void ShenandoahConcurrentMark::update_thread_roots(ShenandoahPhaseTimings::Phase root_phase) {
273-
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
274-
275-
ShenandoahGCPhase phase(root_phase);
276-
277-
#if COMPILER2_OR_JVMCI
278-
DerivedPointerTable::clear();
279-
#endif
280-
ShenandoahHeap* const heap = ShenandoahHeap::heap();
281-
WorkGang* workers = heap->workers();
282-
bool is_par = workers->active_workers() > 1;
283-
284-
ShenandoahUpdateThreadRootsTask task(is_par, root_phase);
285-
workers->run_task(&task);
286-
287-
#if COMPILER2_OR_JVMCI
288-
DerivedPointerTable::update_pointers();
289-
#endif
290-
}
291-
292226
// Mark concurrent roots during concurrent phases
293227
class ShenandoahMarkConcurrentRootsTask : public AbstractGangTask {
294228
private:
@@ -357,6 +291,10 @@ void ShenandoahConcurrentMark::finish_mark() {
357291
assert(task_queues()->is_empty(), "Should be empty");
358292
TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
359293
TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
294+
295+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
296+
heap->set_concurrent_mark_in_progress(false);
297+
heap->mark_complete_marking_context();
360298
}
361299

362300
void ShenandoahConcurrentMark::finish_mark_work() {
@@ -368,7 +306,7 @@ void ShenandoahConcurrentMark::finish_mark_work() {
368306
// root scan, and completes the closure, thus marking through all live objects
369307
// The implementation is the same, so it's shared here.
370308
ShenandoahHeap* const heap = ShenandoahHeap::heap();
371-
ShenandoahGCPhase phase(ShenandoahPhaseTimings::finish_queues);
309+
ShenandoahGCPhase phase(ShenandoahPhaseTimings::finish_mark);
372310
uint nworkers = heap->workers()->active_workers();
373311
task_queues()->reserve(nworkers);
374312

‎src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.hpp

-4
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ class ShenandoahConcurrentMark: public ShenandoahMark {
5353

5454
static void cancel();
5555

56-
// TODO: where to put them
57-
static void update_roots(ShenandoahPhaseTimings::Phase root_phase);
58-
static void update_thread_roots(ShenandoahPhaseTimings::Phase root_phase);
59-
6056
private:
6157
void finish_mark_work();
6258
};

‎src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp

+25-90
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@
2424

2525
#include "precompiled.hpp"
2626

27-
#include "gc/shenandoah/shenandoahConcurrentMark.hpp"
2827
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
28+
#include "gc/shenandoah/shenandoahConcurrentGC.hpp"
2929
#include "gc/shenandoah/shenandoahControlThread.hpp"
30+
#include "gc/shenandoah/shenandoahDegeneratedGC.hpp"
3031
#include "gc/shenandoah/shenandoahFreeSet.hpp"
3132
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
3233
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
3334
#include "gc/shenandoah/shenandoahMark.inline.hpp"
35+
#include "gc/shenandoah/shenandoahMarkCompact.hpp"
3436
#include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
3537
#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
3638
#include "gc/shenandoah/shenandoahUtils.hpp"
@@ -47,7 +49,7 @@ ShenandoahControlThread::ShenandoahControlThread() :
4749
_gc_waiters_lock(Mutex::leaf, "ShenandoahRequestedGC_lock", true, Monitor::_safepoint_check_always),
4850
_periodic_task(this),
4951
_requested_gc_cause(GCCause::_no_cause_specified),
50-
_degen_point(ShenandoahHeap::_degenerated_outside_cycle),
52+
_degen_point(ShenandoahGC::_degenerated_outside_cycle),
5153
_allocs_seen(0) {
5254

5355
reset_gc_id();
@@ -110,7 +112,7 @@ void ShenandoahControlThread::run_service() {
110112
// Choose which GC mode to run in. The block below should select a single mode.
111113
GCMode mode = none;
112114
GCCause::Cause cause = GCCause::_last_gc_cause;
113-
ShenandoahHeap::ShenandoahDegenPoint degen_point = ShenandoahHeap::_degenerated_unset;
115+
ShenandoahGC::ShenandoahDegenPoint degen_point = ShenandoahGC::_degenerated_unset;
114116

115117
if (alloc_failure_pending) {
116118
// Allocation failure takes precedence: we have to deal with it first thing
@@ -120,7 +122,7 @@ void ShenandoahControlThread::run_service() {
120122

121123
// Consume the degen point, and seed it with default value
122124
degen_point = _degen_point;
123-
_degen_point = ShenandoahHeap::_degenerated_outside_cycle;
125+
_degen_point = ShenandoahGC::_degenerated_outside_cycle;
124126

125127
if (ShenandoahDegeneratedGC && heuristics->should_degenerate_cycle()) {
126128
heuristics->record_allocation_failure_gc();
@@ -384,100 +386,31 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau
384386
// Full GC --------------------------/
385387
//
386388
ShenandoahHeap* heap = ShenandoahHeap::heap();
387-
388-
if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_outside_cycle)) return;
389+
if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) return;
389390

390391
GCIdMark gc_id_mark;
391392
ShenandoahGCSession session(cause);
392393

393394
TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
394395

395-
// Reset for upcoming marking
396-
heap->entry_reset();
397-
398-
// Start initial mark under STW
399-
heap->vmop_entry_init_mark();
400-
401-
// Concurrent mark roots
402-
heap->entry_mark_roots();
403-
if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_outside_cycle)) return;
404-
405-
// Continue concurrent mark
406-
heap->entry_mark();
407-
if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_mark)) return;
408-
409-
// Complete marking under STW, and start evacuation
410-
heap->vmop_entry_final_mark();
411-
412-
// Process weak roots that might still point to regions that would be broken by cleanup
413-
if (heap->is_concurrent_weak_root_in_progress()) {
414-
heap->entry_weak_refs();
415-
heap->entry_weak_roots();
416-
}
417-
418-
// Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim
419-
// the space. This would be the last action if there is nothing to evacuate.
420-
heap->entry_cleanup_early();
421-
422-
{
423-
ShenandoahHeapLocker locker(heap->lock());
424-
heap->free_set()->log_status();
425-
}
426-
427-
// Perform concurrent class unloading
428-
if (heap->is_concurrent_weak_root_in_progress() &&
429-
ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
430-
heap->entry_class_unloading();
431-
}
432-
433-
// Processing strong roots
434-
// This may be skipped if there is nothing to update/evacuate.
435-
// If so, strong_root_in_progress would be unset.
436-
if (heap->is_concurrent_strong_root_in_progress()) {
437-
heap->entry_strong_roots();
438-
}
439-
440-
// Continue the cycle with evacuation and optional update-refs.
441-
// This may be skipped if there is nothing to evacuate.
442-
// If so, evac_in_progress would be unset by collection set preparation code.
443-
if (heap->is_evacuation_in_progress()) {
444-
// Concurrently evacuate
445-
heap->entry_evac();
446-
if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_evac)) return;
447-
448-
// Perform update-refs phase.
449-
heap->vmop_entry_init_updaterefs();
450-
heap->entry_updaterefs();
451-
if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_updaterefs)) return;
452-
453-
// Concurrent update thread roots
454-
heap->entry_update_thread_roots();
455-
if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_updaterefs)) return;
456-
457-
heap->vmop_entry_final_updaterefs();
458-
459-
// Update references freed up collection set, kick the cleanup to reclaim the space.
460-
heap->entry_cleanup_complete();
396+
ShenandoahConcurrentGC gc;
397+
if (gc.collect(cause)) {
398+
// Cycle is complete
399+
heap->heuristics()->record_success_concurrent();
400+
heap->shenandoah_policy()->record_success_concurrent();
461401
} else {
462-
// Concurrent weak/strong root flags are unset concurrently. We depend on updateref GC safepoints
463-
// to ensure the changes are visible to all mutators before gc cycle is completed.
464-
// In case of no evacuation, updateref GC safepoints are skipped. Therefore, we will need
465-
// to perform thread handshake to ensure their consistences.
466-
heap->entry_rendezvous_roots();
402+
assert(heap->cancelled_gc(), "Must have been cancelled");
403+
check_cancellation_or_degen(gc.degen_point());
467404
}
468-
469-
// Cycle is complete
470-
heap->heuristics()->record_success_concurrent();
471-
heap->shenandoah_policy()->record_success_concurrent();
472405
}
473406

474-
bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahHeap::ShenandoahDegenPoint point) {
407+
bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) {
475408
ShenandoahHeap* heap = ShenandoahHeap::heap();
476409
if (heap->cancelled_gc()) {
477410
assert (is_alloc_failure_gc() || in_graceful_shutdown(), "Cancel GC either for alloc failure GC, or gracefully exiting");
478411
if (!in_graceful_shutdown()) {
479-
assert (_degen_point == ShenandoahHeap::_degenerated_outside_cycle,
480-
"Should not be set yet: %s", ShenandoahHeap::degen_point_to_string(_degen_point));
412+
assert (_degen_point == ShenandoahGC::_degenerated_outside_cycle,
413+
"Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point));
481414
_degen_point = point;
482415
}
483416
return true;
@@ -493,22 +426,24 @@ void ShenandoahControlThread::service_stw_full_cycle(GCCause::Cause cause) {
493426
GCIdMark gc_id_mark;
494427
ShenandoahGCSession session(cause);
495428

496-
ShenandoahHeap* heap = ShenandoahHeap::heap();
497-
heap->vmop_entry_full(cause);
429+
ShenandoahMarkCompact gc;
430+
gc.collect(cause);
498431

432+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
499433
heap->heuristics()->record_success_full();
500434
heap->shenandoah_policy()->record_success_full();
501435
}
502436

503-
void ShenandoahControlThread::service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahHeap::ShenandoahDegenPoint point) {
504-
assert (point != ShenandoahHeap::_degenerated_unset, "Degenerated point should be set");
437+
void ShenandoahControlThread::service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahGC::ShenandoahDegenPoint point) {
438+
assert (point != ShenandoahGC::_degenerated_unset, "Degenerated point should be set");
505439

506440
GCIdMark gc_id_mark;
507441
ShenandoahGCSession session(cause);
508442

509-
ShenandoahHeap* heap = ShenandoahHeap::heap();
510-
heap->vmop_degenerated(point);
443+
ShenandoahDegenGC gc(point);
444+
gc.collect(cause);
511445

446+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
512447
heap->heuristics()->record_success_degenerated();
513448
heap->shenandoah_policy()->record_success_degenerated();
514449
}

‎src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
2+
* Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
2727

2828
#include "gc/shared/gcCause.hpp"
2929
#include "gc/shared/concurrentGCThread.hpp"
30+
#include "gc/shenandoah/shenandoahGC.hpp"
3031
#include "gc/shenandoah/shenandoahHeap.hpp"
3132
#include "gc/shenandoah/shenandoahPadding.hpp"
3233
#include "gc/shenandoah/shenandoahSharedVariables.hpp"
@@ -91,18 +92,18 @@ class ShenandoahControlThread: public ConcurrentGCThread {
9192
ShenandoahSharedFlag _do_counters_update;
9293
ShenandoahSharedFlag _force_counters_update;
9394
GCCause::Cause _requested_gc_cause;
94-
ShenandoahHeap::ShenandoahDegenPoint _degen_point;
95+
ShenandoahGC::ShenandoahDegenPoint _degen_point;
9596

9697
shenandoah_padding(0);
9798
volatile size_t _allocs_seen;
9899
shenandoah_padding(1);
99100
volatile size_t _gc_id;
100101
shenandoah_padding(2);
101102

102-
bool check_cancellation_or_degen(ShenandoahHeap::ShenandoahDegenPoint point);
103+
bool check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point);
103104
void service_concurrent_normal_cycle(GCCause::Cause cause);
104105
void service_stw_full_cycle(GCCause::Cause cause);
105-
void service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahHeap::ShenandoahDegenPoint point);
106+
void service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahGC::ShenandoahDegenPoint point);
106107
void service_uncommit(double shrink_before, size_t shrink_until);
107108

108109
bool try_set_alloc_failure_gc();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
/*
2+
* Copyright (c) 2021, Red Hat, Inc. 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+
25+
#include "precompiled.hpp"
26+
27+
#include "gc/shared/collectorCounters.hpp"
28+
#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
29+
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
30+
#include "gc/shenandoah/shenandoahConcurrentMark.hpp"
31+
#include "gc/shenandoah/shenandoahDegeneratedGC.hpp"
32+
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
33+
#include "gc/shenandoah/shenandoahMarkCompact.hpp"
34+
#include "gc/shenandoah/shenandoahMetrics.hpp"
35+
#include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
36+
#include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
37+
#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
38+
#include "gc/shenandoah/shenandoahSTWMark.hpp"
39+
#include "gc/shenandoah/shenandoahUtils.hpp"
40+
#include "gc/shenandoah/shenandoahVerifier.hpp"
41+
#include "gc/shenandoah/shenandoahWorkerPolicy.hpp"
42+
#include "gc/shenandoah/shenandoahVMOperations.hpp"
43+
#include "runtime/vmThread.hpp"
44+
#include "utilities/events.hpp"
45+
46+
ShenandoahDegenGC::ShenandoahDegenGC(ShenandoahDegenPoint degen_point) :
47+
ShenandoahGC(),
48+
_degen_point(degen_point) {
49+
}
50+
51+
bool ShenandoahDegenGC::collect(GCCause::Cause cause) {
52+
vmop_degenerated();
53+
return true;
54+
}
55+
56+
void ShenandoahDegenGC::vmop_degenerated() {
57+
TraceCollectorStats tcs(ShenandoahHeap::heap()->monitoring_support()->full_stw_collection_counters());
58+
ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::degen_gc_gross);
59+
VM_ShenandoahDegeneratedGC degenerated_gc(this);
60+
VMThread::execute(&degenerated_gc);
61+
}
62+
63+
void ShenandoahDegenGC::entry_degenerated() {
64+
const char* msg = degen_event_message(_degen_point);
65+
ShenandoahPausePhase gc_phase(msg, ShenandoahPhaseTimings::degen_gc, true /* log_heap_usage */);
66+
EventMark em("%s", msg);
67+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
68+
69+
ShenandoahWorkerScope scope(heap->workers(),
70+
ShenandoahWorkerPolicy::calc_workers_for_stw_degenerated(),
71+
"stw degenerated gc");
72+
73+
heap->set_degenerated_gc_in_progress(true);
74+
op_degenerated();
75+
heap->set_degenerated_gc_in_progress(false);
76+
}
77+
78+
void ShenandoahDegenGC::op_degenerated() {
79+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
80+
// Degenerated GC is STW, but it can also fail. Current mechanics communicates
81+
// GC failure via cancelled_concgc() flag. So, if we detect the failure after
82+
// some phase, we have to upgrade the Degenerate GC to Full GC.
83+
heap->clear_cancelled_gc();
84+
85+
ShenandoahMetricsSnapshot metrics;
86+
metrics.snap_before();
87+
88+
switch (_degen_point) {
89+
// The cases below form the Duff's-like device: it describes the actual GC cycle,
90+
// but enters it at different points, depending on which concurrent phase had
91+
// degenerated.
92+
93+
case _degenerated_outside_cycle:
94+
// We have degenerated from outside the cycle, which means something is bad with
95+
// the heap, most probably heavy humongous fragmentation, or we are very low on free
96+
// space. It makes little sense to wait for Full GC to reclaim as much as it can, when
97+
// we can do the most aggressive degen cycle, which includes processing references and
98+
// class unloading, unless those features are explicitly disabled.
99+
//
100+
101+
// Degenerated from concurrent root mark, reset the flag for STW mark
102+
if (heap->is_concurrent_mark_in_progress()) {
103+
ShenandoahConcurrentMark::cancel();
104+
heap->set_concurrent_mark_in_progress(false);
105+
}
106+
107+
// Note that we can only do this for "outside-cycle" degens, otherwise we would risk
108+
// changing the cycle parameters mid-cycle during concurrent -> degenerated handover.
109+
heap->set_unload_classes(heap->heuristics()->can_unload_classes());
110+
111+
op_reset();
112+
113+
// STW mark
114+
op_mark();
115+
116+
case _degenerated_mark:
117+
// No fallthrough. Continue mark, handed over from concurrent mark
118+
if (_degen_point == ShenandoahDegenPoint::_degenerated_mark) {
119+
op_finish_mark();
120+
}
121+
assert(!heap->cancelled_gc(), "STW mark can not OOM");
122+
123+
/* Degen select Collection Set. etc. */
124+
op_prepare_evacuation();
125+
126+
op_cleanup_early();
127+
128+
case _degenerated_evac:
129+
// If heuristics thinks we should do the cycle, this flag would be set,
130+
// and we can do evacuation. Otherwise, it would be the shortcut cycle.
131+
if (heap->is_evacuation_in_progress()) {
132+
133+
// Degeneration under oom-evac protocol might have left some objects in
134+
// collection set un-evacuated. Restart evacuation from the beginning to
135+
// capture all objects. For all the objects that are already evacuated,
136+
// it would be a simple check, which is supposed to be fast. This is also
137+
// safe to do even without degeneration, as CSet iterator is at beginning
138+
// in preparation for evacuation anyway.
139+
//
140+
// Before doing that, we need to make sure we never had any cset-pinned
141+
// regions. This may happen if allocation failure happened when evacuating
142+
// the about-to-be-pinned object, oom-evac protocol left the object in
143+
// the collection set, and then the pin reached the cset region. If we continue
144+
// the cycle here, we would trash the cset and alive objects in it. To avoid
145+
// it, we fail degeneration right away and slide into Full GC to recover.
146+
147+
{
148+
heap->sync_pinned_region_status();
149+
heap->collection_set()->clear_current_index();
150+
151+
ShenandoahHeapRegion* r;
152+
while ((r = heap->collection_set()->next()) != NULL) {
153+
if (r->is_pinned()) {
154+
heap->cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc);
155+
op_degenerated_fail();
156+
return;
157+
}
158+
}
159+
160+
heap->collection_set()->clear_current_index();
161+
}
162+
op_evacuate();
163+
if (heap->cancelled_gc()) {
164+
op_degenerated_fail();
165+
return;
166+
}
167+
}
168+
169+
// If heuristics thinks we should do the cycle, this flag would be set,
170+
// and we need to do update-refs. Otherwise, it would be the shortcut cycle.
171+
if (heap->has_forwarded_objects()) {
172+
op_init_updaterefs();
173+
assert(!heap->cancelled_gc(), "STW reference update can not OOM");
174+
}
175+
176+
case _degenerated_updaterefs:
177+
if (heap->has_forwarded_objects()) {
178+
op_updaterefs();
179+
op_update_roots();
180+
assert(!heap->cancelled_gc(), "STW reference update can not OOM");
181+
}
182+
183+
if (ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
184+
// Disarm nmethods that armed in concurrent cycle.
185+
// In above case, update roots should disarm them
186+
ShenandoahCodeRoots::disarm_nmethods();
187+
}
188+
189+
op_cleanup_complete();
190+
break;
191+
default:
192+
ShouldNotReachHere();
193+
}
194+
195+
if (ShenandoahVerify) {
196+
heap->verifier()->verify_after_degenerated();
197+
}
198+
199+
if (VerifyAfterGC) {
200+
Universe::verify();
201+
}
202+
203+
metrics.snap_after();
204+
205+
// Check for futility and fail. There is no reason to do several back-to-back Degenerated cycles,
206+
// because that probably means the heap is overloaded and/or fragmented.
207+
if (!metrics.is_good_progress()) {
208+
heap->notify_gc_no_progress();
209+
heap->cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc);
210+
op_degenerated_futile();
211+
} else {
212+
heap->notify_gc_progress();
213+
}
214+
}
215+
216+
void ShenandoahDegenGC::op_reset() {
217+
ShenandoahHeap::heap()->prepare_gc();
218+
}
219+
220+
void ShenandoahDegenGC::op_mark() {
221+
assert(!ShenandoahHeap::heap()->is_concurrent_mark_in_progress(), "Should be reset");
222+
ShenandoahGCPhase phase(ShenandoahPhaseTimings::degen_gc_stw_mark);
223+
ShenandoahSTWMark mark(false /*full gc*/);
224+
mark.clear();
225+
mark.mark();
226+
}
227+
228+
void ShenandoahDegenGC::op_finish_mark() {
229+
ShenandoahConcurrentMark mark;
230+
mark.finish_mark();
231+
}
232+
233+
void ShenandoahDegenGC::op_prepare_evacuation() {
234+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
235+
if (ShenandoahVerify) {
236+
heap->verifier()->verify_roots_no_forwarded();
237+
}
238+
239+
// STW cleanup weak roots and unload classes
240+
heap->parallel_cleaning(false /*full gc*/);
241+
// Prepare regions and collection set
242+
heap->prepare_regions_and_collection_set(false /*concurrent*/);
243+
244+
if (!heap->collection_set()->is_empty()) {
245+
heap->set_evacuation_in_progress(true);
246+
heap->set_has_forwarded_objects(true);
247+
248+
if(ShenandoahVerify) {
249+
heap->verifier()->verify_during_evacuation();
250+
}
251+
} else {
252+
if (ShenandoahVerify) {
253+
heap->verifier()->verify_after_concmark();
254+
}
255+
256+
if (VerifyAfterGC) {
257+
Universe::verify();
258+
}
259+
}
260+
}
261+
262+
void ShenandoahDegenGC::op_cleanup_early() {
263+
ShenandoahHeap::heap()->recycle_trash();
264+
}
265+
266+
void ShenandoahDegenGC::op_evacuate() {
267+
ShenandoahGCPhase phase(ShenandoahPhaseTimings::degen_gc_stw_evac);
268+
ShenandoahHeap::heap()->evacuate_collection_set(false /* concurrent*/);
269+
}
270+
271+
void ShenandoahDegenGC::op_init_updaterefs() {
272+
// Evacuation has completed
273+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
274+
heap->set_evacuation_in_progress(false);
275+
heap->set_concurrent_weak_root_in_progress(false);
276+
heap->set_concurrent_strong_root_in_progress(false);
277+
278+
heap->prepare_update_heap_references(false /*concurrent*/);
279+
heap->set_update_refs_in_progress(true);
280+
}
281+
282+
void ShenandoahDegenGC::op_updaterefs() {
283+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
284+
ShenandoahGCPhase phase(ShenandoahPhaseTimings::degen_gc_updaterefs);
285+
// Handed over from concurrent update references phase
286+
heap->update_heap_references(false /*concurrent*/);
287+
288+
heap->set_update_refs_in_progress(false);
289+
heap->set_has_forwarded_objects(false);
290+
}
291+
292+
void ShenandoahDegenGC::op_update_roots() {
293+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
294+
295+
update_roots(false /*full_gc*/);
296+
297+
heap->update_heap_region_states(false /*concurrent*/);
298+
299+
if (ShenandoahVerify) {
300+
heap->verifier()->verify_after_updaterefs();
301+
}
302+
303+
if (VerifyAfterGC) {
304+
Universe::verify();
305+
}
306+
307+
heap->rebuild_free_set(false /*concurrent*/);
308+
}
309+
310+
void ShenandoahDegenGC::op_cleanup_complete() {
311+
ShenandoahGCPhase phase(ShenandoahPhaseTimings::degen_gc_cleanup_complete);
312+
ShenandoahHeap::heap()->recycle_trash();
313+
}
314+
315+
void ShenandoahDegenGC::op_degenerated_fail() {
316+
log_info(gc)("Cannot finish degeneration, upgrading to Full GC");
317+
ShenandoahHeap::heap()->shenandoah_policy()->record_degenerated_upgrade_to_full();
318+
319+
ShenandoahMarkCompact full_gc;
320+
full_gc.op_full(GCCause::_shenandoah_upgrade_to_full_gc);
321+
}
322+
323+
void ShenandoahDegenGC::op_degenerated_futile() {
324+
ShenandoahHeap::heap()->shenandoah_policy()->record_degenerated_upgrade_to_full();
325+
ShenandoahMarkCompact full_gc;
326+
full_gc.op_full(GCCause::_shenandoah_upgrade_to_full_gc);
327+
}
328+
329+
const char* ShenandoahDegenGC::degen_event_message(ShenandoahDegenPoint point) const {
330+
switch (point) {
331+
case _degenerated_unset:
332+
return "Pause Degenerated GC (<UNSET>)";
333+
case _degenerated_outside_cycle:
334+
return "Pause Degenerated GC (Outside of Cycle)";
335+
case _degenerated_mark:
336+
return "Pause Degenerated GC (Mark)";
337+
case _degenerated_evac:
338+
return "Pause Degenerated GC (Evacuation)";
339+
case _degenerated_updaterefs:
340+
return "Pause Degenerated GC (Update Refs)";
341+
default:
342+
ShouldNotReachHere();
343+
return "ERROR";
344+
}
345+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2021, Red Hat, Inc. 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+
25+
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHDEGENERATEDGC_HPP
26+
#define SHARE_GC_SHENANDOAH_SHENANDOAHDEGENERATEDGC_HPP
27+
28+
#include "gc/shenandoah/shenandoahGC.hpp"
29+
30+
class VM_ShenandoahDegeneratedGC;
31+
32+
class ShenandoahDegenGC : public ShenandoahGC {
33+
friend class VM_ShenandoahDegeneratedGC;
34+
private:
35+
const ShenandoahDegenPoint _degen_point;
36+
37+
public:
38+
ShenandoahDegenGC(ShenandoahDegenPoint degen_point);
39+
bool collect(GCCause::Cause cause);
40+
41+
private:
42+
void vmop_degenerated();
43+
void entry_degenerated();
44+
void op_degenerated();
45+
46+
void op_reset();
47+
void op_mark();
48+
void op_finish_mark();
49+
void op_prepare_evacuation();
50+
void op_cleanup_early();
51+
void op_evacuate();
52+
void op_init_updaterefs();
53+
void op_updaterefs();
54+
void op_update_roots();
55+
void op_cleanup_complete();
56+
57+
// Fail handling
58+
void op_degenerated_futile();
59+
void op_degenerated_fail();
60+
61+
const char* degen_event_message(ShenandoahDegenPoint point) const;
62+
};
63+
64+
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHDEGENERATEDGC_HPP
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (c) 2021, Red Hat, Inc. 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+
25+
#include "precompiled.hpp"
26+
27+
#include "gc/shared/workgroup.hpp"
28+
#include "gc/shenandoah/shenandoahClosures.inline.hpp"
29+
#include "gc/shenandoah/shenandoahGC.hpp"
30+
#include "gc/shenandoah/shenandoahHeap.hpp"
31+
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
32+
#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
33+
#include "gc/shenandoah/shenandoahUtils.hpp"
34+
35+
const char* ShenandoahGC::degen_point_to_string(ShenandoahDegenPoint point) {
36+
switch(point) {
37+
case _degenerated_unset:
38+
return "<UNSET>";
39+
case _degenerated_outside_cycle:
40+
return "Outside of Cycle";
41+
case _degenerated_mark:
42+
return "Mark";
43+
case _degenerated_evac:
44+
return "Evacuation";
45+
case _degenerated_updaterefs:
46+
return "Update References";
47+
default:
48+
ShouldNotReachHere();
49+
return "ERROR";
50+
}
51+
}
52+
53+
class ShenandoahUpdateRootsTask : public AbstractGangTask {
54+
private:
55+
ShenandoahRootUpdater* _root_updater;
56+
bool _check_alive;
57+
public:
58+
ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater, bool check_alive) :
59+
AbstractGangTask("Shenandoah Update Roots"),
60+
_root_updater(root_updater),
61+
_check_alive(check_alive){
62+
}
63+
64+
void work(uint worker_id) {
65+
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
66+
ShenandoahParallelWorkerSession worker_session(worker_id);
67+
68+
ShenandoahHeap* heap = ShenandoahHeap::heap();
69+
ShenandoahUpdateRefsClosure cl;
70+
if (_check_alive) {
71+
ShenandoahForwardedIsAliveClosure is_alive;
72+
_root_updater->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahUpdateRefsClosure>(worker_id, &is_alive, &cl);
73+
} else {
74+
AlwaysTrueClosure always_true;;
75+
_root_updater->roots_do<AlwaysTrueClosure, ShenandoahUpdateRefsClosure>(worker_id, &always_true, &cl);
76+
}
77+
}
78+
};
79+
80+
void ShenandoahGC::update_roots(bool full_gc) {
81+
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
82+
assert(ShenandoahHeap::heap()->is_full_gc_in_progress() ||
83+
ShenandoahHeap::heap()->is_degenerated_gc_in_progress(),
84+
"Only for degenerated GC and full GC");
85+
86+
bool check_alive = !full_gc;
87+
ShenandoahPhaseTimings::Phase p = full_gc ?
88+
ShenandoahPhaseTimings::full_gc_update_roots :
89+
ShenandoahPhaseTimings::degen_gc_update_roots;
90+
91+
ShenandoahGCPhase phase(p);
92+
#if COMPILER2_OR_JVMCI
93+
DerivedPointerTable::clear();
94+
#endif
95+
96+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
97+
WorkGang* workers = heap->workers();
98+
uint nworkers = workers->active_workers();
99+
100+
ShenandoahRootUpdater root_updater(nworkers, p);
101+
ShenandoahUpdateRootsTask update_roots(&root_updater, check_alive);
102+
workers->run_task(&update_roots);
103+
104+
#if COMPILER2_OR_JVMCI
105+
DerivedPointerTable::update_pointers();
106+
#endif
107+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2021, Red Hat, Inc. 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+
25+
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHGC_HPP
26+
#define SHARE_GC_SHENANDOAH_SHENANDOAHGC_HPP
27+
28+
#include "memory/allocation.hpp"
29+
#include "gc/shared/gcCause.hpp"
30+
31+
/*
32+
* Base class of three Shenandoah GC modes
33+
*
34+
* The relationship of the GCs:
35+
*
36+
* ("normal" mode) ----> Concurrent GC ----> (finish)
37+
* |
38+
* | <upgrade>
39+
* v
40+
* ("passive" mode) ---> Degenerated GC ---> (finish)
41+
* |
42+
* | <upgrade>
43+
* v
44+
* Full GC --------> (finish)
45+
*/
46+
47+
class ShenandoahGC : public StackObj {
48+
public:
49+
// Fail point from concurrent GC
50+
enum ShenandoahDegenPoint {
51+
_degenerated_unset,
52+
_degenerated_outside_cycle,
53+
_degenerated_mark,
54+
_degenerated_evac,
55+
_degenerated_updaterefs,
56+
_DEGENERATED_LIMIT
57+
};
58+
59+
virtual bool collect(GCCause::Cause cause) = 0;
60+
static const char* degen_point_to_string(ShenandoahDegenPoint point);
61+
62+
protected:
63+
static void update_roots(bool full_gc);
64+
};
65+
66+
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHGC_HPP

‎src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp

+75-1,091
Large diffs are not rendered by default.

‎src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp

+31-109
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class ShenandoahHeapRegion;
5555
class ShenandoahHeapRegionClosure;
5656
class ShenandoahCollectionSet;
5757
class ShenandoahFreeSet;
58+
class ShenandoahConcurrentMark;
59+
class ShenandoahMarkCompact;
5860
class ShenandoahMonitoringSupport;
5961
class ShenandoahPacer;
6062
class ShenandoahReferenceProcessor;
@@ -120,6 +122,11 @@ class ShenandoahHeap : public CollectedHeap {
120122
friend class ShenandoahGCStateResetter;
121123
friend class ShenandoahParallelObjectIterator;
122124
friend class ShenandoahSafepoint;
125+
// Supported GC
126+
friend class ShenandoahConcurrentGC;
127+
friend class ShenandoahDegenGC;
128+
friend class ShenandoahMarkCompact;
129+
123130
// ---------- Locks that guard important data structures in Heap
124131
//
125132
private:
@@ -301,38 +308,6 @@ class ShenandoahHeap : public CollectedHeap {
301308
inline bool is_concurrent_strong_root_in_progress() const;
302309
inline bool is_concurrent_weak_root_in_progress() const;
303310

304-
// ---------- GC cancellation and degeneration machinery
305-
//
306-
// Cancelled GC flag is used to notify concurrent phases that they should terminate.
307-
//
308-
public:
309-
enum ShenandoahDegenPoint {
310-
_degenerated_unset,
311-
_degenerated_outside_cycle,
312-
_degenerated_mark,
313-
_degenerated_evac,
314-
_degenerated_updaterefs,
315-
_DEGENERATED_LIMIT
316-
};
317-
318-
static const char* degen_point_to_string(ShenandoahDegenPoint point) {
319-
switch (point) {
320-
case _degenerated_unset:
321-
return "<UNSET>";
322-
case _degenerated_outside_cycle:
323-
return "Outside of Cycle";
324-
case _degenerated_mark:
325-
return "Mark";
326-
case _degenerated_evac:
327-
return "Evacuation";
328-
case _degenerated_updaterefs:
329-
return "Update Refs";
330-
default:
331-
ShouldNotReachHere();
332-
return "ERROR";
333-
}
334-
};
335-
336311
private:
337312
enum CancelState {
338313
// Normal state. GC has not been cancelled and is open for cancellation.
@@ -362,85 +337,38 @@ class ShenandoahHeap : public CollectedHeap {
362337

363338
void cancel_gc(GCCause::Cause cause);
364339

365-
// ---------- GC operations entry points
366-
//
367340
public:
368-
// Entry points to STW GC operations, these cause a related safepoint, that then
369-
// call the entry method below
370-
void vmop_entry_init_mark();
371-
void vmop_entry_final_mark();
372-
void vmop_entry_init_updaterefs();
373-
void vmop_entry_final_updaterefs();
374-
void vmop_entry_full(GCCause::Cause cause);
375-
void vmop_degenerated(ShenandoahDegenPoint point);
376-
377-
// Entry methods to normally STW GC operations. These set up logging, monitoring
378-
// and workers for net VM operation
379-
void entry_init_mark();
380-
void entry_final_mark();
381-
void entry_init_updaterefs();
382-
void entry_final_updaterefs();
383-
void entry_full(GCCause::Cause cause);
384-
void entry_degenerated(int point);
385-
386-
// Entry methods to normally concurrent GC operations. These set up logging, monitoring
387-
// for concurrent operation.
388-
void entry_reset();
389-
void entry_mark_roots();
390-
void entry_mark();
391-
void entry_weak_refs();
392-
void entry_weak_roots();
393-
void entry_class_unloading();
394-
void entry_strong_roots();
395-
void entry_cleanup_early();
396-
void entry_rendezvous_roots();
397-
void entry_evac();
398-
void entry_update_thread_roots();
399-
void entry_updaterefs();
400-
void entry_cleanup_complete();
341+
// Elastic heap support
401342
void entry_uncommit(double shrink_before, size_t shrink_until);
343+
void op_uncommit(double shrink_before, size_t shrink_until);
402344

403345
private:
404-
// Actual work for the phases
405-
void op_init_mark();
406-
void op_final_mark();
407-
void op_init_updaterefs();
408-
void op_final_updaterefs();
409-
void op_full(GCCause::Cause cause);
410-
void op_degenerated(ShenandoahDegenPoint point);
411-
void op_degenerated_fail();
412-
void op_degenerated_futile();
413-
414-
void op_reset();
415-
void op_mark_roots();
416-
void op_mark();
417-
void op_weak_refs();
418-
void op_weak_roots();
419-
void op_class_unloading();
420-
void op_strong_roots();
421-
void op_cleanup_early();
422-
void op_rendezvous_roots();
423-
void op_conc_evac();
424-
void op_stw_evac();
425-
void op_update_thread_roots();
426-
void op_updaterefs();
427-
void op_cleanup_complete();
428-
void op_uncommit(double shrink_before, size_t shrink_until);
346+
// GC support
347+
// Reset bitmap, prepare regions for new GC cycle
348+
void prepare_gc();
349+
void prepare_regions_and_collection_set(bool concurrent);
350+
// Evacuation
351+
void prepare_evacuation(bool concurrent);
352+
void evacuate_collection_set(bool concurrent);
353+
// Concurrent root processing
354+
void prepare_concurrent_roots();
355+
void finish_concurrent_roots();
356+
// Concurrent class unloading support
357+
void do_class_unloading();
358+
// Reference updating
359+
void prepare_update_heap_references(bool concurrent);
360+
void update_heap_references(bool concurrent);
361+
// Final update region states
362+
void update_heap_region_states(bool concurrent);
363+
void rebuild_free_set(bool concurrent);
429364

430365
void rendezvous_threads();
366+
void recycle_trash();
431367

432-
// Messages for GC trace events, they have to be immortal for
433-
// passing around the logging/tracing systems
434-
const char* init_mark_event_message() const;
435-
const char* final_mark_event_message() const;
436-
const char* conc_mark_event_message() const;
437-
const char* degen_event_message(ShenandoahDegenPoint point) const;
438-
439-
// Helpers
440-
void finish_mark();
441-
void prepare_evacuation();
368+
public:
369+
void notify_gc_progress() { _progress_last_gc.set(); }
370+
void notify_gc_no_progress() { _progress_last_gc.unset(); }
442371

443-
// ---------- GC subsystems
444372
//
445373
// Mark support
446374
private:
@@ -517,11 +445,6 @@ class ShenandoahHeap : public CollectedHeap {
517445
void stw_process_weak_roots(bool full_gc);
518446
void stw_weak_refs(bool full_gc);
519447

520-
// Prepare concurrent root processing
521-
void prepare_concurrent_roots();
522-
// Prepare and finish concurrent unloading
523-
void prepare_concurrent_unloading();
524-
void finish_concurrent_unloading();
525448
// Heap iteration support
526449
void scan_roots_for_iteration(ShenandoahScanObjectStack* oop_stack, ObjectIterateScanRootClosure* oops);
527450
bool prepare_aux_bitmap_for_iteration();
@@ -717,7 +640,6 @@ class ShenandoahHeap : public CollectedHeap {
717640

718641
private:
719642
void trash_cset_regions();
720-
void update_heap_references(bool concurrent);
721643

722644
// ---------- Testing helpers functions
723645
//

‎src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp

+51-7
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,21 @@
2828
#include "gc/shared/preservedMarks.inline.hpp"
2929
#include "gc/shared/tlab_globals.hpp"
3030
#include "gc/shenandoah/shenandoahForwarding.inline.hpp"
31-
#include "gc/shenandoah/shenandoahConcurrentMark.hpp"
31+
#include "gc/shenandoah/shenandoahConcurrentGC.hpp"
3232
#include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
3333
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
3434
#include "gc/shenandoah/shenandoahFreeSet.hpp"
3535
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
3636
#include "gc/shenandoah/shenandoahMark.inline.hpp"
3737
#include "gc/shenandoah/shenandoahMarkCompact.hpp"
38+
#include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
3839
#include "gc/shenandoah/shenandoahHeapRegionSet.hpp"
3940
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
4041
#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
4142
#include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
4243
#include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
4344
#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
4445
#include "gc/shenandoah/shenandoahSTWMark.hpp"
45-
#include "gc/shenandoah/shenandoahTaskqueue.inline.hpp"
4646
#include "gc/shenandoah/shenandoahUtils.hpp"
4747
#include "gc/shenandoah/shenandoahVerifier.hpp"
4848
#include "gc/shenandoah/shenandoahVMOperations.hpp"
@@ -55,16 +55,60 @@
5555
#include "runtime/biasedLocking.hpp"
5656
#include "runtime/orderAccess.hpp"
5757
#include "runtime/thread.hpp"
58+
#include "runtime/vmThread.hpp"
5859
#include "utilities/copy.hpp"
60+
#include "utilities/events.hpp"
5961
#include "utilities/growableArray.hpp"
6062
#include "gc/shared/workgroup.hpp"
6163

6264
ShenandoahMarkCompact::ShenandoahMarkCompact() :
63-
_gc_timer(NULL),
65+
_gc_timer(ShenandoahHeap::heap()->gc_timer()),
6466
_preserved_marks(new PreservedMarksSet(true)) {}
6567

66-
void ShenandoahMarkCompact::initialize(GCTimer* gc_timer) {
67-
_gc_timer = gc_timer;
68+
bool ShenandoahMarkCompact::collect(GCCause::Cause cause) {
69+
vmop_entry_full(cause);
70+
// Always success
71+
return true;
72+
}
73+
74+
void ShenandoahMarkCompact::vmop_entry_full(GCCause::Cause cause) {
75+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
76+
TraceCollectorStats tcs(heap->monitoring_support()->full_stw_collection_counters());
77+
ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::full_gc_gross);
78+
79+
heap->try_inject_alloc_failure();
80+
VM_ShenandoahFullGC op(cause, this);
81+
VMThread::execute(&op);
82+
}
83+
84+
void ShenandoahMarkCompact::entry_full(GCCause::Cause cause) {
85+
static const char* msg = "Pause Full";
86+
ShenandoahPausePhase gc_phase(msg, ShenandoahPhaseTimings::full_gc, true /* log_heap_usage */);
87+
EventMark em("%s", msg);
88+
89+
ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
90+
ShenandoahWorkerPolicy::calc_workers_for_fullgc(),
91+
"full gc");
92+
93+
op_full(cause);
94+
}
95+
96+
void ShenandoahMarkCompact::op_full(GCCause::Cause cause) {
97+
ShenandoahMetricsSnapshot metrics;
98+
metrics.snap_before();
99+
100+
// Perform full GC
101+
do_it(cause);
102+
103+
metrics.snap_after();
104+
105+
if (metrics.is_good_progress()) {
106+
ShenandoahHeap::heap()->notify_gc_progress();
107+
} else {
108+
// Nothing to do. Tell the allocation path that we have failed to make
109+
// progress, and it can finally fail.
110+
ShenandoahHeap::heap()->notify_gc_no_progress();
111+
}
68112
}
69113

70114
void ShenandoahMarkCompact::do_it(GCCause::Cause gc_cause) {
@@ -116,14 +160,14 @@ void ShenandoahMarkCompact::do_it(GCCause::Cause gc_cause) {
116160

117161
// b. Cancel concurrent mark, if in progress
118162
if (heap->is_concurrent_mark_in_progress()) {
119-
ShenandoahConcurrentMark::cancel();
163+
ShenandoahConcurrentGC::cancel();
120164
heap->set_concurrent_mark_in_progress(false);
121165
}
122166
assert(!heap->is_concurrent_mark_in_progress(), "sanity");
123167

124168
// c. Update roots if this full GC is due to evac-oom, which may carry from-space pointers in roots.
125169
if (has_forwarded_objects) {
126-
ShenandoahConcurrentMark::update_roots(ShenandoahPhaseTimings::full_gc_update_roots);
170+
update_roots(true /*full_gc*/);
127171
}
128172

129173
// d. Reset the bitmaps for new marking

‎src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.hpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
#define SHARE_GC_SHENANDOAH_SHENANDOAHMARKCOMPACT_HPP
2727

2828
#include "gc/shared/gcTimer.hpp"
29+
#include "gc/shenandoah/shenandoahGC.hpp"
2930
#include "gc/shenandoah/shenandoahHeap.hpp"
3031
#include "gc/shenandoah/shenandoahHeapRegionSet.hpp"
32+
#include "gc/shenandoah/shenandoahMetrics.hpp"
3133

3234
/**
3335
* This implements Full GC (e.g. when invoking System.gc()) using a mark-compact algorithm.
@@ -51,21 +53,31 @@
5153
*/
5254

5355
class PreservedMarksSet;
56+
class VM_ShenandoahFullGC;
57+
class ShenandoahDegenGC;
5458

55-
class ShenandoahMarkCompact : public StackObj {
59+
class ShenandoahMarkCompact : public ShenandoahGC {
5660
friend class ShenandoahPrepareForCompactionObjectClosure;
61+
friend class VM_ShenandoahFullGC;
62+
friend class ShenandoahDegenGC;
63+
5764
private:
5865
GCTimer* _gc_timer;
5966

6067
PreservedMarksSet* _preserved_marks;
6168

6269
public:
6370
ShenandoahMarkCompact();
64-
void initialize(GCTimer* gc_timer);
71+
bool collect(GCCause::Cause cause);
72+
73+
private:
74+
// GC entries
75+
void vmop_entry_full(GCCause::Cause cause);
76+
void entry_full(GCCause::Cause cause);
77+
void op_full(GCCause::Cause cause);
6578

6679
void do_it(GCCause::Cause gc_cause);
6780

68-
private:
6981
void phase1_mark_heap();
7082
void phase2_calculate_target_addresses(ShenandoahHeapRegionSet** worker_slices);
7183
void phase3_update_references();

‎src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ bool ShenandoahPhaseTimings::is_worker_phase(Phase phase) {
9898
switch (phase) {
9999
case init_evac:
100100
case scan_roots:
101-
case update_roots:
102-
case final_update_refs_roots:
101+
case finish_mark:
102+
case purge_weak_par:
103103
case full_gc_mark:
104104
case full_gc_update_roots:
105105
case full_gc_adjust_roots:
@@ -126,9 +126,8 @@ bool ShenandoahPhaseTimings::is_worker_phase(Phase phase) {
126126
bool ShenandoahPhaseTimings::is_root_work_phase(Phase phase) {
127127
switch (phase) {
128128
case scan_roots:
129-
case update_roots:
129+
case finish_mark:
130130
case init_evac:
131-
case final_update_refs_roots:
132131
case degen_gc_update_roots:
133132
case full_gc_mark:
134133
case full_gc_update_roots:

‎src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp

+20-9
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,18 @@ class outputStream;
5656
f(scan_roots, " Scan Roots") \
5757
SHENANDOAH_PAR_PHASE_DO(scan_, " S: ", f) \
5858
\
59-
f(conc_mark, "Concurrent Marking") \
6059
f(conc_mark_roots, " Roots ") \
6160
SHENANDOAH_PAR_PHASE_DO(conc_mark_roots, " CM: ", f) \
61+
f(conc_mark, "Concurrent Marking") \
6262
\
6363
f(final_mark_gross, "Pause Final Mark (G)") \
6464
f(final_mark, "Pause Final Mark (N)") \
65-
f(update_roots, " Update Roots") \
66-
SHENANDOAH_PAR_PHASE_DO(update_, " U: ", f) \
67-
f(finish_queues, " Finish Queues") \
68-
f(weakrefs, " Weak References") \
69-
f(weakrefs_process, " Process") \
65+
f(finish_mark, " Finish Mark") \
66+
SHENANDOAH_PAR_PHASE_DO(finish_mark_, " FM: ", f) \
67+
f(purge, " System Purge") \
68+
SHENANDOAH_PAR_PHASE_DO(purge_cu_par_, " CU: ", f) \
69+
f(purge_weak_par, " Weak Roots") \
70+
SHENANDOAH_PAR_PHASE_DO(purge_weak_par_, " WR: ", f) \
7071
f(final_update_region_states, " Update Region States") \
7172
f(final_manage_labs, " Manage GC/TLABs") \
7273
f(choose_cset, " Choose Collection Set") \
@@ -101,14 +102,12 @@ class outputStream;
101102
f(init_update_refs, "Pause Init Update Refs (N)") \
102103
f(init_update_refs_manage_gclabs, " Manage GCLABs") \
103104
\
104-
f(conc_update_thread_roots, "Concurrent Update Thread Roots") \
105105
f(conc_update_refs, "Concurrent Update Refs") \
106+
f(conc_update_thread_roots, "Concurrent Update Thread Roots") \
106107
\
107108
f(final_update_refs_gross, "Pause Final Update Refs (G)") \
108109
f(final_update_refs, "Pause Final Update Refs (N)") \
109110
f(final_update_refs_finish_work, " Finish Work") \
110-
f(final_update_refs_roots, " Update Roots") \
111-
SHENANDOAH_PAR_PHASE_DO(final_update_, " UR: ", f) \
112111
f(final_update_refs_update_region_states, " Update Region States") \
113112
f(final_update_refs_trash_cset, " Trash Collection Set") \
114113
f(final_update_refs_rebuild_freeset, " Rebuild Free Set") \
@@ -129,8 +128,20 @@ class outputStream;
129128
f(degen_gc_purge_weak_par, " Weak Roots") \
130129
SHENANDOAH_PAR_PHASE_DO(degen_gc_purge_weak_p_, " DWR: ", f) \
131130
f(degen_gc_purge_cldg, " CLDG") \
131+
f(degen_gc_final_update_region_states, " Update Region States") \
132+
f(degen_gc_final_manage_labs, " Manage GC/TLABs") \
133+
f(degen_gc_choose_cset, " Choose Collection Set") \
134+
f(degen_gc_final_rebuild_freeset, " Rebuild Free Set") \
135+
f(degen_gc_stw_evac, " Evacuation") \
136+
f(degen_gc_init_update_refs_manage_gclabs, " Manage GCLABs") \
137+
f(degen_gc_updaterefs, " Update References") \
138+
f(degen_gc_final_update_refs_finish_work, " Finish Work") \
139+
f(degen_gc_final_update_refs_update_region_states," Update Region States") \
140+
f(degen_gc_final_update_refs_trash_cset, " Trash Collection Set") \
141+
f(degen_gc_final_update_refs_rebuild_freeset, " Rebuild Free Set") \
132142
f(degen_gc_update_roots, " Degen Update Roots") \
133143
SHENANDOAH_PAR_PHASE_DO(degen_gc_update_, " DU: ", f) \
144+
f(degen_gc_cleanup_complete, " Cleanup") \
134145
\
135146
f(full_gc_gross, "Pause Full GC (G)") \
136147
f(full_gc, "Pause Full GC (N)") \

‎src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
2+
* Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,11 @@
2424

2525
#include "precompiled.hpp"
2626

27+
#include "gc/shenandoah/shenandoahConcurrentGC.hpp"
28+
#include "gc/shenandoah/shenandoahDegeneratedGC.hpp"
2729
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
30+
#include "gc/shenandoah/shenandoahMark.inline.hpp"
31+
#include "gc/shenandoah/shenandoahMarkCompact.hpp"
2832
#include "gc/shenandoah/shenandoahUtils.hpp"
2933
#include "gc/shenandoah/shenandoahVMOperations.hpp"
3034
#include "memory/universe.hpp"
@@ -43,30 +47,30 @@ void VM_ShenandoahReferenceOperation::doit_epilogue() {
4347

4448
void VM_ShenandoahInitMark::doit() {
4549
ShenandoahGCPauseMark mark(_gc_id, SvcGCMarker::CONCURRENT);
46-
ShenandoahHeap::heap()->entry_init_mark();
50+
_gc->entry_init_mark();
4751
}
4852

4953
void VM_ShenandoahFinalMarkStartEvac::doit() {
5054
ShenandoahGCPauseMark mark(_gc_id, SvcGCMarker::CONCURRENT);
51-
ShenandoahHeap::heap()->entry_final_mark();
55+
_gc->entry_final_mark();
5256
}
5357

5458
void VM_ShenandoahFullGC::doit() {
5559
ShenandoahGCPauseMark mark(_gc_id, SvcGCMarker::FULL);
56-
ShenandoahHeap::heap()->entry_full(_gc_cause);
60+
_full_gc->entry_full(_gc_cause);
5761
}
5862

5963
void VM_ShenandoahDegeneratedGC::doit() {
6064
ShenandoahGCPauseMark mark(_gc_id, SvcGCMarker::CONCURRENT);
61-
ShenandoahHeap::heap()->entry_degenerated(_point);
65+
_gc->entry_degenerated();
6266
}
6367

6468
void VM_ShenandoahInitUpdateRefs::doit() {
6569
ShenandoahGCPauseMark mark(_gc_id, SvcGCMarker::CONCURRENT);
66-
ShenandoahHeap::heap()->entry_init_updaterefs();
70+
_gc->entry_init_updaterefs();
6771
}
6872

6973
void VM_ShenandoahFinalUpdateRefs::doit() {
7074
ShenandoahGCPauseMark mark(_gc_id, SvcGCMarker::CONCURRENT);
71-
ShenandoahHeap::heap()->entry_final_updaterefs();
75+
_gc->entry_final_updaterefs();
7276
}

‎src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp

+34-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
2+
* Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,10 @@
2727

2828
#include "gc/shared/gcVMOperations.hpp"
2929

30+
class ShenandoahConcurrentGC;
31+
class ShenandoahDegenGC;
32+
class ShenandoahMarkCompact;
33+
3034
// VM_operations for the Shenandoah Collector.
3135
//
3236
// VM_ShenandoahOperation
@@ -52,54 +56,73 @@ class VM_ShenandoahReferenceOperation : public VM_ShenandoahOperation {
5256
};
5357

5458
class VM_ShenandoahInitMark: public VM_ShenandoahOperation {
59+
private:
60+
ShenandoahConcurrentGC* const _gc;
5561
public:
56-
VM_ShenandoahInitMark() : VM_ShenandoahOperation() {};
62+
VM_ShenandoahInitMark(ShenandoahConcurrentGC* gc) :
63+
VM_ShenandoahOperation(),
64+
_gc(gc) {};
5765
VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahInitMark; }
5866
const char* name() const { return "Shenandoah Init Marking"; }
5967
virtual void doit();
6068
};
6169

6270
class VM_ShenandoahFinalMarkStartEvac: public VM_ShenandoahOperation {
71+
private:
72+
ShenandoahConcurrentGC* const _gc;
6373
public:
64-
VM_ShenandoahFinalMarkStartEvac() : VM_ShenandoahOperation() {};
74+
VM_ShenandoahFinalMarkStartEvac(ShenandoahConcurrentGC* gc) :
75+
VM_ShenandoahOperation(),
76+
_gc(gc) {};
6577
VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahFinalMarkStartEvac; }
6678
const char* name() const { return "Shenandoah Final Mark and Start Evacuation"; }
6779
virtual void doit();
6880
};
6981

7082
class VM_ShenandoahDegeneratedGC: public VM_ShenandoahReferenceOperation {
7183
private:
72-
// Really the ShenandoahHeap::ShenandoahDegenerationPoint, but casted to int here
73-
// in order to avoid dependency on ShenandoahHeap
74-
int _point;
84+
ShenandoahDegenGC* const _gc;
7585
public:
76-
VM_ShenandoahDegeneratedGC(int point) : VM_ShenandoahReferenceOperation(), _point(point) {};
86+
VM_ShenandoahDegeneratedGC(ShenandoahDegenGC* gc) :
87+
VM_ShenandoahReferenceOperation(),
88+
_gc(gc) {};
89+
7790
VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahDegeneratedGC; }
7891
const char* name() const { return "Shenandoah Degenerated GC"; }
7992
virtual void doit();
8093
};
8194

8295
class VM_ShenandoahFullGC : public VM_ShenandoahReferenceOperation {
8396
private:
84-
GCCause::Cause _gc_cause;
97+
GCCause::Cause _gc_cause;
98+
ShenandoahMarkCompact* const _full_gc;
8599
public:
86-
VM_ShenandoahFullGC(GCCause::Cause gc_cause) : VM_ShenandoahReferenceOperation(), _gc_cause(gc_cause) {};
100+
VM_ShenandoahFullGC(GCCause::Cause gc_cause, ShenandoahMarkCompact* full_gc) :
101+
VM_ShenandoahReferenceOperation(),
102+
_gc_cause(gc_cause),
103+
_full_gc(full_gc) {};
87104
VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahFullGC; }
88105
const char* name() const { return "Shenandoah Full GC"; }
89106
virtual void doit();
90107
};
91108

92109
class VM_ShenandoahInitUpdateRefs: public VM_ShenandoahOperation {
110+
ShenandoahConcurrentGC* const _gc;
93111
public:
94-
VM_ShenandoahInitUpdateRefs() : VM_ShenandoahOperation() {};
112+
VM_ShenandoahInitUpdateRefs(ShenandoahConcurrentGC* gc) :
113+
VM_ShenandoahOperation(),
114+
_gc(gc) {};
95115
VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahInitUpdateRefs; }
96116
const char* name() const { return "Shenandoah Init Update References"; }
97117
virtual void doit();
98118
};
99119

100120
class VM_ShenandoahFinalUpdateRefs: public VM_ShenandoahOperation {
121+
ShenandoahConcurrentGC* const _gc;
101122
public:
102-
VM_ShenandoahFinalUpdateRefs() : VM_ShenandoahOperation() {};
123+
VM_ShenandoahFinalUpdateRefs(ShenandoahConcurrentGC* gc) :
124+
VM_ShenandoahOperation(),
125+
_gc(gc) {};
103126
VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahFinalUpdateRefs; }
104127
const char* name() const { return "Shenandoah Final Update References"; }
105128
virtual void doit();

0 commit comments

Comments
 (0)
Please sign in to comment.