< prev index next >

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

Print this page
rev 58672 : Shenandoah: New incremental-update mode


 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:
 218   ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) :
 219     AbstractGangTask("Shenandoah Final Marking"), _cm(cm), _terminator(terminator), _dedup_string(dedup_string) {
 220   }
 221 
 222   void work(uint worker_id) {
 223     ShenandoahHeap* heap = ShenandoahHeap::heap();
 224 
 225     ShenandoahParallelWorkerSession worker_session(worker_id);
 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");




 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   OopClosure*            const _cl;
 187   MarkingCodeBlobClosure*      _code_cl;
 188   uintx _claim_token;
 189 
 190 public:
 191   ShenandoahSATBAndRemarkCodeRootsThreadsClosure(ShenandoahSATBBufferClosure* satb_cl, 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 (thread->is_Java_thread()) {
 199         if (_cl != NULL) {
 200           ResourceMark rm;
 201           thread->oops_do(_cl, _code_cl);
 202         } else  if (_code_cl != NULL) {
 203           // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking
 204           // however the liveness of oops reachable from nmethods have very complex lifecycles:
 205           // * Alive if on the stack of an executing method
 206           // * Weakly reachable otherwise
 207           // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
 208           // live by the SATB invariant but other oops recorded in nmethods may behave differently.
 209           JavaThread* jt = (JavaThread*)thread;
 210           jt->nmethods_do(_code_cl);
 211         }
 212       }
 213     }
 214   }
 215 };
 216 
 217 class ShenandoahFinalMarkingTask : public AbstractGangTask {
 218 private:
 219   ShenandoahConcurrentMark* _cm;
 220   TaskTerminator*           _terminator;
 221   bool _dedup_string;
 222 
 223 public:
 224   ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) :
 225     AbstractGangTask("Shenandoah Final Marking"), _cm(cm), _terminator(terminator), _dedup_string(dedup_string) {
 226   }
 227 
 228   void work(uint worker_id) {
 229     ShenandoahHeap* heap = ShenandoahHeap::heap();
 230 
 231     ShenandoahParallelWorkerSession worker_session(worker_id);
 232     ReferenceProcessor* rp;
 233     if (heap->process_references()) {
 234       rp = heap->ref_processor();
 235       shenandoah_assert_rp_isalive_installed();
 236     } else {
 237       rp = NULL;
 238     }
 239 
 240     // First drain remaining SATB buffers.
 241     // Notice that this is not strictly necessary for mark-compact. But since
 242     // it requires a StrongRootsScope around the task, we need to claim the
 243     // threads, and performance-wise it doesn't really matter. Adds about 1ms to
 244     // full-gc.
 245     {
 246       ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
 247 
 248       ShenandoahSATBBufferClosure cl(q);
 249       SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
 250       while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
 251       bool do_nmethods = heap->unload_classes() && !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading();

 252       if (heap->has_forwarded_objects()) {
 253         ShenandoahMarkResolveRefsClosure resolve_mark_cl(q, rp);
 254         MarkingCodeBlobClosure blobsCl(&resolve_mark_cl, !CodeBlobToOopClosure::FixRelocations);
 255         ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl,
 256                                                           ShenandoahStoreValEnqueueBarrier ? &resolve_mark_cl : NULL,
 257                                                           do_nmethods ? &blobsCl : NULL);
 258         Threads::threads_do(&tc);
 259       } else {
 260         ShenandoahMarkRefsClosure mark_cl(q, rp);
 261         MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
 262         ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl,
 263                                                           ShenandoahStoreValEnqueueBarrier ? &mark_cl : NULL,
 264                                                           do_nmethods ? &blobsCl : NULL);


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


< prev index next >