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 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP
  26 #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP
  27 
  28 #include "code/codeCache.hpp"
  29 #include "gc/shared/oopStorageParState.hpp"
  30 #include "gc/shenandoah/shenandoahCodeRoots.hpp"
  31 #include "gc/shenandoah/shenandoahHeap.hpp"
  32 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
  33 #include "gc/shenandoah/shenandoahSharedVariables.hpp"
  34 #include "gc/shenandoah/shenandoahUtils.hpp"
  35 #include "memory/iterator.hpp"
  36 
  37 class ShenandoahSerialRoot {
  38 public:
  39   typedef void (*OopsDo)(OopClosure*);
  40 private:
  41   ShenandoahSharedFlag                   _claimed;
  42   const OopsDo                           _oops_do;
  43   const ShenandoahPhaseTimings::Phase    _phase;
  44   const ShenandoahPhaseTimings::ParPhase _par_phase;
  45 
  46 public:
  47   ShenandoahSerialRoot(OopsDo oops_do,
  48           ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase);
  49   void oops_do(OopClosure* cl, uint worker_id);
  50 };
  51 
  52 class ShenandoahSerialRoots {
  53 private:
  54   ShenandoahSerialRoot  _universe_root;
  55   ShenandoahSerialRoot  _object_synchronizer_root;
  56   ShenandoahSerialRoot  _management_root;
  57   ShenandoahSerialRoot  _jvmti_root;
  58 public:
  59   ShenandoahSerialRoots(ShenandoahPhaseTimings::Phase phase);
  60   void oops_do(OopClosure* cl, uint worker_id);
  61 };
  62 
  63 class ShenandoahWeakSerialRoot {
  64   typedef void (*WeakOopsDo)(BoolObjectClosure*, OopClosure*);
  65 private:
  66   ShenandoahSharedFlag                   _claimed;
  67   const WeakOopsDo                       _weak_oops_do;
  68   const ShenandoahPhaseTimings::Phase    _phase;
  69   const ShenandoahPhaseTimings::ParPhase _par_phase;
  70 
  71 public:
  72   ShenandoahWeakSerialRoot(WeakOopsDo oops_do,
  73           ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase);
  74   void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
  75 };
  76 
  77 #if INCLUDE_JVMTI
  78 class ShenandoahJVMTIWeakRoot : public ShenandoahWeakSerialRoot {
  79 public:
  80   ShenandoahJVMTIWeakRoot(ShenandoahPhaseTimings::Phase phase);
  81 };
  82 #endif // INCLUDE_JVMTI
  83 
  84 #if INCLUDE_JFR
  85 class ShenandoahJFRWeakRoot : public ShenandoahWeakSerialRoot {
  86 public:
  87   ShenandoahJFRWeakRoot(ShenandoahPhaseTimings::Phase phase);
  88 };
  89 #endif // INCLUDE_JFR
  90 
  91 class ShenandoahSerialWeakRoots {
  92 private:
  93   JVMTI_ONLY(ShenandoahJVMTIWeakRoot _jvmti_weak_roots;)
  94   JFR_ONLY(ShenandoahJFRWeakRoot     _jfr_weak_roots;)
  95 public:
  96   ShenandoahSerialWeakRoots(ShenandoahPhaseTimings::Phase phase) :
  97   JVMTI_ONLY(_jvmti_weak_roots(phase))
  98   JFR_ONLY(JVMTI_ONLY(COMMA)_jfr_weak_roots(phase)) {};
  99   void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
 100   void weak_oops_do(OopClosure* cl, uint worker_id);
 101 };
 102 
 103 template <bool CONCURRENT>
 104 class ShenandoahVMRoot {
 105 private:
 106   OopStorage::ParState<CONCURRENT, false /* is_const */> _itr;
 107   const ShenandoahPhaseTimings::Phase    _phase;
 108   const ShenandoahPhaseTimings::ParPhase _par_phase;
 109 public:
 110   ShenandoahVMRoot(OopStorage* storage,
 111           ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase);
 112 
 113   template <typename Closure>
 114   void oops_do(Closure* cl, uint worker_id);
 115 };
 116 
 117 template <bool CONCURRENT>
 118 class ShenandoahWeakRoot : public ShenandoahVMRoot<CONCURRENT> {
 119 public:
 120   ShenandoahWeakRoot(OopStorage* storage,
 121           ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase);
 122 };
 123 
 124 template <>
 125 class ShenandoahWeakRoot<false /*concurrent*/> {
 126 private:
 127   OopStorage::ParState<false /*concurrent*/, false /*is_const*/> _itr;
 128   const ShenandoahPhaseTimings::Phase    _phase;
 129   const ShenandoahPhaseTimings::ParPhase _par_phase;
 130 
 131 public:
 132   ShenandoahWeakRoot(OopStorage* storage,
 133           ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase);
 134 
 135   template <typename IsAliveClosure, typename KeepAliveClosure>
 136   void weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id);
 137 };
 138 
 139 template <bool CONCURRENT>
 140 class ShenandoahWeakRoots {
 141 private:
 142   ShenandoahWeakRoot<CONCURRENT>  _jni_roots;
 143   ShenandoahWeakRoot<CONCURRENT>  _string_table_roots;
 144   ShenandoahWeakRoot<CONCURRENT>  _resolved_method_table_roots;
 145   ShenandoahWeakRoot<CONCURRENT>  _vm_roots;
 146 
 147 public:
 148   ShenandoahWeakRoots();
 149   ~ShenandoahWeakRoots();
 150 
 151   template <typename Closure>
 152   void oops_do(Closure* cl, uint worker_id);
 153 };
 154 
 155 template <>
 156 class ShenandoahWeakRoots<false /*concurrent */> {
 157 private:
 158   ShenandoahWeakRoot<false /*concurrent*/>  _jni_roots;
 159   ShenandoahWeakRoot<false /*concurrent*/>  _string_table_roots;
 160   ShenandoahWeakRoot<false /*concurrent*/>  _resolved_method_table_roots;
 161   ShenandoahWeakRoot<false /*concurrent*/>  _vm_roots;
 162 public:
 163   ShenandoahWeakRoots(ShenandoahPhaseTimings::Phase phase);
 164 
 165   template <typename Closure>
 166   void oops_do(Closure* cl, uint worker_id);
 167 
 168   template <typename IsAliveClosure, typename KeepAliveClosure>
 169   void weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id);
 170 };
 171 
 172 template <bool CONCURRENT>
 173 class ShenandoahVMRoots {
 174 private:
 175   ShenandoahVMRoot<CONCURRENT>    _jni_handle_roots;
 176   ShenandoahVMRoot<CONCURRENT>    _vm_global_roots;
 177 
 178 public:
 179   ShenandoahVMRoots(ShenandoahPhaseTimings::Phase phase);
 180 
 181   template <typename T>
 182   void oops_do(T* cl, uint worker_id);
 183 };
 184 
 185 class ShenandoahThreadRoots {
 186 private:
 187   ShenandoahPhaseTimings::Phase _phase;
 188   const bool _is_par;
 189 public:
 190   ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par);
 191   ~ShenandoahThreadRoots();
 192 
 193   void oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id);
 194   void threads_do(ThreadClosure* tc, uint worker_id);
 195 };
 196 
 197 class ShenandoahStringDedupRoots {
 198 private:
 199   ShenandoahPhaseTimings::Phase _phase;
 200 public:
 201   ShenandoahStringDedupRoots(ShenandoahPhaseTimings::Phase phase);
 202   ~ShenandoahStringDedupRoots();
 203 
 204   void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
 205 };
 206 
 207 class ShenandoahConcurrentStringDedupRoots {
 208 private:
 209   ShenandoahPhaseTimings::Phase _phase;
 210 
 211 public:
 212   ShenandoahConcurrentStringDedupRoots(ShenandoahPhaseTimings::Phase phase);
 213   ~ShenandoahConcurrentStringDedupRoots();
 214 
 215   void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
 216 };
 217 
 218 class ShenandoahCodeCacheRoots {
 219 private:
 220   ShenandoahPhaseTimings::Phase _phase;
 221   ShenandoahCodeRootsIterator   _coderoots_iterator;
 222 public:
 223   ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase);
 224   ~ShenandoahCodeCacheRoots();
 225 
 226   void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
 227 };
 228 
 229 template <bool CONCURRENT, bool SINGLE_THREADED>
 230 class ShenandoahClassLoaderDataRoots {
 231 private:
 232   ShenandoahSharedSemaphore     _semaphore;
 233   ShenandoahPhaseTimings::Phase _phase;
 234 
 235   static uint worker_count(uint n_workers) {
 236     // Limit concurrency a bit, otherwise it wastes resources when workers are tripping
 237     // over each other. This also leaves free workers to process other parts of the root
 238     // set, while admitted workers are busy with doing the CLDG walk.
 239     return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2));
 240   }
 241 
 242 public:
 243   ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers);
 244   ~ShenandoahClassLoaderDataRoots();
 245 
 246   void always_strong_cld_do(CLDClosure* clds, uint worker_id);
 247   void cld_do(CLDClosure* clds, uint worker_id);
 248 };
 249 
 250 class ShenandoahRootProcessor : public StackObj {
 251 private:
 252   ShenandoahHeap* const               _heap;
 253   const ShenandoahPhaseTimings::Phase _phase;
 254   const ShenandoahGCWorkerPhase       _worker_phase;
 255 public:
 256   ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase);
 257 
 258   ShenandoahHeap* heap() const { return _heap; }
 259 };
 260 
 261 class ShenandoahRootScanner : public ShenandoahRootProcessor {
 262 private:
 263   ShenandoahSerialRoots                                     _serial_roots;
 264   ShenandoahThreadRoots                                     _thread_roots;
 265 
 266 public:
 267   ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 268   ~ShenandoahRootScanner();
 269 
 270   // Apply oops, clds and blobs to all strongly reachable roots in the system,
 271   // during class unloading cycle
 272   void strong_roots_do(uint worker_id, OopClosure* cl);
 273   void strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
 274 
 275   // Apply oops, clds and blobs to all strongly reachable roots and weakly reachable
 276   // roots when class unloading is disabled during this cycle
 277   void roots_do(uint worker_id, OopClosure* cl);
 278   void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
 279 };
 280 
 281 template <bool CONCURRENT>
 282 class ShenandoahConcurrentRootScanner {
 283 private:
 284   ShenandoahVMRoots<CONCURRENT>            _vm_roots;
 285   ShenandoahClassLoaderDataRoots<CONCURRENT, false /* single-threaded*/>
 286                                            _cld_roots;
 287   ShenandoahConcurrentStringDedupRoots     _dedup_roots;
 288   ShenandoahNMethodTableSnapshot*          _codecache_snapshot;
 289   ShenandoahPhaseTimings::Phase            _phase;
 290 
 291 public:
 292   ShenandoahConcurrentRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 293   ~ShenandoahConcurrentRootScanner();
 294 
 295   void oops_do(OopClosure* oops, uint worker_id);
 296 };
 297 
 298 // This scanner is only for SH::object_iteration() and only supports single-threaded
 299 // root scanning
 300 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
 301 private:
 302   ShenandoahSerialRoots                                    _serial_roots;
 303   ShenandoahThreadRoots                                    _thread_roots;
 304   ShenandoahVMRoots<false /*concurrent*/>                  _vm_roots;
 305   ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
 306                                                            _cld_roots;
 307   ShenandoahSerialWeakRoots                                _serial_weak_roots;
 308   ShenandoahWeakRoots<false /*concurrent*/>                _weak_roots;
 309   ShenandoahConcurrentStringDedupRoots                     _dedup_roots;
 310   ShenandoahCodeCacheRoots                                 _code_roots;
 311 
 312 public:
 313   ShenandoahHeapIterationRootScanner();
 314 
 315   void roots_do(OopClosure* cl);
 316 };
 317 
 318 // Evacuate all roots at a safepoint
 319 class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
 320 private:
 321   ShenandoahSerialRoots                                     _serial_roots;
 322   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
 323   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
 324                                                             _cld_roots;
 325   ShenandoahThreadRoots                                     _thread_roots;
 326   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
 327   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
 328   ShenandoahStringDedupRoots                                _dedup_roots;
 329   ShenandoahCodeCacheRoots                                  _code_roots;
 330   bool                                                      _stw_roots_processing;
 331   bool                                                      _stw_class_unloading;
 332 public:
 333   ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase,
 334                           bool stw_roots_processing, bool stw_class_unloading);
 335 
 336   void roots_do(uint worker_id, OopClosure* oops);
 337 };
 338 
 339 // Update all roots at a safepoint
 340 class ShenandoahRootUpdater : public ShenandoahRootProcessor {
 341 private:
 342   ShenandoahSerialRoots                                     _serial_roots;
 343   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
 344   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
 345                                                             _cld_roots;
 346   ShenandoahThreadRoots                                     _thread_roots;
 347   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
 348   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
 349   ShenandoahStringDedupRoots                                _dedup_roots;
 350   ShenandoahCodeCacheRoots                                  _code_roots;
 351 
 352 public:
 353   ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 354 
 355   template<typename IsAlive, typename KeepAlive>
 356   void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
 357 };
 358 
 359 // Adjuster all roots at a safepoint during full gc
 360 class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
 361 private:
 362   ShenandoahSerialRoots                                     _serial_roots;
 363   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
 364   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
 365                                                             _cld_roots;
 366   ShenandoahThreadRoots                                     _thread_roots;
 367   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
 368   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
 369   ShenandoahStringDedupRoots                                _dedup_roots;
 370   ShenandoahCodeCacheRoots                                  _code_roots;
 371 
 372 public:
 373   ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 374 
 375   void roots_do(uint worker_id, OopClosure* oops);
 376 };
 377 
 378 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP