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, ShenandoahCollectorPolicy::TimingPhase phase) : 40 _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)), 41 _srs(n_workers), 42 _phase(phase), 43 _cld_iterator(ClassLoaderDataGraph::parallel_cld_root_iterator()), 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_evacuate_roots(OopClosure* oops, 56 CodeBlobClosure* blobs, 57 uint worker_id) { 58 59 ShenandoahPhaseTimes* phase_times = ShenandoahHeap::heap()->shenandoahPolicy()->phase_times(); 60 { 61 bool is_par = n_workers() > 1; 62 ResourceMark rm; 63 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::ThreadRoots, worker_id); 64 Threads::possibly_parallel_oops_do(is_par, oops, NULL); 65 } 66 67 { 68 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::CodeCacheRoots, worker_id); 69 while (_codecache_iterator.parallel_blobs_do(blobs)); 70 } 71 72 _process_strong_tasks->all_tasks_completed(n_workers()); 73 } 74 75 void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops, 76 OopClosure* weak_oops, 77 CLDClosure* clds, 78 CodeBlobClosure* blobs, 79 uint worker_id) { 80 81 process_java_roots(oops, clds, NULL, blobs, worker_id); 82 process_vm_roots(oops, NULL, weak_oops, worker_id); 83 84 _process_strong_tasks->all_tasks_completed(n_workers()); 85 } 86 87 void ShenandoahRootProcessor::process_all_roots(OopClosure* oops, 88 OopClosure* weak_oops, 89 CLDClosure* clds, 90 CodeBlobClosure* blobs, 91 uint worker_id) { 92 93 ShenandoahPhaseTimes* phase_times = ShenandoahHeap::heap()->shenandoahPolicy()->phase_times(); 94 process_java_roots(oops, clds, clds, NULL, worker_id); 95 process_vm_roots(oops, oops, weak_oops, worker_id); 96 97 if (blobs != NULL) { 98 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::CodeCacheRoots, worker_id); 99 while (_codecache_iterator.parallel_blobs_do(blobs)); 100 } 101 102 _process_strong_tasks->all_tasks_completed(n_workers()); 103 } 104 105 void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots, 106 CLDClosure* strong_clds, 107 CLDClosure* weak_clds, 108 CodeBlobClosure* strong_code, 109 uint worker_id) 110 { 111 ShenandoahPhaseTimes* phase_times = ShenandoahHeap::heap()->shenandoahPolicy()->phase_times(); 112 // Iterating over the CLDG and the Threads are done early to allow us to 113 // first process the strong CLDs and nmethods and then, after a barrier, 114 // let the thread process the weak CLDs and nmethods. 115 { 116 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::CLDGRoots, worker_id); 117 while(_cld_iterator.root_cld_do(strong_clds, weak_clds)); 118 } 119 120 { 121 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::ThreadRoots, worker_id); 122 bool is_par = n_workers() > 1; 123 ResourceMark rm; 124 Threads::possibly_parallel_oops_do(is_par, strong_roots, strong_code); 125 } 126 } 127 128 void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots, 129 OopClosure* weak_roots, 130 OopClosure* jni_weak_roots, 131 uint worker_id) 132 { 133 ShenandoahPhaseTimes* phase_times = ShenandoahHeap::heap()->shenandoahPolicy()->phase_times(); 134 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Universe_oops_do)) { 135 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::UniverseRoots, worker_id); 136 Universe::oops_do(strong_roots); 137 } 138 139 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_oops_do)) { 140 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::JNIRoots, worker_id); 141 JNIHandles::oops_do(strong_roots); 142 } 143 144 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_FlatProfiler_oops_do)) { 145 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::FlatProfilerRoots, worker_id); 146 FlatProfiler::oops_do(strong_roots); 147 } 148 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Management_oops_do)) { 149 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::ManagementRoots, worker_id); 150 Management::oops_do(strong_roots); 151 } 152 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_jvmti_oops_do)) { 153 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::JVMTIRoots, worker_id); 154 JvmtiExport::oops_do(strong_roots); 155 } 156 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) { 157 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::SystemDictionaryRoots, worker_id); 158 SystemDictionary::roots_oops_do(strong_roots, weak_roots); 159 } 160 if (jni_weak_roots != NULL) { 161 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_weak_oops_do)) { 162 ShenandoahAlwaysTrueClosure always_true; 163 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::JNIWeakRoots, worker_id); 164 JNIHandles::weak_oops_do(&always_true, jni_weak_roots); 165 } 166 } 167 168 { 169 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::ObjectSynchronizerRoots, worker_id); 170 while(_om_iterator.parallel_oops_do(strong_roots)); 171 } 172 173 // All threads execute the following. A specific chunk of buckets 174 // from the StringTable are the individual tasks. 175 if (weak_roots != NULL) { 176 ShenandoahParPhaseTimesTracker timer(phase_times, ShenandoahPhaseTimes::StringTableRoots, worker_id); 177 StringTable::possibly_parallel_oops_do(weak_roots); 178 } 179 } 180 181 uint ShenandoahRootProcessor::n_workers() const { 182 return _srs.n_threads(); 183 }