1 /*
2 * Copyright (c) 2021, 2022, 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
26 #include "precompiled.hpp"
27
28 #include "gc/shared/strongRootsScope.hpp"
29 #include "gc/shared/taskTerminator.hpp"
30 #include "gc/shared/workerThread.hpp"
31 #include "gc/shenandoah/shenandoahClosures.inline.hpp"
32 #include "gc/shenandoah/shenandoahGenerationType.hpp"
33 #include "gc/shenandoah/shenandoahMark.inline.hpp"
34 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
35 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
36 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
37 #include "gc/shenandoah/shenandoahSTWMark.hpp"
38 #include "gc/shenandoah/shenandoahVerifier.hpp"
39
40 template<ShenandoahGenerationType GENERATION>
41 class ShenandoahInitMarkRootsClosure : public OopClosure {
42 private:
43 ShenandoahObjToScanQueue* const _queue;
44 ShenandoahMarkingContext* const _mark_context;
45
46 template <class T>
47 inline void do_oop_work(T* p);
48 public:
49 ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q);
50
51 void do_oop(narrowOop* p) { do_oop_work(p); }
52 void do_oop(oop* p) { do_oop_work(p); }
53 };
54
55 template <ShenandoahGenerationType GENERATION>
56 ShenandoahInitMarkRootsClosure<GENERATION>::ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q) :
57 _queue(q),
58 _mark_context(ShenandoahHeap::heap()->marking_context()) {
59 }
60
61 template <ShenandoahGenerationType GENERATION>
62 template <class T>
63 void ShenandoahInitMarkRootsClosure<GENERATION>::do_oop_work(T* p) {
64 ShenandoahMark::mark_through_ref<T, GENERATION>(p, _queue, _mark_context, false);
65 }
66
67 class ShenandoahSTWMarkTask : public WorkerTask {
68 private:
69 ShenandoahSTWMark* const _mark;
70
71 public:
72 ShenandoahSTWMarkTask(ShenandoahSTWMark* mark);
73 void work(uint worker_id);
74 };
75
76 ShenandoahSTWMarkTask::ShenandoahSTWMarkTask(ShenandoahSTWMark* mark) :
77 WorkerTask("Shenandoah STW mark"),
78 _mark(mark) {
79 }
80
81 void ShenandoahSTWMarkTask::work(uint worker_id) {
82 ShenandoahParallelWorkerSession worker_session(worker_id);
83 _mark->mark_roots(worker_id);
84 _mark->finish_mark(worker_id);
85 }
86
87 ShenandoahSTWMark::ShenandoahSTWMark(bool full_gc) :
88 ShenandoahMark(),
89 _root_scanner(full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark),
90 _terminator(ShenandoahHeap::heap()->workers()->active_workers(), ShenandoahHeap::heap()->marking_context()->task_queues()),
91 _full_gc(full_gc) {
92 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a Shenandoah safepoint");
93 }
94
95 void ShenandoahSTWMark::mark() {
96 ShenandoahHeap* const heap = ShenandoahHeap::heap();
97
98 // Arm all nmethods. Even though this is STW mark, some marking code
99 // piggybacks on nmethod barriers for special instances.
100 ShenandoahCodeRoots::arm_nmethods_for_mark();
101
102 // Weak reference processing
103 ShenandoahReferenceProcessor* rp = heap->ref_processor();
104 rp->reset_thread_locals();
105 rp->set_soft_reference_policy(heap->soft_ref_policy()->should_clear_all_soft_refs());
106
107 // Init mark, do not expect forwarded pointers in roots
108 if (ShenandoahVerify) {
109 assert(Thread::current()->is_VM_thread(), "Must be");
110 heap->verifier()->verify_roots_no_forwarded();
111 }
112
113 start_mark();
114
115 uint nworkers = heap->workers()->active_workers();
116 task_queues()->reserve(nworkers);
117
118 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
119
120 {
121 // Mark
122 StrongRootsScope scope(nworkers);
123 ShenandoahSTWMarkTask task(this);
124 heap->workers()->run_task(&task);
125
126 assert(task_queues()->is_empty(), "Should be empty");
127 }
128
129 heap->mark_complete_marking_context();
130 end_mark();
131
132 // Mark is finished, can disarm the nmethods now.
133 ShenandoahCodeRoots::disarm_nmethods();
134
135 assert(task_queues()->is_empty(), "Should be empty");
136 TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
137 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
138 }
139
140 void ShenandoahSTWMark::mark_roots(uint worker_id) {
141 ShenandoahInitMarkRootsClosure<NON_GEN> init_mark(task_queues()->queue(worker_id));
142 _root_scanner.roots_do(&init_mark, worker_id);
143 }
144
145 void ShenandoahSTWMark::finish_mark(uint worker_id) {
146 ShenandoahPhaseTimings::Phase phase = _full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark;
147 ShenandoahWorkerTimingsTracker timer(phase, ShenandoahPhaseTimings::ParallelMark, worker_id);
148 ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->ref_processor();
149 StringDedup::Requests requests;
150
151 mark_loop(worker_id, &_terminator, rp, NON_GEN, false /* not cancellable */,
152 ShenandoahStringDedup::is_enabled() ? ALWAYS_DEDUP : NO_DEDUP, &requests);
153 }
|
1 /*
2 * Copyright (c) 2021, 2022, Red Hat, Inc. All rights reserved.
3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26
27 #include "precompiled.hpp"
28
29 #include "gc/shared/strongRootsScope.hpp"
30 #include "gc/shared/taskTerminator.hpp"
31 #include "gc/shared/workerThread.hpp"
32 #include "gc/shenandoah/shenandoahClosures.inline.hpp"
33 #include "gc/shenandoah/shenandoahGeneration.hpp"
34 #include "gc/shenandoah/shenandoahGenerationType.hpp"
35 #include "gc/shenandoah/shenandoahMark.inline.hpp"
36 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
37 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
38 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
39 #include "gc/shenandoah/shenandoahSTWMark.hpp"
40 #include "gc/shenandoah/shenandoahVerifier.hpp"
41
42 template<ShenandoahGenerationType GENERATION>
43 class ShenandoahInitMarkRootsClosure : public OopClosure {
44 private:
45 ShenandoahObjToScanQueue* const _queue;
46 ShenandoahMarkingContext* const _mark_context;
47
48 template <class T>
49 inline void do_oop_work(T* p);
50
51 public:
52 ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q);
53
54 void do_oop(narrowOop* p) { do_oop_work(p); }
55 void do_oop(oop* p) { do_oop_work(p); }
56 };
57
58 template <ShenandoahGenerationType GENERATION>
59 ShenandoahInitMarkRootsClosure<GENERATION>::ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q) :
60 _queue(q),
61 _mark_context(ShenandoahHeap::heap()->marking_context()) {
62 }
63
64 template <ShenandoahGenerationType GENERATION>
65 template <class T>
66 void ShenandoahInitMarkRootsClosure<GENERATION>::do_oop_work(T* p) {
67 // Only called from STW mark, should not be used to bootstrap old generation marking.
68 ShenandoahMark::mark_through_ref<T, GENERATION>(p, _queue, nullptr, _mark_context, false);
69 }
70
71 class ShenandoahSTWMarkTask : public WorkerTask {
72 private:
73 ShenandoahSTWMark* const _mark;
74
75 public:
76 ShenandoahSTWMarkTask(ShenandoahSTWMark* mark);
77 void work(uint worker_id);
78 };
79
80 ShenandoahSTWMarkTask::ShenandoahSTWMarkTask(ShenandoahSTWMark* mark) :
81 WorkerTask("Shenandoah STW mark"),
82 _mark(mark) {
83 }
84
85 void ShenandoahSTWMarkTask::work(uint worker_id) {
86 ShenandoahParallelWorkerSession worker_session(worker_id);
87 _mark->mark_roots(worker_id);
88 _mark->finish_mark(worker_id);
89 }
90
91 ShenandoahSTWMark::ShenandoahSTWMark(ShenandoahGeneration* generation, bool full_gc) :
92 ShenandoahMark(generation),
93 _root_scanner(full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark),
94 _terminator(ShenandoahHeap::heap()->workers()->active_workers(), task_queues()),
95 _full_gc(full_gc) {
96 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a Shenandoah safepoint");
97 }
98
99 void ShenandoahSTWMark::mark() {
100 ShenandoahHeap* const heap = ShenandoahHeap::heap();
101
102 // Arm all nmethods. Even though this is STW mark, some marking code
103 // piggybacks on nmethod barriers for special instances.
104 ShenandoahCodeRoots::arm_nmethods_for_mark();
105
106 // Weak reference processing
107 ShenandoahReferenceProcessor* rp = heap->active_generation()->ref_processor();
108 rp->reset_thread_locals();
109 rp->set_soft_reference_policy(heap->soft_ref_policy()->should_clear_all_soft_refs());
110
111 // Init mark, do not expect forwarded pointers in roots
112 if (ShenandoahVerify) {
113 assert(Thread::current()->is_VM_thread(), "Must be");
114 heap->verifier()->verify_roots_no_forwarded();
115 }
116
117 start_mark();
118
119 uint nworkers = heap->workers()->active_workers();
120 task_queues()->reserve(nworkers);
121
122 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
123
124 {
125 // Mark
126 if (_generation->is_young()) {
127 // But only scan the remembered set for young generation.
128 _generation->scan_remembered_set(false /* is_concurrent */);
129 }
130
131 StrongRootsScope scope(nworkers);
132 ShenandoahSTWMarkTask task(this);
133 heap->workers()->run_task(&task);
134
135 assert(task_queues()->is_empty(), "Should be empty");
136 }
137
138 _generation->set_mark_complete();
139 end_mark();
140
141 // Mark is finished, can disarm the nmethods now.
142 ShenandoahCodeRoots::disarm_nmethods();
143
144 assert(task_queues()->is_empty(), "Should be empty");
145 TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
146 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
147 }
148
149 void ShenandoahSTWMark::mark_roots(uint worker_id) {
150 switch (_generation->type()) {
151 case NON_GEN: {
152 ShenandoahInitMarkRootsClosure<NON_GEN> init_mark(task_queues()->queue(worker_id));
153 _root_scanner.roots_do(&init_mark, worker_id);
154 break;
155 }
156 case GLOBAL: {
157 ShenandoahInitMarkRootsClosure<GLOBAL> init_mark(task_queues()->queue(worker_id));
158 _root_scanner.roots_do(&init_mark, worker_id);
159 break;
160 }
161 case YOUNG: {
162 ShenandoahInitMarkRootsClosure<YOUNG> init_mark(task_queues()->queue(worker_id));
163 _root_scanner.roots_do(&init_mark, worker_id);
164 break;
165 }
166 case OLD:
167 default:
168 ShouldNotReachHere();
169 }
170 }
171
172 void ShenandoahSTWMark::finish_mark(uint worker_id) {
173 ShenandoahPhaseTimings::Phase phase = _full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark;
174 ShenandoahWorkerTimingsTracker timer(phase, ShenandoahPhaseTimings::ParallelMark, worker_id);
175 ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->active_generation()->ref_processor();
176 StringDedup::Requests requests;
177
178 mark_loop(worker_id, &_terminator, rp,
179 _generation->type(), false /* not cancellable */,
180 ShenandoahStringDedup::is_enabled() ? ALWAYS_DEDUP : NO_DEDUP, &requests);
181 }
|