1 /* 2 * Copyright (c) 2015, 2018, 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 #include "precompiled.hpp" 25 26 #include "classfile/classLoaderData.hpp" 27 #include "classfile/stringTable.hpp" 28 #include "classfile/systemDictionary.hpp" 29 #include "code/codeCache.hpp" 30 #include "gc/shenandoah/shenandoahClosures.inline.hpp" 31 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" 32 #include "gc/shenandoah/shenandoahHeap.inline.hpp" 33 #include "gc/shenandoah/shenandoahHeuristics.hpp" 34 #include "gc/shenandoah/shenandoahPhaseTimings.hpp" 35 #include "gc/shenandoah/shenandoahStringDedup.hpp" 36 #include "gc/shenandoah/shenandoahTimingTracker.hpp" 37 #include "gc/shenandoah/shenandoahVMOperations.hpp" 38 #include "gc/shared/weakProcessor.hpp" 39 #include "memory/allocation.inline.hpp" 40 #include "memory/iterator.hpp" 41 #include "memory/resourceArea.hpp" 42 #include "runtime/thread.hpp" 43 #include "services/management.hpp" 44 45 ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases phase) : 46 _claimed(false), _oops_do(oops_do), _phase(phase) { 47 } 48 49 void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) { 50 if (!_claimed && Atomic::cmpxchg(true, &_claimed, false) == false) { 51 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 52 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); 53 _oops_do(cl); 54 } 55 } 56 57 ShenandoahSerialRoots::ShenandoahSerialRoots() : 58 _universe_root(&ShenandoahSerialRoots::universe_oops_do, ShenandoahPhaseTimings::UniverseRoots), 59 _object_synchronizer_root(&ObjectSynchronizer::oops_do, ShenandoahPhaseTimings::ObjectSynchronizerRoots), 60 _management_root(&Management::oops_do, ShenandoahPhaseTimings::ManagementRoots), 61 _system_dictionary_root(&SystemDictionary::oops_do, ShenandoahPhaseTimings::SystemDictionaryRoots), 62 _jvmti_root(&JvmtiExport::oops_do, ShenandoahPhaseTimings::JVMTIRoots) { 63 } 64 65 void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) { 66 _universe_root.oops_do(cl, worker_id); 67 _object_synchronizer_root.oops_do(cl, worker_id); 68 _management_root.oops_do(cl, worker_id); 69 _system_dictionary_root.oops_do(cl, worker_id); 70 _jvmti_root.oops_do(cl, worker_id); 71 } 72 73 ShenandoahJNIHandleRoots::ShenandoahJNIHandleRoots() : 74 ShenandoahSerialRoot(&JNIHandles::oops_do, ShenandoahPhaseTimings::JNIRoots) { 75 } 76 77 ShenandoahThreadRoots::ShenandoahThreadRoots(bool is_par) : _is_par(is_par) { 78 Threads::change_thread_claim_parity(); 79 } 80 81 void ShenandoahThreadRoots::oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id) { 82 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 83 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id); 84 ResourceMark rm; 85 Threads::possibly_parallel_oops_do(_is_par, oops_cl, code_cl); 86 } 87 88 void ShenandoahThreadRoots::threads_do(ThreadClosure* tc, uint worker_id) { 89 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 90 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id); 91 ResourceMark rm; 92 Threads::possibly_parallel_threads_do(_is_par, tc); 93 } 94 95 ShenandoahThreadRoots::~ShenandoahThreadRoots() { 96 Threads::assert_all_threads_claimed(); 97 } 98 99 ShenandoahWeakRoots::ShenandoahWeakRoots(uint n_workers) : 100 _par_state_string(StringTable::weak_storage()), 101 _claimed(false) { 102 } 103 104 ShenandoahWeakRoots::~ShenandoahWeakRoots() { 105 } 106 107 ShenandoahStringDedupRoots::ShenandoahStringDedupRoots() { 108 if (ShenandoahStringDedup::is_enabled()) { 109 StringDedup::gc_prologue(false); 110 } 111 } 112 113 ShenandoahStringDedupRoots::~ShenandoahStringDedupRoots() { 114 if (ShenandoahStringDedup::is_enabled()) { 115 StringDedup::gc_epilogue(); 116 } 117 } 118 119 void ShenandoahStringDedupRoots::oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) { 120 if (ShenandoahStringDedup::is_enabled()) { 121 ShenandoahStringDedup::parallel_oops_do(is_alive, keep_alive, worker_id); 122 } 123 } 124 125 ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) : 126 _heap(ShenandoahHeap::heap()), 127 _phase(phase) { 128 assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); 129 _heap->phase_timings()->record_workers_start(_phase); 130 } 131 132 ShenandoahRootProcessor::~ShenandoahRootProcessor() { 133 assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); 134 _heap->phase_timings()->record_workers_end(_phase); 135 } 136 137 ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) : 138 ShenandoahRootProcessor(phase), 139 _thread_roots(n_workers > 1), 140 _weak_roots(n_workers) { 141 } 142 143 void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) { 144 MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations); 145 CLDToOopClosure clds(oops); 146 CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds; 147 148 AlwaysTrueClosure always_true; 149 150 _serial_roots.oops_do(oops, worker_id); 151 _jni_roots.oops_do(oops, worker_id); 152 153 _thread_roots.oops_do(oops, NULL, worker_id); 154 _cld_roots.cld_do(&clds, worker_id); 155 _code_roots.code_blobs_do(&blobsCl, worker_id); 156 157 _weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id); 158 _dedup_roots.oops_do(&always_true, oops, worker_id); 159 } 160 161 ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache) : 162 ShenandoahRootProcessor(phase), 163 _thread_roots(n_workers > 1), 164 _weak_roots(n_workers), 165 _update_code_cache(update_code_cache) { 166 } 167 168 ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) : 169 ShenandoahRootProcessor(phase), 170 _thread_roots(n_workers > 1), 171 _weak_roots(n_workers) { 172 assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Full GC only"); 173 } 174 175 void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) { 176 CodeBlobToOopClosure adjust_code_closure(oops, CodeBlobToOopClosure::FixRelocations); 177 CLDToOopClosure adjust_cld_closure(oops); 178 AlwaysTrueClosure always_true; 179 180 _serial_roots.oops_do(oops, worker_id); 181 _jni_roots.oops_do(oops, worker_id); 182 183 _thread_roots.oops_do(oops, NULL, worker_id); 184 _cld_roots.cld_do(&adjust_cld_closure, worker_id); 185 _code_roots.code_blobs_do(&adjust_code_closure, worker_id); 186 187 _weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id); 188 _dedup_roots.oops_do(&always_true, oops, worker_id); 189 } 190 191 ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() : 192 ShenandoahRootProcessor(ShenandoahPhaseTimings::_num_phases), 193 _thread_roots(false /*is par*/), 194 _weak_roots(1) { 195 } 196 197 void ShenandoahHeapIterationRootScanner::roots_do(OopClosure* oops) { 198 assert(Thread::current()->is_VM_thread(), "Only by VM thread"); 199 // Must use _claim_none to avoid interfering with concurrent CLDG iteration 200 CLDToOopClosure clds(oops, false); 201 MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations); 202 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL); 203 AlwaysTrueClosure always_true; 204 ResourceMark rm; 205 206 _serial_roots.oops_do(oops, 0); 207 _jni_roots.oops_do(oops, 0); 208 _cld_roots.cld_do(&clds, 0); 209 _thread_roots.threads_do(&tc_cl, 0); 210 _code_roots.code_blobs_do(&code, 0); 211 212 _weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, 0); 213 _dedup_roots.oops_do(&always_true, oops, 0); 214 } 215 216 void ShenandoahHeapIterationRootScanner::strong_roots_do(OopClosure* oops) { 217 assert(Thread::current()->is_VM_thread(), "Only by VM thread"); 218 // Must use _claim_none to avoid interfering with concurrent CLDG iteration 219 CLDToOopClosure clds(oops, false); 220 MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations); 221 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL); 222 ResourceMark rm; 223 224 _serial_roots.oops_do(oops, 0); 225 _jni_roots.oops_do(oops, 0); 226 _cld_roots.always_strong_cld_do(&clds, 0); 227 _thread_roots.threads_do(&tc_cl, 0); 228 }