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  }