< prev index next >

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

Print this page
rev 58543 : 8241605: Shenandoah: More aggressive reference discovery


 165     ShenandoahConcurrentWorkerSession worker_session(worker_id);
 166     ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
 167     ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
 168     ReferenceProcessor* rp;
 169     if (heap->process_references()) {
 170       rp = heap->ref_processor();
 171       shenandoah_assert_rp_isalive_installed();
 172     } else {
 173       rp = NULL;
 174     }
 175 
 176     _cm->concurrent_scan_code_roots(worker_id, rp);
 177     _cm->mark_loop(worker_id, _terminator, rp,
 178                    true, // cancellable
 179                    ShenandoahStringDedup::is_enabled()); // perform string dedup
 180   }
 181 };
 182 
 183 class ShenandoahSATBAndRemarkCodeRootsThreadsClosure : public ThreadClosure {
 184 private:
 185   ShenandoahSATBBufferClosure* _satb_cl;
 186   MarkingCodeBlobClosure*      _code_cl;

 187   uintx _claim_token;
 188 
 189 public:
 190   ShenandoahSATBAndRemarkCodeRootsThreadsClosure(ShenandoahSATBBufferClosure* satb_cl, MarkingCodeBlobClosure* code_cl) :
 191     _satb_cl(satb_cl), _code_cl(code_cl),

 192     _claim_token(Threads::thread_claim_token()) {}
 193 
 194   void do_thread(Thread* thread) {
 195     if (thread->claim_threads_do(true, _claim_token)) {
 196       ShenandoahThreadLocalData::satb_mark_queue(thread).apply_closure_and_empty(_satb_cl);
 197       if (_code_cl != NULL && thread->is_Java_thread()) {







 198         // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking
 199         // however the liveness of oops reachable from nmethods have very complex lifecycles:
 200         // * Alive if on the stack of an executing method
 201         // * Weakly reachable otherwise
 202         // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
 203         // live by the SATB invariant but other oops recorded in nmethods may behave differently.
 204         JavaThread* jt = (JavaThread*)thread;
 205         jt->nmethods_do(_code_cl);
 206       }
 207     }
 208   }
 209 };
 210 
 211 class ShenandoahFinalMarkingTask : public AbstractGangTask {
 212 private:
 213   ShenandoahConcurrentMark* _cm;
 214   TaskTerminator*           _terminator;
 215   bool _dedup_string;
 216 
 217 public:


 226     ReferenceProcessor* rp;
 227     if (heap->process_references()) {
 228       rp = heap->ref_processor();
 229       shenandoah_assert_rp_isalive_installed();
 230     } else {
 231       rp = NULL;
 232     }
 233 
 234     // First drain remaining SATB buffers.
 235     // Notice that this is not strictly necessary for mark-compact. But since
 236     // it requires a StrongRootsScope around the task, we need to claim the
 237     // threads, and performance-wise it doesn't really matter. Adds about 1ms to
 238     // full-gc.
 239     {
 240       ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
 241 
 242       ShenandoahSATBBufferClosure cl(q);
 243       SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
 244       while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
 245 
 246       if (heap->unload_classes() && !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
 247         if (heap->has_forwarded_objects()) {
 248           ShenandoahMarkResolveRefsClosure resolve_mark_cl(q, rp);
 249           MarkingCodeBlobClosure blobsCl(&resolve_mark_cl, !CodeBlobToOopClosure::FixRelocations);
 250           ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, &blobsCl);


 251           Threads::threads_do(&tc);
 252         } else {
 253           ShenandoahMarkRefsClosure mark_cl(q, rp);
 254           MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
 255           ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, &blobsCl);
 256           Threads::threads_do(&tc);
 257         }
 258       } else {
 259         ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, NULL);
 260         Threads::threads_do(&tc);
 261       }
 262     }
 263 
 264     if (heap->is_degenerated_gc_in_progress()) {
 265       // Degenerated cycle may bypass concurrent cycle, so code roots might not be scanned,
 266       // let's check here.
 267       _cm->concurrent_scan_code_roots(worker_id, rp);
 268     }
 269 
 270     _cm->mark_loop(worker_id, _terminator, rp,
 271                    false, // not cancellable
 272                    _dedup_string);
 273 
 274     assert(_cm->task_queues()->is_empty(), "Should be empty");
 275   }
 276 };
 277 
 278 void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_phase) {
 279   assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");




 165     ShenandoahConcurrentWorkerSession worker_session(worker_id);
 166     ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
 167     ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
 168     ReferenceProcessor* rp;
 169     if (heap->process_references()) {
 170       rp = heap->ref_processor();
 171       shenandoah_assert_rp_isalive_installed();
 172     } else {
 173       rp = NULL;
 174     }
 175 
 176     _cm->concurrent_scan_code_roots(worker_id, rp);
 177     _cm->mark_loop(worker_id, _terminator, rp,
 178                    true, // cancellable
 179                    ShenandoahStringDedup::is_enabled()); // perform string dedup
 180   }
 181 };
 182 
 183 class ShenandoahSATBAndRemarkCodeRootsThreadsClosure : public ThreadClosure {
 184 private:
 185   ShenandoahSATBBufferClosure* const _satb_cl;
 186   OopClosure*                  const _cl;
 187   MarkingCodeBlobClosure*      const _code_cl;
 188   uintx _claim_token;

 189 public:
 190   ShenandoahSATBAndRemarkCodeRootsThreadsClosure(ShenandoahSATBBufferClosure* satb_cl,
 191                                                  OopClosure* cl, MarkingCodeBlobClosure* code_cl) :
 192     _satb_cl(satb_cl), _cl(cl), _code_cl(code_cl),
 193     _claim_token(Threads::thread_claim_token()) {}
 194 
 195   void do_thread(Thread* thread) {
 196     if (thread->claim_threads_do(true, _claim_token)) {
 197       ShenandoahThreadLocalData::satb_mark_queue(thread).apply_closure_and_empty(_satb_cl);
 198       if (_cl != NULL) {
 199         // This doesn't appear to add very much to final-mark latency. If that ever becomes a problem,
 200         // we can attempt to trim it to only scan actual thread-stacks (and avoid stuff like handles, monitors, etc)
 201         // and there only compiled frames. We can also make thread-scans templatized to avoid virtual calls and
 202         // instead inline the closures.
 203         ResourceMark rm;
 204         thread->oops_do(_cl, _code_cl);
 205       } else if (_code_cl != NULL && thread->is_Java_thread()) {
 206         // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking
 207         // however the liveness of oops reachable from nmethods have very complex lifecycles:
 208         // * Alive if on the stack of an executing method
 209         // * Weakly reachable otherwise
 210         // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
 211         // live by the SATB invariant but other oops recorded in nmethods may behave differently.
 212         JavaThread* jt = (JavaThread*)thread;
 213         jt->nmethods_do(_code_cl);
 214       }
 215     }
 216   }
 217 };
 218 
 219 class ShenandoahFinalMarkingTask : public AbstractGangTask {
 220 private:
 221   ShenandoahConcurrentMark* _cm;
 222   TaskTerminator*           _terminator;
 223   bool _dedup_string;
 224 
 225 public:


 234     ReferenceProcessor* rp;
 235     if (heap->process_references()) {
 236       rp = heap->ref_processor();
 237       shenandoah_assert_rp_isalive_installed();
 238     } else {
 239       rp = NULL;
 240     }
 241 
 242     // First drain remaining SATB buffers.
 243     // Notice that this is not strictly necessary for mark-compact. But since
 244     // it requires a StrongRootsScope around the task, we need to claim the
 245     // threads, and performance-wise it doesn't really matter. Adds about 1ms to
 246     // full-gc.
 247     {
 248       ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
 249 
 250       ShenandoahSATBBufferClosure cl(q);
 251       SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
 252       while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
 253 
 254       bool do_nmethods = heap->unload_classes() && !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading();
 255       if (heap->has_forwarded_objects()) {
 256         ShenandoahMarkResolveRefsClosure resolve_mark_cl(q, rp);
 257         MarkingCodeBlobClosure blobsCl(&resolve_mark_cl, !CodeBlobToOopClosure::FixRelocations);
 258         ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl,
 259                                                           ShenandoahAggressiveReferenceDiscovery ? &resolve_mark_cl : NULL,
 260                                                           do_nmethods ? &blobsCl : NULL);
 261         Threads::threads_do(&tc);
 262       } else {
 263         ShenandoahMarkRefsClosure mark_cl(q, rp);
 264         MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
 265         ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl,
 266                                                           ShenandoahAggressiveReferenceDiscovery ? &mark_cl : NULL,
 267                                                           do_nmethods ? &blobsCl : NULL);


 268         Threads::threads_do(&tc);
 269       }
 270     }
 271 
 272     if (heap->is_degenerated_gc_in_progress()) {
 273       // Degenerated cycle may bypass concurrent cycle, so code roots might not be scanned,
 274       // let's check here.
 275       _cm->concurrent_scan_code_roots(worker_id, rp);
 276     }
 277 
 278     _cm->mark_loop(worker_id, _terminator, rp,
 279                    false, // not cancellable
 280                    _dedup_string);
 281 
 282     assert(_cm->task_queues()->is_empty(), "Should be empty");
 283   }
 284 };
 285 
 286 void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_phase) {
 287   assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");


< prev index next >