1 /* 2 * Copyright (c) 2015, Red Hat, Inc. and/or its affiliates. 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/stringTable.hpp" 27 #include "classfile/systemDictionary.hpp" 28 #include "code/codeCache.hpp" 29 #include "gc/shenandoah/shenandoahRootProcessor.hpp" 30 #include "gc/shenandoah/shenandoahHeap.hpp" 31 #include "gc/shenandoah/shenandoahBarrierSet.hpp" 32 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" 33 #include "gc/shenandoah/shenandoahPhaseTimes.hpp" 34 #include "memory/allocation.inline.hpp" 35 #include "runtime/fprofiler.hpp" 36 #include "runtime/mutex.hpp" 37 #include "services/management.hpp" 38 39 ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers, 40 ShenandoahCollectorPolicy::TimingPhase phase) : 41 _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)), 42 _srs(n_workers), 43 _phase(phase), 44 _codecache_iterator(CodeCache::parallel_iterator()), 45 _om_iterator(ObjectSynchronizer::parallel_iterator()) 46 { 47 heap->shenandoahPolicy()->record_workers_start(_phase); 48 } 49 50 ShenandoahRootProcessor::~ShenandoahRootProcessor() { 51 delete _process_strong_tasks; 52 ShenandoahHeap::heap()->shenandoahPolicy()->record_workers_end(_phase); 53 } 54 55 void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops, 56 OopClosure* weak_oops, 57 CLDClosure* clds, 58 CodeBlobClosure* blobs, 59 uint worker_id) { 60 61 process_java_roots(oops, clds, NULL, blobs, worker_id); 62 process_vm_roots(oops, NULL, weak_oops, worker_id); 63 64 _process_strong_tasks->all_tasks_completed(n_workers()); 65 } 66 67 void ShenandoahRootProcessor::process_all_roots(OopClosure* oops, 68 OopClosure* weak_oops, 69 CLDClosure* clds, 70 CodeBlobClosure* blobs, 71 uint worker_id) { 72 73 ShenandoahPhaseTimes* phase_times = ShenandoahHeap::heap()->shenandoahPolicy()->phase_times(); 74 process_java_roots(oops, clds, clds, NULL, worker_id); 75 process_vm_roots(oops, oops, weak_oops, worker_id); 76 77 if (blobs != NULL) { 78 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::CodeCacheRoots, worker_id); 79 _codecache_iterator.parallel_blobs_do(blobs); 80 } 81 82 _process_strong_tasks->all_tasks_completed(n_workers()); 83 } 84 85 void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots, 86 CLDClosure* strong_clds, 87 CLDClosure* weak_clds, 88 CodeBlobClosure* strong_code, 89 uint worker_id) 90 { 91 ShenandoahPhaseTimes* phase_times = ShenandoahHeap::heap()->shenandoahPolicy()->phase_times(); 92 // Iterating over the CLDG and the Threads are done early to allow us to 93 // first process the strong CLDs and nmethods and then, after a barrier, 94 // let the thread process the weak CLDs and nmethods. 95 { 96 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::CLDGRoots, worker_id); 97 _cld_iterator.root_cld_do(strong_clds, weak_clds); 98 } 99 100 { 101 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::ThreadRoots, worker_id); 102 bool is_par = n_workers() > 1; 103 ResourceMark rm; 104 Threads::possibly_parallel_oops_do(is_par, strong_roots, strong_code); 105 } 106 } 107 108 void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots, 109 OopClosure* weak_roots, 110 OopClosure* jni_weak_roots, 111 uint worker_id) 112 { 113 ShenandoahPhaseTimes* phase_times = ShenandoahHeap::heap()->shenandoahPolicy()->phase_times(); 114 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Universe_oops_do)) { 115 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::UniverseRoots, worker_id); 116 Universe::oops_do(strong_roots); 117 } 118 119 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_oops_do)) { 120 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::JNIRoots, worker_id); 121 JNIHandles::oops_do(strong_roots); 122 } 123 124 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_FlatProfiler_oops_do)) { 125 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::FlatProfilerRoots, worker_id); 126 FlatProfiler::oops_do(strong_roots); 127 } 128 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Management_oops_do)) { 129 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::ManagementRoots, worker_id); 130 Management::oops_do(strong_roots); 131 } 132 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_jvmti_oops_do)) { 133 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::JVMTIRoots, worker_id); 134 JvmtiExport::oops_do(strong_roots); 135 } 136 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) { 137 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::SystemDictionaryRoots, worker_id); 138 SystemDictionary::roots_oops_do(strong_roots, weak_roots); 139 } 140 if (jni_weak_roots != NULL) { 141 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_weak_oops_do)) { 142 ShenandoahAlwaysTrueClosure always_true; 143 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::JNIWeakRoots, worker_id); 144 JNIHandles::weak_oops_do(&always_true, jni_weak_roots); 145 } 146 } 147 148 { 149 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::ObjectSynchronizerRoots, worker_id); 150 while(_om_iterator.parallel_oops_do(strong_roots)); 151 } 152 153 // All threads execute the following. A specific chunk of buckets 154 // from the StringTable are the individual tasks. 155 if (weak_roots != NULL) { 156 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::StringTableRoots, worker_id); 157 StringTable::possibly_parallel_oops_do(weak_roots); 158 } 159 } 160 161 uint ShenandoahRootProcessor::n_workers() const { 162 return _srs.n_threads(); 163 } 164 165 ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, ShenandoahCollectorPolicy::TimingPhase phase) : 166 _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)), 167 _srs(n_workers), 168 _phase(phase), 169 _codecache_iterator(CodeCache::parallel_iterator()) 170 { 171 heap->shenandoahPolicy()->record_workers_start(_phase); 172 } 173 174 ShenandoahRootEvacuator::~ShenandoahRootEvacuator() { 175 delete _process_strong_tasks; 176 ShenandoahHeap::heap()->shenandoahPolicy()->record_workers_end(_phase); 177 } 178 179 void ShenandoahRootEvacuator::process_evacuate_roots(OopClosure* oops, 180 CodeBlobClosure* blobs, 181 uint worker_id) { 182 183 ShenandoahPhaseTimes* phase_times = ShenandoahHeap::heap()->shenandoahPolicy()->phase_times(); 184 { 185 bool is_par = n_workers() > 1; 186 ResourceMark rm; 187 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::ThreadRoots, worker_id); 188 Threads::possibly_parallel_oops_do(is_par, oops, NULL); 189 } 190 191 { 192 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::CodeCacheRoots, worker_id); 193 _codecache_iterator.parallel_blobs_do(blobs); 194 } 195 196 _process_strong_tasks->all_tasks_completed(n_workers()); 197 } 198 199 uint ShenandoahRootEvacuator::n_workers() const { 200 return _srs.n_threads(); 201 } 202 203 // Implemenation of ParallelCLDRootIterator 204 ParallelCLDRootIterator::ParallelCLDRootIterator() { 205 assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); 206 ClassLoaderDataGraph::clear_claimed_marks(); 207 } 208 209 void ParallelCLDRootIterator::root_cld_do(CLDClosure* strong, CLDClosure* weak) { 210 ClassLoaderDataGraph::roots_cld_do(strong, weak); 211 } 212