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 _system_dictionary_root; 58 ShenandoahSerialRoot _jvmti_root; 59 public: 60 ShenandoahSerialRoots(ShenandoahPhaseTimings::Phase phase); 61 void oops_do(OopClosure* cl, uint worker_id); 62 }; 63 64 class ShenandoahWeakSerialRoot { 65 typedef void (*WeakOopsDo)(BoolObjectClosure*, OopClosure*); 66 private: 67 ShenandoahSharedFlag _claimed; 68 const WeakOopsDo _weak_oops_do; 69 const ShenandoahPhaseTimings::Phase _phase; 70 const ShenandoahPhaseTimings::ParPhase _par_phase; 71 72 public: 73 ShenandoahWeakSerialRoot(WeakOopsDo oops_do, 74 ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase); 75 void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id); 76 }; 77 78 #if INCLUDE_JVMTI 79 class ShenandoahJVMTIWeakRoot : public ShenandoahWeakSerialRoot { 80 public: 81 ShenandoahJVMTIWeakRoot(ShenandoahPhaseTimings::Phase phase); 82 }; 83 #endif // INCLUDE_JVMTI 84 85 #if INCLUDE_JFR 86 class ShenandoahJFRWeakRoot : public ShenandoahWeakSerialRoot { 87 public: 88 ShenandoahJFRWeakRoot(ShenandoahPhaseTimings::Phase phase); 89 }; 90 #endif // INCLUDE_JFR 91 92 class ShenandoahSerialWeakRoots { 93 private: 94 JVMTI_ONLY(ShenandoahJVMTIWeakRoot _jvmti_weak_roots;) 95 JFR_ONLY(ShenandoahJFRWeakRoot _jfr_weak_roots;) 96 public: 97 ShenandoahSerialWeakRoots(ShenandoahPhaseTimings::Phase phase) : 98 JVMTI_ONLY(_jvmti_weak_roots(phase)) 99 JFR_ONLY(JVMTI_ONLY(COMMA)_jfr_weak_roots(phase)) {}; 100 void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id); 101 void weak_oops_do(OopClosure* cl, uint worker_id); 102 }; 103 104 template <bool CONCURRENT> 105 class ShenandoahVMRoot { 106 private: 107 OopStorage::ParState<CONCURRENT, false /* is_const */> _itr; 108 const ShenandoahPhaseTimings::Phase _phase; 109 const ShenandoahPhaseTimings::ParPhase _par_phase; 110 public: 111 ShenandoahVMRoot(OopStorage* storage, 112 ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase); 113 114 template <typename Closure> 115 void oops_do(Closure* cl, uint worker_id); 116 }; 117 118 template <bool CONCURRENT> 119 class ShenandoahWeakRoot : public ShenandoahVMRoot<CONCURRENT> { 120 public: 121 ShenandoahWeakRoot(OopStorage* storage, 122 ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase); 123 }; 124 125 template <> 126 class ShenandoahWeakRoot<false /*concurrent*/> { 127 private: 128 OopStorage::ParState<false /*concurrent*/, false /*is_const*/> _itr; 129 const ShenandoahPhaseTimings::Phase _phase; 130 const ShenandoahPhaseTimings::ParPhase _par_phase; 131 132 public: 133 ShenandoahWeakRoot(OopStorage* storage, 134 ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase); 135 136 template <typename IsAliveClosure, typename KeepAliveClosure> 137 void weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id); 138 }; 139 140 template <bool CONCURRENT> 141 class ShenandoahWeakRoots { 142 private: 143 ShenandoahWeakRoot<CONCURRENT> _jni_roots; 144 ShenandoahWeakRoot<CONCURRENT> _string_table_roots; 145 ShenandoahWeakRoot<CONCURRENT> _resolved_method_table_roots; 146 ShenandoahWeakRoot<CONCURRENT> _vm_roots; 147 148 public: 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 public: 209 ShenandoahConcurrentStringDedupRoots(); 210 ~ShenandoahConcurrentStringDedupRoots(); 211 212 void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id); 213 }; 214 215 class ShenandoahCodeCacheRoots { 216 private: 217 ShenandoahPhaseTimings::Phase _phase; 218 ShenandoahCodeRootsIterator _coderoots_iterator; 219 public: 220 ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase); 221 ~ShenandoahCodeCacheRoots(); 222 223 void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id); 224 }; 225 226 template <bool CONCURRENT, bool SINGLE_THREADED> 227 class ShenandoahClassLoaderDataRoots { 228 private: 229 ShenandoahSharedSemaphore _semaphore; 230 ShenandoahPhaseTimings::Phase _phase; 231 232 static uint worker_count(uint n_workers) { 233 // Limit concurrency a bit, otherwise it wastes resources when workers are tripping 234 // over each other. This also leaves free workers to process other parts of the root 235 // set, while admitted workers are busy with doing the CLDG walk. 236 return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2)); 237 } 238 239 public: 240 ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers); 241 ~ShenandoahClassLoaderDataRoots(); 242 243 void always_strong_cld_do(CLDClosure* clds, uint worker_id); 244 void cld_do(CLDClosure* clds, uint worker_id); 245 }; 246 247 class ShenandoahRootProcessor : public StackObj { 248 private: 249 ShenandoahHeap* const _heap; 250 const ShenandoahPhaseTimings::Phase _phase; 251 const ShenandoahGCWorkerPhase _worker_phase; 252 public: 253 ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase); 254 255 ShenandoahHeap* heap() const { return _heap; } 256 }; 257 258 class ShenandoahRootScanner : public ShenandoahRootProcessor { 259 private: 260 ShenandoahSerialRoots _serial_roots; 261 ShenandoahThreadRoots _thread_roots; 262 ShenandoahCodeCacheRoots _code_roots; 263 ShenandoahVMRoots<false /*concurrent*/ > _vm_roots; 264 ShenandoahStringDedupRoots _dedup_roots; 265 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 266 _cld_roots; 267 public: 268 ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); 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 // This scanner is only for SH::object_iteration() and only supports single-threaded 282 // root scanning 283 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor { 284 private: 285 ShenandoahSerialRoots _serial_roots; 286 ShenandoahThreadRoots _thread_roots; 287 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 288 ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/> 289 _cld_roots; 290 ShenandoahSerialWeakRoots _serial_weak_roots; 291 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 292 ShenandoahConcurrentStringDedupRoots _dedup_roots; 293 ShenandoahCodeCacheRoots _code_roots; 294 295 public: 296 ShenandoahHeapIterationRootScanner(); 297 298 void roots_do(OopClosure* cl); 299 }; 300 301 // Evacuate all roots at a safepoint 302 class ShenandoahRootEvacuator : public ShenandoahRootProcessor { 303 private: 304 ShenandoahSerialRoots _serial_roots; 305 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 306 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 307 _cld_roots; 308 ShenandoahThreadRoots _thread_roots; 309 ShenandoahSerialWeakRoots _serial_weak_roots; 310 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 311 ShenandoahStringDedupRoots _dedup_roots; 312 ShenandoahCodeCacheRoots _code_roots; 313 bool _stw_roots_processing; 314 bool _stw_class_unloading; 315 public: 316 ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, 317 bool stw_roots_processing, bool stw_class_unloading); 318 319 void roots_do(uint worker_id, OopClosure* oops); 320 }; 321 322 // Update all roots at a safepoint 323 class ShenandoahRootUpdater : public ShenandoahRootProcessor { 324 private: 325 ShenandoahSerialRoots _serial_roots; 326 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 327 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 328 _cld_roots; 329 ShenandoahThreadRoots _thread_roots; 330 ShenandoahSerialWeakRoots _serial_weak_roots; 331 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 332 ShenandoahStringDedupRoots _dedup_roots; 333 ShenandoahCodeCacheRoots _code_roots; 334 335 public: 336 ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase); 337 338 template<typename IsAlive, typename KeepAlive> 339 void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive); 340 }; 341 342 // Adjuster all roots at a safepoint during full gc 343 class ShenandoahRootAdjuster : public ShenandoahRootProcessor { 344 private: 345 ShenandoahSerialRoots _serial_roots; 346 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 347 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 348 _cld_roots; 349 ShenandoahThreadRoots _thread_roots; 350 ShenandoahSerialWeakRoots _serial_weak_roots; 351 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 352 ShenandoahStringDedupRoots _dedup_roots; 353 ShenandoahCodeCacheRoots _code_roots; 354 355 public: 356 ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase); 357 358 void roots_do(uint worker_id, OopClosure* oops); 359 }; 360 361 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP