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