< prev index next >

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

Print this page
*** 28,19 ***
--- 28,21 ---
  #include "gc/shared/strongRootsScope.hpp"
  #include "gc/shared/taskTerminator.hpp"
  #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp"
  #include "gc/shenandoah/shenandoahClosures.inline.hpp"
  #include "gc/shenandoah/shenandoahConcurrentMark.hpp"
+ #include "gc/shenandoah/shenandoahGeneration.hpp"
  #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  #include "gc/shenandoah/shenandoahMark.inline.hpp"
  #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
  #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
  #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
  #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
  #include "gc/shenandoah/shenandoahStringDedup.hpp"
  #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp"
  #include "gc/shenandoah/shenandoahUtils.hpp"
+ #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp"
  #include "memory/iterator.inline.hpp"
  #include "memory/resourceArea.hpp"
  
  class ShenandoahUpdateRootsTask : public AbstractGangTask {
  private:

*** 67,10 ***
--- 69,11 ---
        _root_updater->roots_do<AlwaysTrueClosure, ShenandoahUpdateRefsClosure>(worker_id, &always_true, &cl);
      }
    }
  };
  
+ template <GenerationMode GENERATION>
  class ShenandoahConcurrentMarkingTask : public AbstractGangTask {
  private:
    ShenandoahConcurrentMark* const _cm;
    TaskTerminator* const           _terminator;
  

*** 81,15 ***
  
    void work(uint worker_id) {
      ShenandoahHeap* heap = ShenandoahHeap::heap();
      ShenandoahConcurrentWorkerSession worker_session(worker_id);
      ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
!     ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
-     ShenandoahReferenceProcessor* rp = heap->ref_processor();
      assert(rp != NULL, "need reference processor");
      StringDedup::Requests requests;
!     _cm->mark_loop(worker_id, _terminator, rp,
                     true /*cancellable*/,
                     ShenandoahStringDedup::is_enabled() ? ENQUEUE_DEDUP : NO_DEDUP,
                     &requests);
    }
  };
--- 84,14 ---
  
    void work(uint worker_id) {
      ShenandoahHeap* heap = ShenandoahHeap::heap();
      ShenandoahConcurrentWorkerSession worker_session(worker_id);
      ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
!     ShenandoahReferenceProcessor* rp = heap->active_generation()->ref_processor();
      assert(rp != NULL, "need reference processor");
      StringDedup::Requests requests;
!     _cm->mark_loop(GENERATION, worker_id, _terminator, rp,
                     true /*cancellable*/,
                     ShenandoahStringDedup::is_enabled() ? ENQUEUE_DEDUP : NO_DEDUP,
                     &requests);
    }
  };

*** 118,10 ***
--- 120,11 ---
        }
      }
    }
  };
  
+ template<GenerationMode GENERATION>
  class ShenandoahFinalMarkingTask : public AbstractGangTask {
  private:
    ShenandoahConcurrentMark* _cm;
    TaskTerminator*           _terminator;
    bool                      _dedup_string;

*** 133,84 ***
  
    void work(uint worker_id) {
      ShenandoahHeap* heap = ShenandoahHeap::heap();
  
      ShenandoahParallelWorkerSession worker_session(worker_id);
-     ShenandoahReferenceProcessor* rp = heap->ref_processor();
      StringDedup::Requests requests;
  
      // First drain remaining SATB buffers.
      {
        ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
  
!       ShenandoahSATBBufferClosure cl(q);
        SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
        while (satb_mq_set.apply_closure_to_completed_buffer(&cl)) {}
        assert(!heap->has_forwarded_objects(), "Not expected");
  
!       ShenandoahMarkRefsClosure             mark_cl(q, rp);
        ShenandoahSATBAndRemarkThreadsClosure tc(satb_mq_set,
                                                 ShenandoahIUBarrier ? &mark_cl : NULL);
        Threads::threads_do(&tc);
      }
!     _cm->mark_loop(worker_id, _terminator, rp,
                     false /*not cancellable*/,
                     _dedup_string ? ENQUEUE_DEDUP : NO_DEDUP,
                     &requests);
      assert(_cm->task_queues()->is_empty(), "Should be empty");
    }
  };
  
! ShenandoahConcurrentMark::ShenandoahConcurrentMark() :
!   ShenandoahMark() {}
  
  // Mark concurrent roots during concurrent phases
  class ShenandoahMarkConcurrentRootsTask : public AbstractGangTask {
  private:
    SuspendibleThreadSetJoiner          _sts_joiner;
    ShenandoahConcurrentRootScanner     _root_scanner;
    ShenandoahObjToScanQueueSet* const  _queue_set;
    ShenandoahReferenceProcessor* const _rp;
  
  public:
    ShenandoahMarkConcurrentRootsTask(ShenandoahObjToScanQueueSet* qs,
                                      ShenandoahReferenceProcessor* rp,
                                      ShenandoahPhaseTimings::Phase phase,
                                      uint nworkers);
    void work(uint worker_id);
  };
  
! ShenandoahMarkConcurrentRootsTask::ShenandoahMarkConcurrentRootsTask(ShenandoahObjToScanQueueSet* qs,
!                                                                      ShenandoahReferenceProcessor* rp,
!                                                                      ShenandoahPhaseTimings::Phase phase,
!                                                                      uint nworkers) :
    AbstractGangTask("Shenandoah Concurrent Mark Roots"),
    _root_scanner(nworkers, phase),
    _queue_set(qs),
    _rp(rp) {
    assert(!ShenandoahHeap::heap()->has_forwarded_objects(), "Not expected");
  }
  
! void ShenandoahMarkConcurrentRootsTask::work(uint worker_id) {
    ShenandoahConcurrentWorkerSession worker_session(worker_id);
    ShenandoahObjToScanQueue* q = _queue_set->queue(worker_id);
!   ShenandoahMarkRefsClosure cl(q, _rp);
    _root_scanner.roots_do(&cl, worker_id);
  }
  
  void ShenandoahConcurrentMark::mark_concurrent_roots() {
    ShenandoahHeap* const heap = ShenandoahHeap::heap();
    assert(!heap->has_forwarded_objects(), "Not expected");
  
-   TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
- 
    WorkGang* workers = heap->workers();
!   ShenandoahReferenceProcessor* rp = heap->ref_processor();
!   task_queues()->reserve(workers->active_workers());
!   ShenandoahMarkConcurrentRootsTask task(task_queues(), rp, ShenandoahPhaseTimings::conc_mark_roots, workers->active_workers());
! 
!   workers->run_task(&task);
  }
  
  class ShenandoahFlushSATBHandshakeClosure : public HandshakeClosure {
  private:
    SATBMarkQueueSet& _qset;
--- 136,105 ---
  
    void work(uint worker_id) {
      ShenandoahHeap* heap = ShenandoahHeap::heap();
  
      ShenandoahParallelWorkerSession worker_session(worker_id);
      StringDedup::Requests requests;
+     ShenandoahReferenceProcessor* rp = heap->active_generation()->ref_processor();
  
      // First drain remaining SATB buffers.
      {
        ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
+       ShenandoahObjToScanQueue* old = _cm->get_old_queue(worker_id);
  
!       ShenandoahSATBBufferClosure<GENERATION> cl(q, old);
        SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
        while (satb_mq_set.apply_closure_to_completed_buffer(&cl)) {}
        assert(!heap->has_forwarded_objects(), "Not expected");
  
!       ShenandoahMarkRefsClosure<GENERATION> mark_cl(q, rp, old);
        ShenandoahSATBAndRemarkThreadsClosure tc(satb_mq_set,
                                                 ShenandoahIUBarrier ? &mark_cl : NULL);
        Threads::threads_do(&tc);
      }
!     _cm->mark_loop(GENERATION, worker_id, _terminator, rp,
                     false /*not cancellable*/,
                     _dedup_string ? ENQUEUE_DEDUP : NO_DEDUP,
                     &requests);
      assert(_cm->task_queues()->is_empty(), "Should be empty");
    }
  };
  
! ShenandoahConcurrentMark::ShenandoahConcurrentMark(ShenandoahGeneration* generation) :
!   ShenandoahMark(generation) {}
  
  // Mark concurrent roots during concurrent phases
+ template<GenerationMode GENERATION>
  class ShenandoahMarkConcurrentRootsTask : public AbstractGangTask {
  private:
    SuspendibleThreadSetJoiner          _sts_joiner;
    ShenandoahConcurrentRootScanner     _root_scanner;
    ShenandoahObjToScanQueueSet* const  _queue_set;
+   ShenandoahObjToScanQueueSet* const  _old_queue_set;
    ShenandoahReferenceProcessor* const _rp;
  
  public:
    ShenandoahMarkConcurrentRootsTask(ShenandoahObjToScanQueueSet* qs,
+                                     ShenandoahObjToScanQueueSet* old,
                                      ShenandoahReferenceProcessor* rp,
                                      ShenandoahPhaseTimings::Phase phase,
                                      uint nworkers);
    void work(uint worker_id);
  };
  
! template<GenerationMode GENERATION>
! ShenandoahMarkConcurrentRootsTask<GENERATION>::ShenandoahMarkConcurrentRootsTask(ShenandoahObjToScanQueueSet* qs,
!                                                                                  ShenandoahObjToScanQueueSet* old,
!                                                                                  ShenandoahReferenceProcessor* rp,
+                                                                                  ShenandoahPhaseTimings::Phase phase,
+                                                                                  uint nworkers) :
    AbstractGangTask("Shenandoah Concurrent Mark Roots"),
    _root_scanner(nworkers, phase),
    _queue_set(qs),
+   _old_queue_set(old),
    _rp(rp) {
    assert(!ShenandoahHeap::heap()->has_forwarded_objects(), "Not expected");
  }
  
! template<GenerationMode GENERATION>
+ void ShenandoahMarkConcurrentRootsTask<GENERATION>::work(uint worker_id) {
    ShenandoahConcurrentWorkerSession worker_session(worker_id);
    ShenandoahObjToScanQueue* q = _queue_set->queue(worker_id);
!   ShenandoahObjToScanQueue* old = _old_queue_set == NULL ? NULL : _old_queue_set->queue(worker_id);
+   ShenandoahMarkRefsClosure<GENERATION> cl(q, _rp, old);
    _root_scanner.roots_do(&cl, worker_id);
  }
  
  void ShenandoahConcurrentMark::mark_concurrent_roots() {
    ShenandoahHeap* const heap = ShenandoahHeap::heap();
    assert(!heap->has_forwarded_objects(), "Not expected");
  
    WorkGang* workers = heap->workers();
!   ShenandoahReferenceProcessor* rp = _generation->ref_processor();
!   _generation->reserve_task_queues(workers->active_workers());
!   switch (_generation->generation_mode()) {
!     case YOUNG: {
!       ShenandoahMarkConcurrentRootsTask<YOUNG> task(task_queues(), old_task_queues(), rp, ShenandoahPhaseTimings::conc_mark_roots, workers->active_workers());
+       workers->run_task(&task);
+       break;
+     }
+     case GLOBAL: {
+       assert(old_task_queues() == NULL, "Global mark should not have old gen mark queues.");
+       ShenandoahMarkConcurrentRootsTask<GLOBAL> task(task_queues(), old_task_queues(), rp, ShenandoahPhaseTimings::conc_mark_roots, workers->active_workers());
+       workers->run_task(&task);
+       break;
+     }
+     default:
+       // Intentionally haven't added OLD here. We use a YOUNG generation
+       // cycle to bootstrap concurrent old marking.
+       ShouldNotReachHere();
+   }
  }
  
  class ShenandoahFlushSATBHandshakeClosure : public HandshakeClosure {
  private:
    SATBMarkQueueSet& _qset;

*** 231,13 ***
    task_queues()->reserve(nworkers);
  
    ShenandoahSATBMarkQueueSet& qset = ShenandoahBarrierSet::satb_mark_queue_set();
    ShenandoahFlushSATBHandshakeClosure flush_satb(qset);
    for (uint flushes = 0; flushes < ShenandoahMaxSATBBufferFlushes; flushes++) {
!     TaskTerminator terminator(nworkers, task_queues());
!     ShenandoahConcurrentMarkingTask task(this, &terminator);
!     workers->run_task(&task);
  
      if (heap->cancelled_gc()) {
        // GC is cancelled, break out.
        break;
      }
--- 255,32 ---
    task_queues()->reserve(nworkers);
  
    ShenandoahSATBMarkQueueSet& qset = ShenandoahBarrierSet::satb_mark_queue_set();
    ShenandoahFlushSATBHandshakeClosure flush_satb(qset);
    for (uint flushes = 0; flushes < ShenandoahMaxSATBBufferFlushes; flushes++) {
!     switch (_generation->generation_mode()) {
!       case YOUNG: {
!         TaskTerminator terminator(nworkers, task_queues());
+         ShenandoahConcurrentMarkingTask<YOUNG> task(this, &terminator);
+         workers->run_task(&task);
+         break;
+       }
+       case OLD: {
+         TaskTerminator terminator(nworkers, task_queues());
+         ShenandoahConcurrentMarkingTask<OLD> task(this, &terminator);
+         workers->run_task(&task);
+         break;
+       }
+       case GLOBAL: {
+         TaskTerminator terminator(nworkers, task_queues());
+         ShenandoahConcurrentMarkingTask<GLOBAL> task(this, &terminator);
+         workers->run_task(&task);
+         break;
+       }
+       default:
+         ShouldNotReachHere();
+     }
  
      if (heap->cancelled_gc()) {
        // GC is cancelled, break out.
        break;
      }

*** 260,13 ***
    finish_mark_work();
    assert(task_queues()->is_empty(), "Should be empty");
    TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
    TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
  
!   ShenandoahHeap* const heap = ShenandoahHeap::heap();
!   heap->set_concurrent_mark_in_progress(false);
-   heap->mark_complete_marking_context();
  }
  
  void ShenandoahConcurrentMark::finish_mark_work() {
    // Finally mark everything else we've got in our queues during the previous steps.
    // It does two different things for concurrent vs. mark-compact GC:
--- 303,12 ---
    finish_mark_work();
    assert(task_queues()->is_empty(), "Should be empty");
    TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
    TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
  
!   _generation->set_concurrent_mark_in_progress(false);
!   _generation->set_mark_complete();
  }
  
  void ShenandoahConcurrentMark::finish_mark_work() {
    // Finally mark everything else we've got in our queues during the previous steps.
    // It does two different things for concurrent vs. mark-compact GC:

*** 280,17 ***
    uint nworkers = heap->workers()->active_workers();
    task_queues()->reserve(nworkers);
  
    StrongRootsScope scope(nworkers);
    TaskTerminator terminator(nworkers, task_queues());
-   ShenandoahFinalMarkingTask task(this, &terminator, ShenandoahStringDedup::is_enabled());
-   heap->workers()->run_task(&task);
  
!   assert(task_queues()->is_empty(), "Should be empty");
! }
  
  
! void ShenandoahConcurrentMark::cancel() {
-   clear();
-   ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->ref_processor();
-   rp->abandon_partial_discovery();
  }
--- 322,29 ---
    uint nworkers = heap->workers()->active_workers();
    task_queues()->reserve(nworkers);
  
    StrongRootsScope scope(nworkers);
    TaskTerminator terminator(nworkers, task_queues());
  
!   switch (_generation->generation_mode()) {
!     case YOUNG:{
+       ShenandoahFinalMarkingTask<YOUNG> task(this, &terminator, ShenandoahStringDedup::is_enabled());
+       heap->workers()->run_task(&task);
+       break;
+     }
+     case OLD:{
+       ShenandoahFinalMarkingTask<OLD> task(this, &terminator, ShenandoahStringDedup::is_enabled());
+       heap->workers()->run_task(&task);
+       break;
+     }
+     case GLOBAL:{
+       ShenandoahFinalMarkingTask<GLOBAL> task(this, &terminator, ShenandoahStringDedup::is_enabled());
+       heap->workers()->run_task(&task);
+       break;
+     }
+     default:
+       ShouldNotReachHere();
+   }
  
  
!   assert(task_queues()->is_empty(), "Should be empty");
  }
< prev index next >