1 /*
2  * Copyright (c) 2015, 2021, 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 template <bool CONCURRENT>
38 class ShenandoahVMWeakRoots {
39 private:
40   OopStorageSetWeakParState<CONCURRENT, false /* is_const */> _weak_roots;
41   ShenandoahPhaseTimings::Phase                               _phase;
42 
43 public:
44   ShenandoahVMWeakRoots(ShenandoahPhaseTimings::Phase phase);
45 
46   template <typename T>
47   void oops_do(T* cl, uint worker_id);
48 
49   template <typename IsAlive, typename KeepAlive>
50   void weak_oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id);
51 
52   void report_num_dead();
53 };
54 
55 template <bool CONCURRENT>
56 class ShenandoahVMRoots {
57 private:
58   OopStorageSetStrongParState<CONCURRENT, false /* is_const */> _strong_roots;
59   ShenandoahPhaseTimings::Phase                                 _phase;
60 
61 public:
62   ShenandoahVMRoots(ShenandoahPhaseTimings::Phase phase);
63 
64   template <typename T>
65   void oops_do(T* cl, uint worker_id);
66 };
67 
68 class ShenandoahJavaThreadsIterator {
69 private:
70   static const uint _chunks_per_worker = 16; // educated guess
71 
72   ThreadsListHandle             _threads;
73   uint const                    _length;
74   uint const                    _stride;
75   volatile uint                 _claimed;
76   ShenandoahPhaseTimings::Phase _phase;
77 
78   uint claim();
79 public:
80   ShenandoahJavaThreadsIterator(ShenandoahPhaseTimings::Phase phase, uint n_workers);
81   void threads_do(ThreadClosure* cl, uint worker_id);
82 
length() const83   uint length() const { return _length; }
thread_at(uint index) const84   Thread* thread_at(uint index) const { return _threads.thread_at(index); }
85 };
86 
87 class ShenandoahThreadRoots {
88 private:
89   ShenandoahPhaseTimings::Phase _phase;
90   const bool _is_par;
91 public:
92   ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par);
93   ~ShenandoahThreadRoots();
94 
95   void oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id);
96   void threads_do(ThreadClosure* tc, uint worker_id);
97 };
98 
99 class ShenandoahCodeCacheRoots {
100 private:
101   ShenandoahPhaseTimings::Phase _phase;
102   ShenandoahCodeRootsIterator   _coderoots_iterator;
103 public:
104   ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase);
105   ~ShenandoahCodeCacheRoots();
106 
107   void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
108 };
109 
110 template <bool CONCURRENT, bool SINGLE_THREADED>
111 class ShenandoahClassLoaderDataRoots {
112 private:
113   ShenandoahSharedSemaphore     _semaphore;
114   ShenandoahPhaseTimings::Phase _phase;
115 
worker_count(uint n_workers)116   static uint worker_count(uint n_workers) {
117     if (SINGLE_THREADED) return 1u;
118 
119     // Limit concurrency a bit, otherwise it wastes resources when workers are tripping
120     // over each other. This also leaves free workers to process other parts of the root
121     // set, while admitted workers are busy with doing the CLDG walk.
122     return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2));
123   }
124 
125 public:
126   ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers);
127   ~ShenandoahClassLoaderDataRoots();
128 
129   void always_strong_cld_do(CLDClosure* clds, uint worker_id);
130   void cld_do(CLDClosure* clds, uint worker_id);
131 
132 private:
133   typedef void (*CldDo)(CLDClosure*);
134   void cld_do_impl(CldDo f, CLDClosure* clds, uint worker_id);
135 };
136 
137 class ShenandoahRootProcessor : public StackObj {
138 private:
139   ShenandoahHeap* const               _heap;
140   const ShenandoahPhaseTimings::Phase _phase;
141   const ShenandoahGCWorkerPhase       _worker_phase;
142 public:
143   ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase);
144 
heap() const145   ShenandoahHeap* heap() const { return _heap; }
146 };
147 
148 class ShenandoahRootScanner : public ShenandoahRootProcessor {
149 private:
150   ShenandoahThreadRoots                                     _thread_roots;
151 
152 public:
153   ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
154   ~ShenandoahRootScanner();
155 
156   void roots_do(uint worker_id, OopClosure* cl);
157 
158 private:
159   void roots_do(uint worker_id, OopClosure* oops, CodeBlobClosure* code, ThreadClosure* tc = NULL);
160 };
161 
162 // STW root scanner
163 class ShenandoahSTWRootScanner : public ShenandoahRootProcessor {
164 private:
165   ShenandoahThreadRoots           _thread_roots;
166   ShenandoahCodeCacheRoots        _code_roots;
167   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /* single_thread*/>
168                                   _cld_roots;
169   ShenandoahVMRoots<false /*concurrent*/>
170                                   _vm_roots;
171   const bool                      _unload_classes;
172 public:
173   ShenandoahSTWRootScanner(ShenandoahPhaseTimings::Phase phase);
174 
175   template <typename T>
176   void roots_do(T* oops, uint worker_id);
177 };
178 
179 class ShenandoahConcurrentRootScanner : public ShenandoahRootProcessor {
180 private:
181   ShenandoahJavaThreadsIterator             _java_threads;
182   ShenandoahVMRoots<true /*concurrent*/>    _vm_roots;
183   ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /* single-threaded*/>
184                                            _cld_roots;
185   ShenandoahNMethodTableSnapshot*          _codecache_snapshot;
186   ShenandoahPhaseTimings::Phase            _phase;
187 
188 public:
189   ShenandoahConcurrentRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
190   ~ShenandoahConcurrentRootScanner();
191 
192   void roots_do(OopClosure* oops, uint worker_id);
193 
194 private:
195   void update_tlab_stats();
196 };
197 
198 // This scanner is only for SH::object_iteration() and only supports single-threaded
199 // root scanning
200 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
201 private:
202   ShenandoahThreadRoots                                    _thread_roots;
203   ShenandoahVMRoots<false /*concurrent*/>                  _vm_roots;
204   ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
205                                                            _cld_roots;
206   ShenandoahVMWeakRoots<false /*concurrent*/>              _weak_roots;
207   ShenandoahCodeCacheRoots                                 _code_roots;
208 
209 public:
210   ShenandoahHeapIterationRootScanner();
211 
212   void roots_do(OopClosure* cl);
213 };
214 
215 // Update all roots at a safepoint
216 class ShenandoahRootUpdater : public ShenandoahRootProcessor {
217 private:
218   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
219   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
220                                                             _cld_roots;
221   ShenandoahThreadRoots                                     _thread_roots;
222   ShenandoahVMWeakRoots<false /*concurrent*/>               _weak_roots;
223   ShenandoahCodeCacheRoots                                  _code_roots;
224 
225 public:
226   ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase);
227 
228   template<typename IsAlive, typename KeepAlive>
229   void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
230 };
231 
232 // Adjuster all roots at a safepoint during full gc
233 class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
234 private:
235   ShenandoahVMRoots<false /*concurrent*/>                   _vm_roots;
236   ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
237                                                             _cld_roots;
238   ShenandoahThreadRoots                                     _thread_roots;
239   ShenandoahVMWeakRoots<false /*concurrent*/>               _weak_roots;
240   ShenandoahCodeCacheRoots                                  _code_roots;
241 
242 public:
243   ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
244 
245   void roots_do(uint worker_id, OopClosure* oops);
246 };
247 
248 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP
249