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