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/oopStorageParState.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 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(); 149 ~ShenandoahWeakRoots(); 150 151 template <typename Closure> 152 void oops_do(Closure* cl, uint worker_id); 153 }; 154 155 template <> 156 class ShenandoahWeakRoots<false /*concurrent */> { 157 private: 158 ShenandoahWeakRoot<false /*concurrent*/> _jni_roots; 159 ShenandoahWeakRoot<false /*concurrent*/> _string_table_roots; 160 ShenandoahWeakRoot<false /*concurrent*/> _resolved_method_table_roots; 161 ShenandoahWeakRoot<false /*concurrent*/> _vm_roots; 162 public: 163 ShenandoahWeakRoots(ShenandoahPhaseTimings::Phase phase); 164 165 template <typename Closure> 166 void oops_do(Closure* cl, uint worker_id); 167 168 template <typename IsAliveClosure, typename KeepAliveClosure> 169 void weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id); 170 }; 171 172 template <bool CONCURRENT> 173 class ShenandoahVMRoots { 174 private: 175 ShenandoahVMRoot<CONCURRENT> _jni_handle_roots; 176 ShenandoahVMRoot<CONCURRENT> _vm_global_roots; 177 178 public: 179 ShenandoahVMRoots(ShenandoahPhaseTimings::Phase phase); 180 181 template <typename T> 182 void oops_do(T* cl, uint worker_id); 183 }; 184 185 class ShenandoahThreadRoots { 186 private: 187 ShenandoahPhaseTimings::Phase _phase; 188 const bool _is_par; 189 public: 190 ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par); 191 ~ShenandoahThreadRoots(); 192 193 void oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id); 194 void threads_do(ThreadClosure* tc, uint worker_id); 195 }; 196 197 class ShenandoahStringDedupRoots { 198 private: 199 ShenandoahPhaseTimings::Phase _phase; 200 public: 201 ShenandoahStringDedupRoots(ShenandoahPhaseTimings::Phase phase); 202 ~ShenandoahStringDedupRoots(); 203 204 void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id); 205 }; 206 207 class ShenandoahConcurrentStringDedupRoots { 208 private: 209 ShenandoahPhaseTimings::Phase _phase; 210 211 public: 212 ShenandoahConcurrentStringDedupRoots(ShenandoahPhaseTimings::Phase phase); 213 ~ShenandoahConcurrentStringDedupRoots(); 214 215 void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id); 216 }; 217 218 class ShenandoahCodeCacheRoots { 219 private: 220 ShenandoahPhaseTimings::Phase _phase; 221 ShenandoahCodeRootsIterator _coderoots_iterator; 222 public: 223 ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase); 224 ~ShenandoahCodeCacheRoots(); 225 226 void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id); 227 }; 228 229 template <bool CONCURRENT, bool SINGLE_THREADED> 230 class ShenandoahClassLoaderDataRoots { 231 private: 232 ShenandoahSharedSemaphore _semaphore; 233 ShenandoahPhaseTimings::Phase _phase; 234 235 static uint worker_count(uint n_workers) { 236 // Limit concurrency a bit, otherwise it wastes resources when workers are tripping 237 // over each other. This also leaves free workers to process other parts of the root 238 // set, while admitted workers are busy with doing the CLDG walk. 239 return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2)); 240 } 241 242 public: 243 ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers); 244 ~ShenandoahClassLoaderDataRoots(); 245 246 void always_strong_cld_do(CLDClosure* clds, uint worker_id); 247 void cld_do(CLDClosure* clds, uint worker_id); 248 }; 249 250 class ShenandoahRootProcessor : public StackObj { 251 private: 252 ShenandoahHeap* const _heap; 253 const ShenandoahPhaseTimings::Phase _phase; 254 const ShenandoahGCWorkerPhase _worker_phase; 255 public: 256 ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase); 257 258 ShenandoahHeap* heap() const { return _heap; } 259 }; 260 261 class ShenandoahRootScanner : public ShenandoahRootProcessor { 262 private: 263 ShenandoahSerialRoots _serial_roots; 264 ShenandoahThreadRoots _thread_roots; 265 266 public: 267 ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); 268 ~ShenandoahRootScanner(); 269 270 // Apply oops, clds and blobs to all strongly reachable roots in the system, 271 // during class unloading cycle 272 void strong_roots_do(uint worker_id, OopClosure* cl); 273 void strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL); 274 275 // Apply oops, clds and blobs to all strongly reachable roots and weakly reachable 276 // roots when class unloading is disabled during this cycle 277 void roots_do(uint worker_id, OopClosure* cl); 278 void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL); 279 }; 280 281 template <bool CONCURRENT> 282 class ShenandoahConcurrentRootScanner { 283 private: 284 ShenandoahVMRoots<CONCURRENT> _vm_roots; 285 ShenandoahClassLoaderDataRoots<CONCURRENT, false /* single-threaded*/> 286 _cld_roots; 287 ShenandoahConcurrentStringDedupRoots _dedup_roots; 288 ShenandoahNMethodTableSnapshot* _codecache_snapshot; 289 ShenandoahPhaseTimings::Phase _phase; 290 291 public: 292 ShenandoahConcurrentRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); 293 ~ShenandoahConcurrentRootScanner(); 294 295 void oops_do(OopClosure* oops, uint worker_id); 296 }; 297 298 // This scanner is only for SH::object_iteration() and only supports single-threaded 299 // root scanning 300 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor { 301 private: 302 ShenandoahSerialRoots _serial_roots; 303 ShenandoahThreadRoots _thread_roots; 304 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 305 ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/> 306 _cld_roots; 307 ShenandoahSerialWeakRoots _serial_weak_roots; 308 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 309 ShenandoahConcurrentStringDedupRoots _dedup_roots; 310 ShenandoahCodeCacheRoots _code_roots; 311 312 public: 313 ShenandoahHeapIterationRootScanner(); 314 315 void roots_do(OopClosure* cl); 316 }; 317 318 // Evacuate all roots at a safepoint 319 class ShenandoahRootEvacuator : 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 _code_roots; 330 bool _stw_roots_processing; 331 bool _stw_class_unloading; 332 public: 333 ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, 334 bool stw_roots_processing, bool stw_class_unloading); 335 336 void roots_do(uint worker_id, OopClosure* oops); 337 }; 338 339 // Update all roots at a safepoint 340 class ShenandoahRootUpdater : public ShenandoahRootProcessor { 341 private: 342 ShenandoahSerialRoots _serial_roots; 343 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 344 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 345 _cld_roots; 346 ShenandoahThreadRoots _thread_roots; 347 ShenandoahSerialWeakRoots _serial_weak_roots; 348 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 349 ShenandoahStringDedupRoots _dedup_roots; 350 ShenandoahCodeCacheRoots _code_roots; 351 352 public: 353 ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase); 354 355 template<typename IsAlive, typename KeepAlive> 356 void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive); 357 }; 358 359 // Adjuster all roots at a safepoint during full gc 360 class ShenandoahRootAdjuster : public ShenandoahRootProcessor { 361 private: 362 ShenandoahSerialRoots _serial_roots; 363 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 364 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 365 _cld_roots; 366 ShenandoahThreadRoots _thread_roots; 367 ShenandoahSerialWeakRoots _serial_weak_roots; 368 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 369 ShenandoahStringDedupRoots _dedup_roots; 370 ShenandoahCodeCacheRoots _code_roots; 371 372 public: 373 ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase); 374 375 void roots_do(uint worker_id, OopClosure* oops); 376 }; 377 378 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP