1 /* 2 * Copyright (c) 2015, 2021, 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 template <bool CONCURRENT> 38 class ShenandoahVMWeakRoots { 39 private: 40 OopStorageSetWeakParState<CONCURRENT, false /* is_const */> _weak_roots; 41 ShenandoahPhaseTimings::Phase _phase; 42 43 public: 44 ShenandoahVMWeakRoots(ShenandoahPhaseTimings::Phase phase); 45 46 template <typename T> 47 void oops_do(T* cl, uint worker_id); 48 49 template <typename IsAlive, typename KeepAlive> 50 void weak_oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id); 51 52 void report_num_dead(); 53 }; 54 55 template <bool CONCURRENT> 56 class ShenandoahVMRoots { 57 private: 58 OopStorageSetStrongParState<CONCURRENT, false /* is_const */> _strong_roots; 59 ShenandoahPhaseTimings::Phase _phase; 60 61 public: 62 ShenandoahVMRoots(ShenandoahPhaseTimings::Phase phase); 63 64 template <typename T> 65 void oops_do(T* cl, uint worker_id); 66 }; 67 68 class ShenandoahJavaThreadsIterator { 69 private: 70 static const uint _chunks_per_worker = 16; // educated guess 71 72 ThreadsListHandle _threads; 73 uint const _length; 74 uint const _stride; 75 volatile uint _claimed; 76 ShenandoahPhaseTimings::Phase _phase; 77 78 uint claim(); 79 public: 80 ShenandoahJavaThreadsIterator(ShenandoahPhaseTimings::Phase phase, uint n_workers); 81 void threads_do(ThreadClosure* cl, uint worker_id); 82 length() const83 uint length() const { return _length; } thread_at(uint index) const84 Thread* thread_at(uint index) const { return _threads.thread_at(index); } 85 }; 86 87 class ShenandoahThreadRoots { 88 private: 89 ShenandoahPhaseTimings::Phase _phase; 90 const bool _is_par; 91 public: 92 ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par); 93 ~ShenandoahThreadRoots(); 94 95 void oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id); 96 void threads_do(ThreadClosure* tc, uint worker_id); 97 }; 98 99 class ShenandoahCodeCacheRoots { 100 private: 101 ShenandoahPhaseTimings::Phase _phase; 102 ShenandoahCodeRootsIterator _coderoots_iterator; 103 public: 104 ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase); 105 ~ShenandoahCodeCacheRoots(); 106 107 void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id); 108 }; 109 110 template <bool CONCURRENT, bool SINGLE_THREADED> 111 class ShenandoahClassLoaderDataRoots { 112 private: 113 ShenandoahSharedSemaphore _semaphore; 114 ShenandoahPhaseTimings::Phase _phase; 115 worker_count(uint n_workers)116 static uint worker_count(uint n_workers) { 117 if (SINGLE_THREADED) return 1u; 118 119 // Limit concurrency a bit, otherwise it wastes resources when workers are tripping 120 // over each other. This also leaves free workers to process other parts of the root 121 // set, while admitted workers are busy with doing the CLDG walk. 122 return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2)); 123 } 124 125 public: 126 ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers); 127 ~ShenandoahClassLoaderDataRoots(); 128 129 void always_strong_cld_do(CLDClosure* clds, uint worker_id); 130 void cld_do(CLDClosure* clds, uint worker_id); 131 132 private: 133 typedef void (*CldDo)(CLDClosure*); 134 void cld_do_impl(CldDo f, CLDClosure* clds, uint worker_id); 135 }; 136 137 class ShenandoahRootProcessor : public StackObj { 138 private: 139 ShenandoahHeap* const _heap; 140 const ShenandoahPhaseTimings::Phase _phase; 141 const ShenandoahGCWorkerPhase _worker_phase; 142 public: 143 ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase); 144 heap() const145 ShenandoahHeap* heap() const { return _heap; } 146 }; 147 148 class ShenandoahRootScanner : public ShenandoahRootProcessor { 149 private: 150 ShenandoahThreadRoots _thread_roots; 151 152 public: 153 ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); 154 ~ShenandoahRootScanner(); 155 156 void roots_do(uint worker_id, OopClosure* cl); 157 158 private: 159 void roots_do(uint worker_id, OopClosure* oops, CodeBlobClosure* code, ThreadClosure* tc = NULL); 160 }; 161 162 // STW root scanner 163 class ShenandoahSTWRootScanner : public ShenandoahRootProcessor { 164 private: 165 ShenandoahThreadRoots _thread_roots; 166 ShenandoahCodeCacheRoots _code_roots; 167 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /* single_thread*/> 168 _cld_roots; 169 ShenandoahVMRoots<false /*concurrent*/> 170 _vm_roots; 171 const bool _unload_classes; 172 public: 173 ShenandoahSTWRootScanner(ShenandoahPhaseTimings::Phase phase); 174 175 template <typename T> 176 void roots_do(T* oops, uint worker_id); 177 }; 178 179 class ShenandoahConcurrentRootScanner : public ShenandoahRootProcessor { 180 private: 181 ShenandoahJavaThreadsIterator _java_threads; 182 ShenandoahVMRoots<true /*concurrent*/> _vm_roots; 183 ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /* single-threaded*/> 184 _cld_roots; 185 ShenandoahNMethodTableSnapshot* _codecache_snapshot; 186 ShenandoahPhaseTimings::Phase _phase; 187 188 public: 189 ShenandoahConcurrentRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); 190 ~ShenandoahConcurrentRootScanner(); 191 192 void roots_do(OopClosure* oops, uint worker_id); 193 194 private: 195 void update_tlab_stats(); 196 }; 197 198 // This scanner is only for SH::object_iteration() and only supports single-threaded 199 // root scanning 200 class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor { 201 private: 202 ShenandoahThreadRoots _thread_roots; 203 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 204 ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/> 205 _cld_roots; 206 ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots; 207 ShenandoahCodeCacheRoots _code_roots; 208 209 public: 210 ShenandoahHeapIterationRootScanner(); 211 212 void roots_do(OopClosure* cl); 213 }; 214 215 // Update all roots at a safepoint 216 class ShenandoahRootUpdater : public ShenandoahRootProcessor { 217 private: 218 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 219 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 220 _cld_roots; 221 ShenandoahThreadRoots _thread_roots; 222 ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots; 223 ShenandoahCodeCacheRoots _code_roots; 224 225 public: 226 ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase); 227 228 template<typename IsAlive, typename KeepAlive> 229 void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive); 230 }; 231 232 // Adjuster all roots at a safepoint during full gc 233 class ShenandoahRootAdjuster : public ShenandoahRootProcessor { 234 private: 235 ShenandoahVMRoots<false /*concurrent*/> _vm_roots; 236 ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> 237 _cld_roots; 238 ShenandoahThreadRoots _thread_roots; 239 ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots; 240 ShenandoahCodeCacheRoots _code_roots; 241 242 public: 243 ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase); 244 245 void roots_do(uint worker_id, OopClosure* oops); 246 }; 247 248 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP 249