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 
 150   template <typename Closure>
 151   void oops_do(Closure* cl, uint worker_id);
 152 };
 153 
 154 template <>
 155 class ShenandoahWeakRoots<false /*concurrent */> {
 156 private:
 157   ShenandoahWeakRoot<false /*concurrent*/>  _jni_roots;
 158   ShenandoahWeakRoot<false /*concurrent*/>  _string_table_roots;
 159   ShenandoahWeakRoot<false /*concurrent*/>  _resolved_method_table_roots;
 160   ShenandoahWeakRoot<false /*concurrent*/>  _vm_roots;
 161 public:
 162   ShenandoahWeakRoots(ShenandoahPhaseTimings::Phase phase);
 163 
 164   template <typename Closure>
 165   void oops_do(Closure* cl, uint worker_id);
 166 
 167   template <typename IsAliveClosure, typename KeepAliveClosure>
 168   void weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id);
 169 };
 170 
 171 template <bool CONCURRENT>
 172 class ShenandoahVMRoots {
 173 private:
 174   ShenandoahVMRoot<CONCURRENT>    _jni_handle_roots;
 175   ShenandoahVMRoot<CONCURRENT>    _vm_global_roots;
 176 
 177 public:
 178   ShenandoahVMRoots(ShenandoahPhaseTimings::Phase phase);
 179 
 180   template <typename T>
 181   void oops_do(T* cl, uint worker_id);
 182 };
 183 
 184 class ShenandoahThreadRoots {
 185 private:
 186   ShenandoahPhaseTimings::Phase _phase;
 187   const bool _is_par;
 188 public:
 189   ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par);
 190   ~ShenandoahThreadRoots();
 191 
 192   void oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id);
 193   void threads_do(ThreadClosure* tc, uint worker_id);
 194 };
 195 
 196 class ShenandoahStringDedupRoots {
 197 private:
 198   ShenandoahPhaseTimings::Phase _phase;
 199 public:
 200   ShenandoahStringDedupRoots(ShenandoahPhaseTimings::Phase phase);
 201   ~ShenandoahStringDedupRoots();
 202 
 203   void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
 204 };
 205 
 206 class ShenandoahConcurrentStringDedupRoots {
 207 private:
 208   ShenandoahPhaseTimings::Phase _phase;
 209 
 210 public:
 211   ShenandoahConcurrentStringDedupRoots(ShenandoahPhaseTimings::Phase phase);
 212   ~ShenandoahConcurrentStringDedupRoots();
 213 
 214   void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
 215 };
 216 
 217 class ShenandoahCodeCacheRoots {
 218 private:
 219   ShenandoahPhaseTimings::Phase _phase;
 220   ShenandoahCodeRootsIterator   _coderoots_iterator;
 221 public:
 222   ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase);
 223   ~ShenandoahCodeCacheRoots();
 224 
 225   void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
 226 };
 227 
 228 template <bool CONCURRENT, bool SINGLE_THREADED>
 229 class ShenandoahClassLoaderDataRoots {
 230 private:
 231   ShenandoahSharedSemaphore     _semaphore;
 232   ShenandoahPhaseTimings::Phase _phase;
 233 
 234   static uint worker_count(uint n_workers) {
 235     // Limit concurrency a bit, otherwise it wastes resources when workers are tripping
 236     // over each other. This also leaves free workers to process other parts of the root
 237     // set, while admitted workers are busy with doing the CLDG walk.
 238     return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2));
 239   }
 240 
 241 public:
 242   ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers);
 243   ~ShenandoahClassLoaderDataRoots();
 244 
 245   void always_strong_cld_do(CLDClosure* clds, uint worker_id);
 246   void cld_do(CLDClosure* clds, uint worker_id);
 247 };
 248 
 249 class ShenandoahRootProcessor : public StackObj {
 250 private:
 251   ShenandoahHeap* const               _heap;
 252   const ShenandoahPhaseTimings::Phase _phase;
 253   const ShenandoahGCWorkerPhase       _worker_phase;
 254 public:
 255   ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase);
 256 
 257   ShenandoahHeap* heap() const { return _heap; }
 258 };
 259 
 260 class ShenandoahRootScanner : public ShenandoahRootProcessor {
 261 private:
 262   ShenandoahSerialRoots                                     _serial_roots;
 263   ShenandoahThreadRoots                                     _thread_roots;
 264 
 265 public:
 266   ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 267   ~ShenandoahRootScanner();
 268 
 269   // Apply oops, clds and blobs to all strongly reachable roots in the system,
 270   // during class unloading cycle
 271   void strong_roots_do(uint worker_id, OopClosure* cl);
 272   void strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
 273 
 274   // Apply oops, clds and blobs to all strongly reachable roots and weakly reachable
 275   // roots when class unloading is disabled during this cycle
 276   void roots_do(uint worker_id, OopClosure* cl);
 277   void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
 278 };
 279 
 280 template <bool CONCURRENT>
 281 class ShenandoahConcurrentRootScanner {
 282 private:
 283   ShenandoahVMRoots<CONCURRENT>            _vm_roots;
 284   ShenandoahClassLoaderDataRoots<CONCURRENT, false /* single-threaded*/>
 285                                            _cld_roots;
 286   ShenandoahConcurrentStringDedupRoots     _dedup_roots;
 287   ShenandoahNMethodTableSnapshot*          _codecache_snapshot;
 288   ShenandoahPhaseTimings::Phase            _phase;
 289 
 290 public:
 291   ShenandoahConcurrentRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 292   ~ShenandoahConcurrentRootScanner();
 293 
 294   void oops_do(OopClosure* oops, uint worker_id);
 295 };
 296 
 297 // This scanner is only for SH::object_iteration() and only supports single-threaded
 298 // root scanning
 299 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
 300 private:
 301   ShenandoahSerialRoots                                    _serial_roots;
 302   ShenandoahThreadRoots                                    _thread_roots;
 303   ShenandoahVMRoots<false /*concurrent*/>                  _vm_roots;
 304   ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
 305                                                            _cld_roots;
 306   ShenandoahSerialWeakRoots                                _serial_weak_roots;
 307   ShenandoahWeakRoots<false /*concurrent*/>                _weak_roots;
 308   ShenandoahConcurrentStringDedupRoots                     _dedup_roots;
 309   ShenandoahCodeCacheRoots                                 _code_roots;
 310 
 311 public:
 312   ShenandoahHeapIterationRootScanner();
 313 
 314   void roots_do(OopClosure* cl);
 315 };
 316 
 317 // Evacuate all roots at a safepoint
 318 class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
 319 private:
 320   ShenandoahSerialRoots                                     _serial_roots;
 321   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
 322   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
 323                                                             _cld_roots;
 324   ShenandoahThreadRoots                                     _thread_roots;
 325   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
 326   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
 327   ShenandoahStringDedupRoots                                _dedup_roots;
 328   ShenandoahCodeCacheRoots                                  _code_roots;
 329   bool                                                      _stw_roots_processing;
 330   bool                                                      _stw_class_unloading;
 331 public:
 332   ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase,
 333                           bool stw_roots_processing, bool stw_class_unloading);
 334 
 335   void roots_do(uint worker_id, OopClosure* oops);
 336 };
 337 
 338 // Update all roots at a safepoint
 339 class ShenandoahRootUpdater : public ShenandoahRootProcessor {
 340 private:
 341   ShenandoahSerialRoots                                     _serial_roots;
 342   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
 343   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
 344                                                             _cld_roots;
 345   ShenandoahThreadRoots                                     _thread_roots;
 346   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
 347   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
 348   ShenandoahStringDedupRoots                                _dedup_roots;
 349   ShenandoahCodeCacheRoots                                  _code_roots;
 350 
 351 public:
 352   ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 353 
 354   template<typename IsAlive, typename KeepAlive>
 355   void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
 356 };
 357 
 358 // Adjuster all roots at a safepoint during full gc
 359 class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
 360 private:
 361   ShenandoahSerialRoots                                     _serial_roots;
 362   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
 363   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
 364                                                             _cld_roots;
 365   ShenandoahThreadRoots                                     _thread_roots;
 366   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
 367   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
 368   ShenandoahStringDedupRoots                                _dedup_roots;
 369   ShenandoahCodeCacheRoots                                  _code_roots;
 370 
 371 public:
 372   ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 373 
 374   void roots_do(uint worker_id, OopClosure* oops);
 375 };
 376 
 377 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP