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/oopStorageSetParState.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 ShenandoahVMWeakRoots {
105 private:
106   OopStorageSetWeakParState<CONCURRENT, false /* is_const */> _weak_roots;
107   ShenandoahPhaseTimings::Phase                               _phase;
108 
109 public:
110   ShenandoahVMWeakRoots(ShenandoahPhaseTimings::Phase phase);
111 
112   template <typename T>
113   void oops_do(T* cl, uint worker_id);
114 
115   template <typename IsAlive, typename KeepAlive>
116   void weak_oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id);
117 
118   void notify();
119 };
120 
121 template <bool CONCURRENT>
122 class ShenandoahVMRoots {
123 private:
124   OopStorageSetStrongParState<CONCURRENT, false /* is_const */> _strong_roots;
125   ShenandoahPhaseTimings::Phase                                 _phase;
126 
127 public:
128   ShenandoahVMRoots(ShenandoahPhaseTimings::Phase phase);
129 
130   template <typename T>
131   void oops_do(T* cl, uint worker_id);
132 };
133 
134 class ShenandoahThreadRoots {
135 private:
136   ShenandoahPhaseTimings::Phase _phase;
137   const bool _is_par;
138 public:
139   ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par);
140   ~ShenandoahThreadRoots();
141 
142   void oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id);
143   void threads_do(ThreadClosure* tc, uint worker_id);
144 };
145 
146 class ShenandoahStringDedupRoots {
147 private:
148   ShenandoahPhaseTimings::Phase _phase;
149 public:
150   ShenandoahStringDedupRoots(ShenandoahPhaseTimings::Phase phase);
151   ~ShenandoahStringDedupRoots();
152 
153   void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
154 };
155 
156 class ShenandoahConcurrentStringDedupRoots {
157 private:
158   ShenandoahPhaseTimings::Phase _phase;
159 
160 public:
161   ShenandoahConcurrentStringDedupRoots(ShenandoahPhaseTimings::Phase phase);
162   ~ShenandoahConcurrentStringDedupRoots();
163 
164   void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
165 };
166 
167 class ShenandoahCodeCacheRoots {
168 private:
169   ShenandoahPhaseTimings::Phase _phase;
170   ShenandoahCodeRootsIterator   _coderoots_iterator;
171 public:
172   ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase);
173   ~ShenandoahCodeCacheRoots();
174 
175   void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
176 };
177 
178 template <bool CONCURRENT, bool SINGLE_THREADED>
179 class ShenandoahClassLoaderDataRoots {
180 private:
181   ShenandoahSharedSemaphore     _semaphore;
182   ShenandoahPhaseTimings::Phase _phase;
183 
184   static uint worker_count(uint n_workers) {
185     // Limit concurrency a bit, otherwise it wastes resources when workers are tripping
186     // over each other. This also leaves free workers to process other parts of the root
187     // set, while admitted workers are busy with doing the CLDG walk.
188     return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2));
189   }
190 
191 public:
192   ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers);
193   ~ShenandoahClassLoaderDataRoots();
194 
195   void always_strong_cld_do(CLDClosure* clds, uint worker_id);
196   void cld_do(CLDClosure* clds, uint worker_id);
197 };
198 
199 class ShenandoahRootProcessor : public StackObj {
200 private:
201   ShenandoahHeap* const               _heap;
202   const ShenandoahPhaseTimings::Phase _phase;
203   const ShenandoahGCWorkerPhase       _worker_phase;
204 public:
205   ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase);
206 
207   ShenandoahHeap* heap() const { return _heap; }
208 };
209 
210 class ShenandoahRootScanner : public ShenandoahRootProcessor {
211 private:
212   ShenandoahSerialRoots                                     _serial_roots;
213   ShenandoahThreadRoots                                     _thread_roots;
214 
215 public:
216   ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
217   ~ShenandoahRootScanner();
218 
219   // Apply oops, clds and blobs to all strongly reachable roots in the system,
220   // during class unloading cycle
221   void strong_roots_do(uint worker_id, OopClosure* cl);
222   void strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
223 
224   // Apply oops, clds and blobs to all strongly reachable roots and weakly reachable
225   // roots when class unloading is disabled during this cycle
226   void roots_do(uint worker_id, OopClosure* cl);
227   void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
228 };
229 
230 template <bool CONCURRENT>
231 class ShenandoahConcurrentRootScanner {
232 private:
233   ShenandoahVMRoots<CONCURRENT>            _vm_roots;
234   ShenandoahClassLoaderDataRoots<CONCURRENT, false /* single-threaded*/>
235                                            _cld_roots;
236   ShenandoahConcurrentStringDedupRoots     _dedup_roots;
237   ShenandoahNMethodTableSnapshot*          _codecache_snapshot;
238   ShenandoahPhaseTimings::Phase            _phase;
239 
240 public:
241   ShenandoahConcurrentRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
242   ~ShenandoahConcurrentRootScanner();
243 
244   void oops_do(OopClosure* oops, uint worker_id);
245 };
246 
247 // This scanner is only for SH::object_iteration() and only supports single-threaded
248 // root scanning
249 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
250 private:
251   ShenandoahSerialRoots                                    _serial_roots;
252   ShenandoahThreadRoots                                    _thread_roots;
253   ShenandoahVMRoots<false /*concurrent*/>                  _vm_roots;
254   ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
255                                                            _cld_roots;
256   ShenandoahSerialWeakRoots                                _serial_weak_roots;
257   ShenandoahVMWeakRoots<false /*concurrent*/>              _weak_roots;
258   ShenandoahConcurrentStringDedupRoots                     _dedup_roots;
259   ShenandoahCodeCacheRoots                                 _code_roots;
260 
261 public:
262   ShenandoahHeapIterationRootScanner();
263 
264   void roots_do(OopClosure* cl);
265 };
266 
267 // Evacuate all roots at a safepoint
268 class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
269 private:
270   ShenandoahSerialRoots                                     _serial_roots;
271   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
272   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
273                                                             _cld_roots;
274   ShenandoahThreadRoots                                     _thread_roots;
275   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
276   ShenandoahVMWeakRoots<false /*concurrent*/>               _weak_roots;
277   ShenandoahStringDedupRoots                                _dedup_roots;
278   ShenandoahCodeCacheRoots                                  _code_roots;
279   bool                                                      _stw_roots_processing;
280   bool                                                      _stw_class_unloading;
281 public:
282   ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase,
283                           bool stw_roots_processing, bool stw_class_unloading);
284 
285   void roots_do(uint worker_id, OopClosure* oops);
286 };
287 
288 // Update all roots at a safepoint
289 class ShenandoahRootUpdater : public ShenandoahRootProcessor {
290 private:
291   ShenandoahSerialRoots                                     _serial_roots;
292   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
293   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
294                                                             _cld_roots;
295   ShenandoahThreadRoots                                     _thread_roots;
296   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
297   ShenandoahVMWeakRoots<false /*concurrent*/>               _weak_roots;
298   ShenandoahStringDedupRoots                                _dedup_roots;
299   ShenandoahCodeCacheRoots                                  _code_roots;
300 
301 public:
302   ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase);
303 
304   template<typename IsAlive, typename KeepAlive>
305   void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
306 };
307 
308 // Adjuster all roots at a safepoint during full gc
309 class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
310 private:
311   ShenandoahSerialRoots                                     _serial_roots;
312   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
313   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
314                                                             _cld_roots;
315   ShenandoahThreadRoots                                     _thread_roots;
316   ShenandoahSerialWeakRoots                                 _serial_weak_roots;
317   ShenandoahVMWeakRoots<false /*concurrent*/>               _weak_roots;
318   ShenandoahStringDedupRoots                                _dedup_roots;
319   ShenandoahCodeCacheRoots                                  _code_roots;
320 
321 public:
322   ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
323 
324   void roots_do(uint worker_id, OopClosure* oops);
325 };
326 
327 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP