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  }