1 /*
2 * Copyright (c) 2015, 2020, 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 "classfile/classLoaderDataGraph.hpp"
28 #include "classfile/stringTable.hpp"
29 #include "classfile/systemDictionary.hpp"
30 #include "code/codeCache.hpp"
31 #include "gc/shenandoah/shenandoahClosures.inline.hpp"
32 #include "gc/shenandoah/shenandoahConcurrentRoots.hpp"
33 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
34 #include "gc/shenandoah/shenandoahHeap.hpp"
35 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
36 #include "gc/shenandoah/shenandoahStringDedup.hpp"
37 #include "gc/shenandoah/shenandoahTimingTracker.hpp"
38 #include "gc/shenandoah/shenandoahVMOperations.hpp"
39 #include "jfr/jfr.hpp"
40 #include "memory/iterator.hpp"
41 #include "memory/resourceArea.hpp"
42 #include "memory/universe.hpp"
43 #include "runtime/thread.hpp"
44 #include "services/management.hpp"
45 #include "tsan/tsanOopMap.hpp"
46
47 ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases phase) :
48 _oops_do(oops_do), _phase(phase) {
49 }
50
51 void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) {
52 if (_claimed.try_set()) {
53 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
54 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
55 _oops_do(cl);
56 }
57 }
58
59 // Overwrite the second argument for SD::oops_do, don't include vm global oop storage.
60 static void system_dictionary_oops_do(OopClosure* cl) {
61 SystemDictionary::oops_do(cl, false);
62 }
63
64 ShenandoahSerialRoots::ShenandoahSerialRoots() :
65 _universe_root(&Universe::oops_do, ShenandoahPhaseTimings::UniverseRoots),
66 _object_synchronizer_root(&ObjectSynchronizer::oops_do, ShenandoahPhaseTimings::ObjectSynchronizerRoots),
67 _management_root(&Management::oops_do, ShenandoahPhaseTimings::ManagementRoots),
68 _system_dictionary_root(&system_dictionary_oops_do, ShenandoahPhaseTimings::SystemDictionaryRoots),
69 _jvmti_root(&JvmtiExport::oops_do, ShenandoahPhaseTimings::JVMTIRoots) {
70 }
71
72 void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) {
73 _universe_root.oops_do(cl, worker_id);
74 _object_synchronizer_root.oops_do(cl, worker_id);
75 _management_root.oops_do(cl, worker_id);
76 _system_dictionary_root.oops_do(cl, worker_id);
77 _jvmti_root.oops_do(cl, worker_id);
78 }
79
80 ShenandoahWeakSerialRoot::ShenandoahWeakSerialRoot(ShenandoahWeakSerialRoot::WeakOopsDo weak_oops_do, ShenandoahPhaseTimings::GCParPhases phase) :
81 _weak_oops_do(weak_oops_do), _phase(phase) {
82 }
83
84 void ShenandoahWeakSerialRoot::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) {
85 if (_claimed.try_set()) {
86 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
87 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
88 _weak_oops_do(is_alive, keep_alive);
89 }
90 }
91
92 #if INCLUDE_JVMTI
93 ShenandoahJVMTIWeakRoot::ShenandoahJVMTIWeakRoot() :
94 ShenandoahWeakSerialRoot(&JvmtiExport::weak_oops_do, ShenandoahPhaseTimings::JVMTIWeakRoots) {
95 }
96 #endif // INCLUDE_JVMTI
97
98 #if INCLUDE_JFR
99 ShenandoahJFRWeakRoot::ShenandoahJFRWeakRoot() :
100 ShenandoahWeakSerialRoot(&Jfr::weak_oops_do, ShenandoahPhaseTimings::JFRWeakRoots) {
101 }
102 #endif // INCLUDE_JFR
103
104 #if INCLUDE_TSAN
105 ShenandoahTSANWeakRoot::ShenandoahTSANWeakRoot() :
106 ShenandoahWeakSerialRoot(&TsanOopMap::weak_oops_do, ShenandoahPhaseTimings::TSANWeakRoots) {
107 }
108 #endif // INCLUDE_TSAN
109
110 void ShenandoahSerialWeakRoots::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) {
111 JVMTI_ONLY(_jvmti_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);)
112 JFR_ONLY(_jfr_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);)
113 TSAN_ONLY(_tsan_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);)
114 }
115
116 void ShenandoahSerialWeakRoots::weak_oops_do(OopClosure* cl, uint worker_id) {
117 AlwaysTrueClosure always_true;
118 weak_oops_do(&always_true, cl, worker_id);
119 }
120
121 ShenandoahThreadRoots::ShenandoahThreadRoots(bool is_par) : _is_par(is_par) {
122 Threads::change_thread_claim_token();
123 }
124
125 void ShenandoahThreadRoots::oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id) {
126 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
127 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
128 ResourceMark rm;
129 Threads::possibly_parallel_oops_do(_is_par, oops_cl, code_cl);
130 }
131
132 void ShenandoahThreadRoots::threads_do(ThreadClosure* tc, uint worker_id) {
133 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
134 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
135 ResourceMark rm;
136 Threads::possibly_parallel_threads_do(_is_par, tc);
137 }
138
139 ShenandoahThreadRoots::~ShenandoahThreadRoots() {
140 Threads::assert_all_threads_claimed();
141 }
142
143 ShenandoahStringDedupRoots::ShenandoahStringDedupRoots() {
144 if (ShenandoahStringDedup::is_enabled()) {
145 StringDedup::gc_prologue(false);
146 }
147 }
148
149 ShenandoahStringDedupRoots::~ShenandoahStringDedupRoots() {
150 if (ShenandoahStringDedup::is_enabled()) {
151 StringDedup::gc_epilogue();
152 }
153 }
154
155 void ShenandoahStringDedupRoots::oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) {
156 if (ShenandoahStringDedup::is_enabled()) {
157 ShenandoahStringDedup::parallel_oops_do(is_alive, keep_alive, worker_id);
158 }
159 }
160
161 ShenandoahConcurrentStringDedupRoots::ShenandoahConcurrentStringDedupRoots() {
162 if (ShenandoahStringDedup::is_enabled()) {
163 StringDedupTable_lock->lock_without_safepoint_check();
164 StringDedupQueue_lock->lock_without_safepoint_check();
165 StringDedup::gc_prologue(true);
166 }
167 }
168
169 ShenandoahConcurrentStringDedupRoots::~ShenandoahConcurrentStringDedupRoots() {
170 if (ShenandoahStringDedup::is_enabled()) {
171 StringDedup::gc_epilogue();
172 StringDedupQueue_lock->unlock();
173 StringDedupTable_lock->unlock();
174 }
175 }
176
177 void ShenandoahConcurrentStringDedupRoots::oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) {
178 if (ShenandoahStringDedup::is_enabled()) {
179 assert_locked_or_safepoint_weak(StringDedupQueue_lock);
180 assert_locked_or_safepoint_weak(StringDedupTable_lock);
181
182 StringDedupUnlinkOrOopsDoClosure sd_cl(is_alive, keep_alive);
183 StringDedupQueue::unlink_or_oops_do(&sd_cl);
184 StringDedupTable::unlink_or_oops_do(&sd_cl, worker_id);
185 }
186 }
187
188 ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) :
189 _heap(ShenandoahHeap::heap()),
190 _phase(phase) {
191 assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
192 _heap->phase_timings()->record_workers_start(_phase);
193 }
194
195 ShenandoahRootProcessor::~ShenandoahRootProcessor() {
196 assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
197 _heap->phase_timings()->record_workers_end(_phase);
198 }
199
200 ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers,
201 ShenandoahPhaseTimings::Phase phase,
202 bool include_concurrent_roots,
203 bool include_concurrent_code_roots) :
204 ShenandoahRootProcessor(phase),
205 _thread_roots(n_workers > 1),
206 _include_concurrent_roots(include_concurrent_roots),
207 _include_concurrent_code_roots(include_concurrent_code_roots) {
208 }
209
210 void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
211 MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations);
212 ShenandoahCodeBlobAndDisarmClosure blobs_and_disarm_Cl(oops);
213 CodeBlobToOopClosure* codes_cl = ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() ?
214 static_cast<CodeBlobToOopClosure*>(&blobs_and_disarm_Cl) :
215 static_cast<CodeBlobToOopClosure*>(&blobsCl);
216 AlwaysTrueClosure always_true;
217
218 _serial_roots.oops_do(oops, worker_id);
219 _serial_weak_roots.weak_oops_do(oops, worker_id);
220 if (_include_concurrent_roots) {
221 CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
222 _vm_roots.oops_do<OopClosure>(oops, worker_id);
223 _cld_roots.cld_do(&clds, worker_id);
224 _weak_roots.oops_do<OopClosure>(oops, worker_id);
225 _dedup_roots.oops_do(&always_true, oops, worker_id);
226 }
227
228 if (_include_concurrent_code_roots) {
229 _code_roots.code_blobs_do(codes_cl, worker_id);
230 _thread_roots.oops_do(oops, NULL, worker_id);
231 } else {
232 _thread_roots.oops_do(oops, codes_cl, worker_id);
233 }
234 }
235
236 ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
237 ShenandoahRootProcessor(phase),
238 _thread_roots(n_workers > 1) {
239 }
240
241 ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
242 ShenandoahRootProcessor(phase),
243 _thread_roots(n_workers > 1) {
244 assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Full GC only");
245 }
246
247 void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
248 CodeBlobToOopClosure code_blob_cl(oops, CodeBlobToOopClosure::FixRelocations);
249 ShenandoahCodeBlobAndDisarmClosure blobs_and_disarm_Cl(oops);
250 CodeBlobToOopClosure* adjust_code_closure = ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() ?
251 static_cast<CodeBlobToOopClosure*>(&blobs_and_disarm_Cl) :
252 static_cast<CodeBlobToOopClosure*>(&code_blob_cl);
253 CLDToOopClosure adjust_cld_closure(oops, ClassLoaderData::_claim_strong);
254 AlwaysTrueClosure always_true;
255
256 _serial_roots.oops_do(oops, worker_id);
257 _vm_roots.oops_do(oops, worker_id);
258
259 _thread_roots.oops_do(oops, NULL, worker_id);
260 _cld_roots.cld_do(&adjust_cld_closure, worker_id);
261 _code_roots.code_blobs_do(adjust_code_closure, worker_id);
262
263 _serial_weak_roots.weak_oops_do(oops, worker_id);
264 _weak_roots.oops_do<OopClosure>(oops, worker_id);
265 _dedup_roots.oops_do(&always_true, oops, worker_id);
266 }
267
268 ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() :
269 ShenandoahRootProcessor(ShenandoahPhaseTimings::_num_phases),
270 _thread_roots(false /*is par*/) {
271 }
272
273 void ShenandoahHeapIterationRootScanner::roots_do(OopClosure* oops) {
274 assert(Thread::current()->is_VM_thread(), "Only by VM thread");
275 // Must use _claim_none to avoid interfering with concurrent CLDG iteration
276 CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
277 MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations);
278 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL);
279 AlwaysTrueClosure always_true;
280 ResourceMark rm;
281
282 _serial_roots.oops_do(oops, 0);
283 _vm_roots.oops_do(oops, 0);
284 _cld_roots.cld_do(&clds, 0);
285 _thread_roots.threads_do(&tc_cl, 0);
286 _code_roots.code_blobs_do(&code, 0);
287
288 _serial_weak_roots.weak_oops_do(oops, 0);
289 _weak_roots.oops_do<OopClosure>(oops, 0);
290 _dedup_roots.oops_do(&always_true, oops, 0);
291 }
292
293 void ShenandoahHeapIterationRootScanner::strong_roots_do(OopClosure* oops) {
294 assert(Thread::current()->is_VM_thread(), "Only by VM thread");
295 // Must use _claim_none to avoid interfering with concurrent CLDG iteration
296 CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
297 MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations);
298 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL);
299 ResourceMark rm;
300
301 _serial_roots.oops_do(oops, 0);
302 _vm_roots.oops_do(oops, 0);
303 _cld_roots.always_strong_cld_do(&clds, 0);
304 _thread_roots.threads_do(&tc_cl, 0);
305 }