1 /* 2 * Copyright (c) 2019, 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_INLINE_HPP 25 #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP 26 27 #include "classfile/classLoaderDataGraph.hpp" 28 #include "classfile/stringTable.hpp" 29 #include "classfile/systemDictionary.hpp" 30 #include "gc/shared/oopStorageParState.inline.hpp" 31 #include "gc/shenandoah/shenandoahHeuristics.hpp" 32 #include "gc/shenandoah/shenandoahRootProcessor.hpp" 33 #include "gc/shenandoah/shenandoahTimingTracker.hpp" 34 #include "gc/shenandoah/shenandoahUtils.hpp" 35 #include "memory/resourceArea.hpp" 36 #include "prims/resolvedMethodTable.hpp" 37 #include "runtime/safepoint.hpp" 38 39 template <bool CONCURRENT> 40 inline ShenandoahVMRoot<CONCURRENT>::ShenandoahVMRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) : 41 _itr(storage), _phase(phase) { 42 } 43 44 template <bool CONCURRENT> 45 template <typename Closure> 46 inline void ShenandoahVMRoot<CONCURRENT>::oops_do(Closure* cl, uint worker_id) { 47 if (CONCURRENT) { 48 _itr.oops_do(cl); 49 } else { 50 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 51 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); 52 _itr.oops_do(cl); 53 } 54 } 55 56 template <bool CONCURRENT> 57 inline ShenandoahWeakRoot<CONCURRENT>::ShenandoahWeakRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) : 58 ShenandoahVMRoot<CONCURRENT>(storage, phase) { 59 } 60 61 inline ShenandoahWeakRoot<false>::ShenandoahWeakRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) : 62 _itr(storage), _phase(phase) { 63 } 64 65 template <typename IsAliveClosure, typename KeepAliveClosure> 66 void ShenandoahWeakRoot<false /* concurrent */>::weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id) { 67 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 68 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); 69 _itr.weak_oops_do(is_alive, keep_alive); 70 } 71 72 template <bool CONCURRENT> 73 ShenandoahWeakRoots<CONCURRENT>::ShenandoahWeakRoots() : 74 _jni_roots(OopStorageSet::jni_weak(), ShenandoahPhaseTimings::JNIWeakRoots), 75 _string_table_roots(OopStorageSet::string_table_weak(), ShenandoahPhaseTimings::StringTableRoots), 76 _resolved_method_table_roots(OopStorageSet::resolved_method_table_weak(), ShenandoahPhaseTimings::ResolvedMethodTableRoots), 77 _vm_roots(OopStorageSet::vm_weak(), ShenandoahPhaseTimings::VMWeakRoots) { 78 } 79 80 template <bool CONCURRENT> 81 template <typename Closure> 82 void ShenandoahWeakRoots<CONCURRENT>::oops_do(Closure* cl, uint worker_id) { 83 _jni_roots.oops_do(cl, worker_id); 84 _string_table_roots.oops_do(cl, worker_id); 85 _resolved_method_table_roots.oops_do(cl, worker_id); 86 _vm_roots.oops_do(cl, worker_id); 87 } 88 89 inline ShenandoahWeakRoots<false /* concurrent */>::ShenandoahWeakRoots() : 90 _jni_roots(OopStorageSet::jni_weak(), ShenandoahPhaseTimings::JNIWeakRoots), 91 _string_table_roots(OopStorageSet::string_table_weak(), ShenandoahPhaseTimings::StringTableRoots), 92 _resolved_method_table_roots(OopStorageSet::resolved_method_table_weak(), ShenandoahPhaseTimings::ResolvedMethodTableRoots), 93 _vm_roots(OopStorageSet::vm_weak(), ShenandoahPhaseTimings::VMWeakRoots) { 94 } 95 96 template <typename IsAliveClosure, typename KeepAliveClosure> 97 void ShenandoahWeakRoots<false /* concurrent*/>::weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id) { 98 _jni_roots.weak_oops_do(is_alive, keep_alive, worker_id); 99 _string_table_roots.weak_oops_do(is_alive, keep_alive, worker_id); 100 _resolved_method_table_roots.weak_oops_do(is_alive, keep_alive, worker_id); 101 _vm_roots.weak_oops_do(is_alive, keep_alive, worker_id); 102 } 103 104 template <typename Closure> 105 void ShenandoahWeakRoots<false /* concurrent */>::oops_do(Closure* cl, uint worker_id) { 106 AlwaysTrueClosure always_true; 107 weak_oops_do<AlwaysTrueClosure, Closure>(&always_true, cl, worker_id); 108 } 109 110 template <bool CONCURRENT> 111 ShenandoahVMRoots<CONCURRENT>::ShenandoahVMRoots() : 112 _jni_handle_roots(OopStorageSet::jni_global(), ShenandoahPhaseTimings::JNIRoots), 113 _vm_global_roots(OopStorageSet::vm_global(), ShenandoahPhaseTimings::VMGlobalRoots) { 114 } 115 116 template <bool CONCURRENT> 117 template <typename T> 118 void ShenandoahVMRoots<CONCURRENT>::oops_do(T* cl, uint worker_id) { 119 _jni_handle_roots.oops_do(cl, worker_id); 120 _vm_global_roots.oops_do(cl, worker_id); 121 } 122 123 template <bool CONCURRENT, bool SINGLE_THREADED> 124 ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::ShenandoahClassLoaderDataRoots() { 125 if (!SINGLE_THREADED) { 126 ClassLoaderDataGraph::clear_claimed_marks(); 127 } 128 if (CONCURRENT) { 129 ClassLoaderDataGraph_lock->lock(); 130 } 131 } 132 133 template <bool CONCURRENT, bool SINGLE_THREADED> 134 ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::~ShenandoahClassLoaderDataRoots() { 135 if (CONCURRENT) { 136 ClassLoaderDataGraph_lock->unlock(); 137 } 138 } 139 140 141 template <bool CONCURRENT, bool SINGLE_THREADED> 142 void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::always_strong_cld_do(CLDClosure* clds, uint worker_id) { 143 if (SINGLE_THREADED) { 144 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 145 assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread"); 146 ClassLoaderDataGraph::always_strong_cld_do(clds); 147 } else if (CONCURRENT) { 148 ClassLoaderDataGraph::always_strong_cld_do(clds); 149 } else { 150 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 151 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); 152 ClassLoaderDataGraph::always_strong_cld_do(clds); 153 } 154 } 155 156 template <bool CONCURRENT, bool SINGLE_THREADED> 157 void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do(CLDClosure* clds, uint worker_id) { 158 if (SINGLE_THREADED) { 159 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 160 assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread"); 161 ClassLoaderDataGraph::cld_do(clds); 162 } else if (CONCURRENT) { 163 ClassLoaderDataGraph::cld_do(clds); 164 } else { 165 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 166 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); 167 ClassLoaderDataGraph::cld_do(clds); 168 } 169 } 170 171 template <typename ITR> 172 ShenandoahCodeCacheRoots<ITR>::ShenandoahCodeCacheRoots() { 173 nmethod::oops_do_marking_prologue(); 174 } 175 176 template <typename ITR> 177 void ShenandoahCodeCacheRoots<ITR>::code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id) { 178 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 179 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); 180 _coderoots_iterator.possibly_parallel_blobs_do(blob_cl); 181 } 182 183 template <typename ITR> 184 ShenandoahCodeCacheRoots<ITR>::~ShenandoahCodeCacheRoots() { 185 nmethod::oops_do_marking_epilogue(); 186 } 187 188 class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure { 189 private: 190 OopClosure* _f; 191 CodeBlobClosure* _cf; 192 ThreadClosure* _thread_cl; 193 public: 194 ShenandoahParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf, ThreadClosure* thread_cl) : 195 _f(f), _cf(cf), _thread_cl(thread_cl) {} 196 197 void do_thread(Thread* t) { 198 if (_thread_cl != NULL) { 199 _thread_cl->do_thread(t); 200 } 201 t->oops_do(_f, _cf); 202 } 203 }; 204 205 template <typename ITR> 206 ShenandoahRootScanner<ITR>::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) : 207 ShenandoahRootProcessor(phase), 208 _thread_roots(n_workers > 1) { 209 } 210 211 template <typename ITR> 212 void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops) { 213 CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong); 214 MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations); 215 roots_do(worker_id, oops, &clds_cl, &blobs_cl); 216 } 217 218 template <typename ITR> 219 void ShenandoahRootScanner<ITR>::strong_roots_do(uint worker_id, OopClosure* oops) { 220 CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong); 221 MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations); 222 strong_roots_do(worker_id, oops, &clds_cl, &blobs_cl); 223 } 224 225 template <typename ITR> 226 void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) { 227 assert(!ShenandoahSafepoint::is_at_shenandoah_safepoint() || 228 !ShenandoahHeap::heap()->unload_classes() || 229 ShenandoahHeap::heap()->is_traversal_mode(), 230 "Expect class unloading or traversal when Shenandoah cycle is running"); 231 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); 232 ResourceMark rm; 233 234 _serial_roots.oops_do(oops, worker_id); 235 _vm_roots.oops_do(oops, worker_id); 236 237 if (clds != NULL) { 238 _cld_roots.cld_do(clds, worker_id); 239 } else { 240 assert(ShenandoahHeap::heap()->is_concurrent_traversal_in_progress(), "Only possible with traversal GC"); 241 } 242 243 _thread_roots.threads_do(&tc_cl, worker_id); 244 245 // With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here, 246 // and instead do that in concurrent phase under the relevant lock. This saves init mark 247 // pause time. 248 if (code != NULL && !ShenandoahConcurrentScanCodeRoots) { 249 _code_roots.code_blobs_do(code, worker_id); 250 } 251 } 252 253 template <typename ITR> 254 void ShenandoahRootScanner<ITR>::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) { 255 assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading"); 256 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); 257 ResourceMark rm; 258 259 _serial_roots.oops_do(oops, worker_id); 260 _vm_roots.oops_do(oops, worker_id); 261 _cld_roots.always_strong_cld_do(clds, worker_id); 262 _thread_roots.threads_do(&tc_cl, worker_id); 263 } 264 265 template <typename IsAlive, typename KeepAlive> 266 void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive) { 267 CodeBlobToOopClosure update_blobs(keep_alive, CodeBlobToOopClosure::FixRelocations); 268 CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong); 269 270 _serial_roots.oops_do(keep_alive, worker_id); 271 _vm_roots.oops_do(keep_alive, worker_id); 272 273 _thread_roots.oops_do(keep_alive, NULL, worker_id); 274 _cld_roots.cld_do(&clds, worker_id); 275 _code_roots.code_blobs_do(&update_blobs, worker_id); 276 277 _serial_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id); 278 _weak_roots.weak_oops_do(is_alive, keep_alive, worker_id); 279 _dedup_roots.oops_do(is_alive, keep_alive, worker_id); 280 } 281 282 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP