1 /*
   2  * Copyright (c) 2015, 2020, Red Hat, Inc. All rights reserved.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP
  25 #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP
  26 
  27 #include "code/codeCache.hpp"
  28 #include "gc/shared/oopStorageParState.hpp"
  29 #include "gc/shenandoah/shenandoahCodeRoots.hpp"
  30 #include "gc/shenandoah/shenandoahHeap.hpp"
  31 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
  32 #include "gc/shenandoah/shenandoahSharedVariables.hpp"
  33 #include "gc/shenandoah/shenandoahUtils.hpp"
  34 #include "memory/iterator.hpp"
  35 
  36 class ShenandoahSerialRoot {
  37 public:
  38   typedef void (*OopsDo)(OopClosure*);
  39 private:
  40   ShenandoahSharedFlag                   _claimed;
  41   const OopsDo                           _oops_do;
  42   const ShenandoahPhaseTimings::Phase    _phase;
  43   const ShenandoahPhaseTimings::ParPhase _par_phase;
  44 
  45 public:
  46   ShenandoahSerialRoot(OopsDo oops_do,
  47           ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase);
  48   void oops_do(OopClosure* cl, uint worker_id);
  49 };
  50 
  51 class ShenandoahSerialRoots {
  52 private:
  53   ShenandoahSerialRoot  _universe_root;
  54   ShenandoahSerialRoot  _object_synchronizer_root;
  55   ShenandoahSerialRoot  _management_root;
  56   ShenandoahSerialRoot  _system_dictionary_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(ShenandoahPhaseTimings::Phase phase);
 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 template <typename ITR>
 207 class ShenandoahCodeCacheRoots {
 208 private:
 209   ShenandoahPhaseTimings::Phase _phase;
 210   ITR _coderoots_iterator;
 211 public:
 212   ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase);
 213   ~ShenandoahCodeCacheRoots();
 214 
 215   void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
 216 };
 217 
 218 template <bool CONCURRENT, bool SINGLE_THREADED>
 219 class ShenandoahClassLoaderDataRoots {
 220 private:
 221   ShenandoahSharedSemaphore     _semaphore;
 222   ShenandoahPhaseTimings::Phase _phase;
 223 
 224   static uint worker_count(uint n_workers) {
 225     // Limit concurrency a bit, otherwise it wastes resources when workers are tripping
 226     // over each other. This also leaves free workers to process other parts of the root
 227     // set, while admitted workers are busy with doing the CLDG walk.
 228     return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2));
 229   }
 230 
 231 public:
 232   ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers);
 233   ~ShenandoahClassLoaderDataRoots();
 234 
 235   void always_strong_cld_do(CLDClosure* clds, uint worker_id);
 236   void cld_do(CLDClosure* clds, uint worker_id);
 237 };
 238 
 239 class ShenandoahRootProcessor : public StackObj {
 240 private:
 241   ShenandoahHeap* const               _heap;
 242   const ShenandoahPhaseTimings::Phase _phase;
 243   const ShenandoahGCWorkerPhase       _worker_phase;
 244 public:
 245   ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase);
 246 
 247   ShenandoahHeap* heap() const { return _heap; }
 248 };
 249 
 250 template <typename ITR>
 251 class ShenandoahRootScanner : public ShenandoahRootProcessor {
 252 private:
 253   ShenandoahSerialRoots                                     _serial_roots;
 254   ShenandoahThreadRoots                                     _thread_roots;
 255   ShenandoahCodeCacheRoots<ITR>                             _code_roots;
 256   ShenandoahVMRoots<false /*concurrent*/ >                  _vm_roots;
 257   ShenandoahStringDedupRoots                                _dedup_roots;
 258   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
 259                                                             _cld_roots;
 260 public:
 261   ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 262 
 263   // Apply oops, clds and blobs to all strongly reachable roots in the system,
 264   // during class unloading cycle
 265   void strong_roots_do(uint worker_id, OopClosure* cl);
 266   void strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
 267 
 268   // Apply oops, clds and blobs to all strongly reachable roots and weakly reachable
 269   // roots when class unloading is disabled during this cycle
 270   void roots_do(uint worker_id, OopClosure* cl);
 271   void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
 272 };
 273 
 274 typedef ShenandoahRootScanner<ShenandoahAllCodeRootsIterator> ShenandoahAllRootScanner;
 275 typedef ShenandoahRootScanner<ShenandoahCsetCodeRootsIterator> ShenandoahCSetRootScanner;
 276 
 277 // This scanner is only for SH::object_iteration() and only supports single-threaded
 278 // root scanning
 279 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
 280 private:
 281   ShenandoahSerialRoots                                    _serial_roots;
 282   ShenandoahThreadRoots                                    _thread_roots;
 283   ShenandoahVMRoots<false /*concurrent*/>                  _vm_roots;
 284   ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
 285                                                            _cld_roots;
 286   ShenandoahSerialWeakRoots                                _serial_weak_roots;
 287   ShenandoahWeakRoots<false /*concurrent*/>                _weak_roots;
 288   ShenandoahStringDedupRoots                               _dedup_roots;
 289   ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
 290 
 291 public:
 292   ShenandoahHeapIterationRootScanner();
 293 
 294   void roots_do(OopClosure* cl);
 295 };
 296 
 297 // Evacuate all roots at a safepoint
 298 class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
 299 private:
 300   ShenandoahSerialRoots                                     _serial_roots;
 301   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
 302   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
 303                                                             _cld_roots;
 304   ShenandoahThreadRoots                                     _thread_roots;
 305   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
 306   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
 307   ShenandoahStringDedupRoots                                _dedup_roots;
 308   ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator>  _code_roots;
 309   bool                                                      _stw_roots_processing;
 310   bool                                                      _stw_class_unloading;
 311 public:
 312   ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase,
 313                           bool stw_roots_processing, bool stw_class_unloading);
 314 
 315   void roots_do(uint worker_id, OopClosure* oops);
 316 };
 317 
 318 // Update all roots at a safepoint
 319 class ShenandoahRootUpdater : 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<ShenandoahAllCodeRootsIterator>  _code_roots;
 330 
 331 public:
 332   ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 333 
 334   template<typename IsAlive, typename KeepAlive>
 335   void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
 336 };
 337 
 338 // Adjuster all roots at a safepoint during full gc
 339 class ShenandoahRootAdjuster : 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<ShenandoahAllCodeRootsIterator>  _code_roots;
 350 
 351 public:
 352   ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 353 
 354   void roots_do(uint worker_id, OopClosure* oops);
 355 };
 356 
 357 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP