1 /* 2 * Copyright (c) 2015, 2020, Red Hat, Inc. All rights reserved. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP 25 #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP 26 27 #include "code/codeCache.hpp" 28 #include "gc/shared/oopStorageParState.hpp" 29 #include "gc/shenandoah/shenandoahCodeRoots.hpp" 30 #include "gc/shenandoah/shenandoahHeap.hpp" 31 #include "gc/shenandoah/shenandoahPhaseTimings.hpp" 32 #include "gc/shenandoah/shenandoahSharedVariables.hpp" 33 #include "gc/shenandoah/shenandoahUtils.hpp" 34 #include "memory/iterator.hpp" 35 36 class ShenandoahSerialRoot { 37 public: 38 typedef void (*OopsDo)(OopClosure*); 39 private: 40 ShenandoahSharedFlag _claimed; 41 const OopsDo _oops_do; 42 const ShenandoahPhaseTimings::Phase _phase; 43 const ShenandoahPhaseTimings::ParPhase _par_phase; 44 45 public: 46 ShenandoahSerialRoot(OopsDo oops_do, 47 ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase); 48 void oops_do(OopClosure* cl, uint worker_id); 49 }; 50 51 class ShenandoahSerialRoots { 52 private: 53 ShenandoahSerialRoot _universe_root; 54 ShenandoahSerialRoot _object_synchronizer_root; 55 ShenandoahSerialRoot _management_root; 56 ShenandoahSerialRoot _system_dictionary_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(ShenandoahPhaseTimings::Phase phase); 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 template <typename ITR> 207 class ShenandoahCodeCacheRoots { 208 private: 209 ShenandoahPhaseTimings::Phase _phase; 210 ITR _coderoots_iterator; 211 public: 212 ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase); 213 ~ShenandoahCodeCacheRoots(); 214 215 void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id); 216 }; 217 218 template <bool CONCURRENT, bool SINGLE_THREADED> 219 class ShenandoahClassLoaderDataRoots { 220 private: 221 ShenandoahSharedSemaphore _semaphore; 222 ShenandoahPhaseTimings::Phase _phase; 223 224 static uint worker_count(uint n_workers) { 225 // Limit concurrency a bit, otherwise it wastes resources when workers are tripping 226 // over each other. This also leaves free workers to process other parts of the root 227 // set, while admitted workers are busy with doing the CLDG walk. 228 return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2)); 229 } 230 231 public: 232 ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers); 233 ~ShenandoahClassLoaderDataRoots(); 234 235 void always_strong_cld_do(CLDClosure* clds, uint worker_id); 236 void cld_do(CLDClosure* clds, uint worker_id); 237 }; 238 239 class ShenandoahRootProcessor : public StackObj { 240 private: 241 ShenandoahHeap* const _heap; 242 const ShenandoahPhaseTimings::Phase _phase; 243 const ShenandoahGCWorkerPhase _worker_phase; 244 public: 245 ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase); 246 247 ShenandoahHeap* heap() const { return _heap; } 248 }; 249 250 template <typename ITR> 251 class ShenandoahRootScanner : public ShenandoahRootProcessor { 252 private: 253 ShenandoahSerialRoots _serial_roots; 254 ShenandoahThreadRoots _thread_roots; 255 ShenandoahCodeCacheRoots<ITR> _code_roots; 256 ShenandoahVMRoots<false /*concurrent*/ > _vm_roots; 257 ShenandoahStringDedupRoots _dedup_roots; 258 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 259 _cld_roots; 260 public: 261 ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); 262 263 // Apply oops, clds and blobs to all strongly reachable roots in the system, 264 // during class unloading cycle 265 void strong_roots_do(uint worker_id, OopClosure* cl); 266 void strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL); 267 268 // Apply oops, clds and blobs to all strongly reachable roots and weakly reachable 269 // roots when class unloading is disabled during this cycle 270 void roots_do(uint worker_id, OopClosure* cl); 271 void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL); 272 }; 273 274 typedef ShenandoahRootScanner<ShenandoahAllCodeRootsIterator> ShenandoahAllRootScanner; 275 typedef ShenandoahRootScanner<ShenandoahCsetCodeRootsIterator> ShenandoahCSetRootScanner; 276 277 // This scanner is only for SH::object_iteration() and only supports single-threaded 278 // root scanning 279 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor { 280 private: 281 ShenandoahSerialRoots _serial_roots; 282 ShenandoahThreadRoots _thread_roots; 283 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 284 ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/> 285 _cld_roots; 286 ShenandoahSerialWeakRoots _serial_weak_roots; 287 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 288 ShenandoahStringDedupRoots _dedup_roots; 289 ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots; 290 291 public: 292 ShenandoahHeapIterationRootScanner(); 293 294 void roots_do(OopClosure* cl); 295 }; 296 297 // Evacuate all roots at a safepoint 298 class ShenandoahRootEvacuator : public ShenandoahRootProcessor { 299 private: 300 ShenandoahSerialRoots _serial_roots; 301 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 302 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 303 _cld_roots; 304 ShenandoahThreadRoots _thread_roots; 305 ShenandoahSerialWeakRoots _serial_weak_roots; 306 ShenandoahWeakRoots<false /*concurrent*/> _weak_roots; 307 ShenandoahStringDedupRoots _dedup_roots; 308 ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots; 309 bool _stw_roots_processing; 310 bool _stw_class_unloading; 311 public: 312 ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, 313 bool stw_roots_processing, bool stw_class_unloading); 314 315 void roots_do(uint worker_id, OopClosure* oops); 316 }; 317 318 // Update all roots at a safepoint 319 class ShenandoahRootUpdater : 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<ShenandoahAllCodeRootsIterator> _code_roots; 330 331 public: 332 ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase); 333 334 template<typename IsAlive, typename KeepAlive> 335 void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive); 336 }; 337 338 // Adjuster all roots at a safepoint during full gc 339 class ShenandoahRootAdjuster : 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<ShenandoahAllCodeRootsIterator> _code_roots; 350 351 public: 352 ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase); 353 354 void roots_do(uint worker_id, OopClosure* oops); 355 }; 356 357 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP