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/classLoaderDataGraph.hpp" 27 #include "classfile/stringTable.hpp" 28 #include "classfile/systemDictionary.hpp" 29 #include "code/codeCache.hpp" 30 #include "gc/shenandoah/shenandoahRootProcessor.hpp" 31 #include "gc/shenandoah/shenandoahHeap.hpp" 32 #include "gc/shenandoah/shenandoahPhaseTimings.hpp" 33 #include "gc/shenandoah/shenandoahStringDedup.hpp" 34 #include "gc/shenandoah/shenandoahTimingTracker.hpp" 35 #include "gc/shenandoah/shenandoahUtils.hpp" 36 #include "gc/shenandoah/vm_operations_shenandoah.hpp" 37 #include "gc/shared/weakProcessor.hpp" 38 #include "memory/allocation.inline.hpp" 39 #include "memory/iterator.hpp" 40 #include "memory/resourceArea.hpp" 41 #include "runtime/thread.hpp" 42 #include "services/management.hpp" 43 44 ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers, 45 ShenandoahPhaseTimings::Phase phase) : 46 _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)), 47 _srs(n_workers), 48 _par_state_string(StringTable::weak_storage()), 49 _phase(phase), 50 _coderoots_all_iterator(ShenandoahCodeRoots::iterator()) 51 { 52 heap->phase_timings()->record_workers_start(_phase); 53 54 if (ShenandoahStringDedup::is_enabled()) { 55 StringDedup::gc_prologue(false); 56 } 57 } 58 59 ShenandoahRootProcessor::~ShenandoahRootProcessor() { 60 delete _process_strong_tasks; 61 if (ShenandoahStringDedup::is_enabled()) { 62 StringDedup::gc_epilogue(); 63 } 64 65 ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); 66 } 67 68 void ShenandoahRootProcessor::process_all_roots_slow(OopClosure* oops) { 69 CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong); 70 CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations); 71 72 CodeCache::blobs_do(&blobs); 73 ClassLoaderDataGraph::cld_do(&clds); 74 Universe::oops_do(oops); 75 Management::oops_do(oops); 76 JvmtiExport::oops_do(oops); 77 JNIHandles::oops_do(oops); 78 WeakProcessor::oops_do(oops); 79 ObjectSynchronizer::oops_do(oops); 80 SystemDictionary::oops_do(oops); 81 StringTable::oops_do(oops); 82 83 if (ShenandoahStringDedup::is_enabled()) { 84 ShenandoahStringDedup::oops_do_slow(oops); 85 } 86 87 // Do thread roots the last. This allows verification code to find 88 // any broken objects from those special roots first, not the accidental 89 // dangling reference from the thread root. 90 Threads::possibly_parallel_oops_do(false, oops, &blobs); 91 } 92 93 void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops, 94 OopClosure* weak_oops, 95 CLDClosure* clds, 96 CLDClosure* weak_clds, 97 CodeBlobClosure* blobs, 98 ThreadClosure* thread_cl, 99 uint worker_id) { 100 101 process_java_roots(oops, clds, weak_clds, blobs, thread_cl, worker_id); 102 process_vm_roots(oops, NULL, weak_oops, worker_id); 103 104 _process_strong_tasks->all_tasks_completed(n_workers()); 105 } 106 107 void ShenandoahRootProcessor::process_all_roots(OopClosure* oops, 108 OopClosure* weak_oops, 109 CLDClosure* clds, 110 CodeBlobClosure* blobs, 111 ThreadClosure* thread_cl, 112 uint worker_id) { 113 114 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 115 process_java_roots(oops, clds, clds, blobs, thread_cl, worker_id); 116 process_vm_roots(oops, oops, weak_oops, worker_id); 117 118 if (blobs != NULL) { 119 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); 120 _coderoots_all_iterator.possibly_parallel_blobs_do(blobs); 121 } 122 123 _process_strong_tasks->all_tasks_completed(n_workers()); 124 } 125 126 class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure { 127 private: 128 OopClosure* _f; 129 CodeBlobClosure* _cf; 130 ThreadClosure* _thread_cl; 131 public: 132 ShenandoahParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf, ThreadClosure* thread_cl) : 133 _f(f), _cf(cf), _thread_cl(thread_cl) {} 134 135 void do_thread(Thread* t) { 136 if (_thread_cl != NULL) { 137 _thread_cl->do_thread(t); 138 } 139 t->oops_do(_f, _cf); 140 } 141 }; 142 143 void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots, 144 CLDClosure* strong_clds, 145 CLDClosure* weak_clds, 146 CodeBlobClosure* strong_code, 147 ThreadClosure* thread_cl, 148 uint worker_id) 149 { 150 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 151 // Iterating over the CLDG and the Threads are done early to allow us to 152 // first process the strong CLDs and nmethods and then, after a barrier, 153 // let the thread process the weak CLDs and nmethods. 154 { 155 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); 156 _cld_iterator.root_cld_do(strong_clds, weak_clds); 157 } 158 159 { 160 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id); 161 bool is_par = n_workers() > 1; 162 ResourceMark rm; 163 ShenandoahParallelOopsDoThreadClosure cl(strong_roots, strong_code, thread_cl); 164 Threads::possibly_parallel_threads_do(is_par, &cl); 165 } 166 } 167 168 void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots, 169 OopClosure* weak_roots, 170 OopClosure* jni_weak_roots, 171 uint worker_id) 172 { 173 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 174 if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_Universe_oops_do)) { 175 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id); 176 Universe::oops_do(strong_roots); 177 } 178 179 if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_JNIHandles_oops_do)) { 180 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id); 181 JNIHandles::oops_do(strong_roots); 182 } 183 if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_Management_oops_do)) { 184 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id); 185 Management::oops_do(strong_roots); 186 } 187 if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_jvmti_oops_do)) { 188 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id); 189 JvmtiExport::oops_do(strong_roots); 190 } 191 if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) { 192 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id); 193 SystemDictionary::oops_do(strong_roots); 194 } 195 if (jni_weak_roots != NULL) { 196 if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_JNIHandles_weak_oops_do)) { 197 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIWeakRoots, worker_id); 198 WeakProcessor::oops_do(jni_weak_roots); 199 } 200 } 201 202 if (ShenandoahStringDedup::is_enabled() && weak_roots != NULL) { 203 ShenandoahStringDedup::parallel_oops_do(weak_roots, worker_id); 204 } 205 206 { 207 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id); 208 if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do)) { 209 ObjectSynchronizer::oops_do(strong_roots); 210 } 211 } 212 213 // All threads execute the following. A specific chunk of buckets 214 // from the StringTable are the individual tasks. 215 if (weak_roots != NULL) { 216 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::StringTableRoots, worker_id); 217 StringTable::possibly_parallel_oops_do(&_par_state_string, weak_roots); 218 } 219 } 220 221 uint ShenandoahRootProcessor::n_workers() const { 222 return _srs.n_threads(); 223 } 224 225 ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, ShenandoahPhaseTimings::Phase phase) : 226 _evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)), 227 _srs(n_workers), 228 _phase(phase), 229 _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()) 230 { 231 heap->phase_timings()->record_workers_start(_phase); 232 } 233 234 ShenandoahRootEvacuator::~ShenandoahRootEvacuator() { 235 delete _evacuation_tasks; 236 ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); 237 } 238 239 void ShenandoahRootEvacuator::process_evacuate_roots(OopClosure* oops, 240 CodeBlobClosure* blobs, 241 uint worker_id) { 242 243 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); 244 { 245 bool is_par = n_workers() > 1; 246 ResourceMark rm; 247 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id); 248 249 Threads::possibly_parallel_oops_do(is_par, oops, NULL); 250 } 251 252 if (blobs != NULL) { 253 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); 254 _coderoots_cset_iterator.possibly_parallel_blobs_do(blobs); 255 } 256 257 if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_jvmti_oops_do)) { 258 ShenandoahForwardedIsAliveClosure is_alive; 259 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id); 260 JvmtiExport::weak_oops_do(&is_alive, oops); 261 } 262 } 263 264 uint ShenandoahRootEvacuator::n_workers() const { 265 return _srs.n_threads(); 266 } 267 268 // Implemenation of ParallelCLDRootIterator 269 ParallelCLDRootIterator::ParallelCLDRootIterator() { 270 assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); 271 ClassLoaderDataGraph::clear_claimed_marks(); 272 } 273 274 void ParallelCLDRootIterator::root_cld_do(CLDClosure* strong, CLDClosure* weak) { 275 ClassLoaderDataGraph::roots_cld_do(strong, weak); 276 }