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