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