< 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 +84,14 @@
  
    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();
+     ShenandoahReferenceProcessor* rp = heap->active_generation()->ref_processor();
      assert(rp != NULL, "need reference processor");
      StringDedup::Requests requests;
-     _cm->mark_loop(worker_id, _terminator, rp,
+     _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 +136,105 @@
  
    void work(uint worker_id) {
      ShenandoahHeap* heap = ShenandoahHeap::heap();
  
      ShenandoahParallelWorkerSession worker_session(worker_id);
-     ShenandoahReferenceProcessor* rp = heap->ref_processor();
      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 cl(q);
+       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             mark_cl(q, rp);
+       ShenandoahMarkRefsClosure<GENERATION> mark_cl(q, rp, old);
        ShenandoahSATBAndRemarkThreadsClosure tc(satb_mq_set,
                                                 ShenandoahIUBarrier ? &mark_cl : NULL);
        Threads::threads_do(&tc);
      }
-     _cm->mark_loop(worker_id, _terminator, rp,
+     _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() :
-   ShenandoahMark() {}
+ 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);
  };
  
- ShenandoahMarkConcurrentRootsTask::ShenandoahMarkConcurrentRootsTask(ShenandoahObjToScanQueueSet* qs,
-                                                                      ShenandoahReferenceProcessor* rp,
-                                                                      ShenandoahPhaseTimings::Phase phase,
-                                                                      uint nworkers) :
+ 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");
  }
  
- void ShenandoahMarkConcurrentRootsTask::work(uint worker_id) {
+ template<GenerationMode GENERATION>
+ void ShenandoahMarkConcurrentRootsTask<GENERATION>::work(uint worker_id) {
    ShenandoahConcurrentWorkerSession worker_session(worker_id);
    ShenandoahObjToScanQueue* q = _queue_set->queue(worker_id);
-   ShenandoahMarkRefsClosure cl(q, _rp);
+   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");
  
-   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);
+   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 +255,32 @@
    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);
+     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 +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());
  
-   ShenandoahHeap* const heap = ShenandoahHeap::heap();
-   heap->set_concurrent_mark_in_progress(false);
-   heap->mark_complete_marking_context();
+   _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 +322,29 @@
    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");
- }
+   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();
+   }
  
  
- void ShenandoahConcurrentMark::cancel() {
-   clear();
-   ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->ref_processor();
-   rp->abandon_partial_discovery();
+   assert(task_queues()->is_empty(), "Should be empty");
  }
< prev index next >