< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp

Print this page


   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/shenandoahVMOperations.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);


 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 }
   1 /*
   2  * Copyright (c) 2015, 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 #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/shenandoahVMOperations.hpp"
  37 #include "gc/shared/weakProcessor.inline.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 struct PhaseMap {
  45   WeakProcessorPhases::Phase            _weak_processor_phase;
  46   ShenandoahPhaseTimings::GCParPhases   _shenandoah_phase;
  47 };
  48 
  49 static const struct PhaseMap phase_mapping[] = {
  50 #if INCLUDE_JVMTI
  51   {WeakProcessorPhases::jvmti,       ShenandoahPhaseTimings::JVMTIWeakRoots},
  52 #endif
  53 #if INCLUDE_JFR
  54   {WeakProcessorPhases::jfr,         ShenandoahPhaseTimings::JFRWeakRoots},
  55 #endif
  56   {WeakProcessorPhases::jni,         ShenandoahPhaseTimings::JNIWeakRoots},
  57   {WeakProcessorPhases::stringtable, ShenandoahPhaseTimings::StringTableRoots},
  58   {WeakProcessorPhases::vm,          ShenandoahPhaseTimings::VMWeakRoots}
  59 };
  60 
  61 STATIC_ASSERT(sizeof(phase_mapping) / sizeof(PhaseMap) == WeakProcessorPhases::phase_count);
  62 
  63 ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers,
  64                                                  ShenandoahPhaseTimings::Phase phase) :
  65   _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)),
  66   _srs(n_workers),
  67   _par_state_string(StringTable::weak_storage()),
  68   _phase(phase),
  69   _coderoots_all_iterator(ShenandoahCodeRoots::iterator()),
  70   _weak_processor_timings(n_workers),
  71   _weak_processor_task(&_weak_processor_timings, n_workers),
  72   _processed_weak_roots(false) {
  73   heap->phase_timings()->record_workers_start(_phase);
  74 
  75   if (ShenandoahStringDedup::is_enabled()) {
  76     StringDedup::gc_prologue(false);
  77   }
  78 }
  79 
  80 ShenandoahRootProcessor::~ShenandoahRootProcessor() {
  81   delete _process_strong_tasks;
  82   if (ShenandoahStringDedup::is_enabled()) {
  83     StringDedup::gc_epilogue();
  84   }
  85 
  86   ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
  87 
  88   if (_processed_weak_roots) {
  89     assert(_weak_processor_timings.max_threads() == n_workers(), "Must match");
  90     for (uint index = 0; index < WeakProcessorPhases::phase_count; index ++) {
  91       weak_processor_timing_to_shenandoah_timing(phase_mapping[index]._weak_processor_phase,
  92                                                  phase_mapping[index]._shenandoah_phase,
  93                                                  worker_times);
  94     }
  95   }
  96 
  97   ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
  98 }
  99 
 100 void ShenandoahRootProcessor::weak_processor_timing_to_shenandoah_timing(const WeakProcessorPhases::Phase wpp,
 101                                                                          const ShenandoahPhaseTimings::GCParPhases spp,
 102                                                                          ShenandoahWorkerTimings* worker_times) const {
 103   if (WeakProcessorPhases::is_serial(wpp)) {
 104     worker_times->record_time_secs(spp, 0, _weak_processor_timings.phase_time_sec(wpp));
 105   } else {
 106     for (uint index = 0; index < _weak_processor_timings.max_threads(); index ++) {
 107       worker_times->record_time_secs(spp, index, _weak_processor_timings.worker_time_sec(index, wpp));
 108     }
 109   }
 110 }
 111 
 112 void ShenandoahRootProcessor::process_all_roots_slow(OopClosure* oops) {
 113   CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
 114   CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations);
 115 
 116   CodeCache::blobs_do(&blobs);
 117   ClassLoaderDataGraph::cld_do(&clds);
 118   Universe::oops_do(oops);
 119   Management::oops_do(oops);
 120   JvmtiExport::oops_do(oops);
 121   JNIHandles::oops_do(oops);
 122   WeakProcessor::oops_do(oops);
 123   ObjectSynchronizer::oops_do(oops);
 124   SystemDictionary::oops_do(oops);

 125 
 126   if (ShenandoahStringDedup::is_enabled()) {
 127     ShenandoahStringDedup::oops_do_slow(oops);
 128   }
 129 
 130   // Do thread roots the last. This allows verification code to find
 131   // any broken objects from those special roots first, not the accidental
 132   // dangling reference from the thread root.
 133   Threads::possibly_parallel_oops_do(false, oops, &blobs);
 134 }
 135 
 136 void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops,
 137                                                    OopClosure* weak_oops,
 138                                                    CLDClosure* clds,
 139                                                    CLDClosure* weak_clds,
 140                                                    CodeBlobClosure* blobs,
 141                                                    ThreadClosure* thread_cl,
 142                                                    uint worker_id) {
 143 
 144   process_java_roots(oops, clds, weak_clds, blobs, thread_cl, worker_id);


 219     Universe::oops_do(strong_roots);
 220   }
 221 
 222   if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_JNIHandles_oops_do)) {
 223     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id);
 224     JNIHandles::oops_do(strong_roots);
 225   }
 226   if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_Management_oops_do)) {
 227     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id);
 228     Management::oops_do(strong_roots);
 229   }
 230   if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_jvmti_oops_do)) {
 231     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id);
 232     JvmtiExport::oops_do(strong_roots);
 233   }
 234   if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) {
 235     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id);
 236     SystemDictionary::oops_do(strong_roots);
 237   }
 238   if (jni_weak_roots != NULL) {
 239     AlwaysTrueClosure always_true;
 240     _weak_processor_task.work<AlwaysTrueClosure, OopClosure>(worker_id, &always_true, jni_weak_roots);
 241     _processed_weak_roots = true;

 242   }
 243 
 244   if (ShenandoahStringDedup::is_enabled() && weak_roots != NULL) {
 245     ShenandoahStringDedup::parallel_oops_do(weak_roots, worker_id);
 246   }
 247 
 248   {
 249     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id);
 250     if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do)) {
 251       ObjectSynchronizer::oops_do(strong_roots);
 252     }
 253   }







 254 }
 255 
 256 uint ShenandoahRootProcessor::n_workers() const {
 257   return _srs.n_threads();
 258 }
 259 
 260 ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, ShenandoahPhaseTimings::Phase phase) :
 261   _evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
 262   _srs(n_workers),
 263   _phase(phase),
 264   _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()),
 265   _par_state_string(StringTable::weak_storage())
 266 
 267 {
 268   heap->phase_timings()->record_workers_start(_phase);
 269   if (ShenandoahStringDedup::is_enabled()) {
 270     StringDedup::gc_prologue(false);
 271   }
 272 }
 273 
 274 ShenandoahRootEvacuator::~ShenandoahRootEvacuator() {
 275   delete _evacuation_tasks;
 276   if (ShenandoahStringDedup::is_enabled()) {
 277     StringDedup::gc_epilogue();
 278   }
 279   ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
 280 }
 281 
 282 void ShenandoahRootEvacuator::process_evacuate_roots(OopClosure* oops,
 283                                                      CodeBlobClosure* blobs,
 284                                                      uint worker_id) {
 285 
 286   ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
 287   {
 288     bool is_par = n_workers() > 1;
 289     ResourceMark rm;
 290     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
 291 
 292     Threads::possibly_parallel_oops_do(is_par, oops, NULL);
 293   }
 294 
 295   if (blobs != NULL) {
 296     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
 297     _coderoots_cset_iterator.possibly_parallel_blobs_do(blobs);
 298   }
 299 
 300   if (ShenandoahStringDedup::is_enabled()) {
 301     ShenandoahStringDedup::parallel_oops_do(oops, worker_id);
 302   }
 303 
 304   if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Universe_oops_do)) {
 305     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id);
 306     Universe::oops_do(oops);
 307   }
 308 
 309   if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Management_oops_do)) {
 310     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id);
 311     Management::oops_do(oops);
 312   }
 313 
 314   if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_jvmti_oops_do)) {

 315     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id);
 316     JvmtiExport::oops_do(oops);
 317     ShenandoahForwardedIsAliveClosure is_alive;
 318     JvmtiExport::weak_oops_do(&is_alive, oops);
 319   }
 320 
 321   if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_SystemDictionary_oops_do)) {
 322     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id);
 323     SystemDictionary::oops_do(oops);
 324   }
 325 
 326   if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_ObjectSynchronizer_oops_do)) {
 327     ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id);
 328     ObjectSynchronizer::oops_do(oops);
 329   }
 330 
 331 }
 332 
 333 uint ShenandoahRootEvacuator::n_workers() const {
 334   return _srs.n_threads();
 335 }
 336 
 337 // Implemenation of ParallelCLDRootIterator
 338 ParallelCLDRootIterator::ParallelCLDRootIterator() {
 339   assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
 340   ClassLoaderDataGraph::clear_claimed_marks();
 341 }
 342 
 343 void ParallelCLDRootIterator::root_cld_do(CLDClosure* strong, CLDClosure* weak) {
 344     ClassLoaderDataGraph::roots_cld_do(strong, weak);
 345 }
< prev index next >