< prev index next >

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

Print this page
*** 25,110 ***
  
  #include "precompiled.hpp"
  
  #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  #include "gc/shenandoah/shenandoahClosures.inline.hpp"
  #include "gc/shenandoah/shenandoahMark.inline.hpp"
  #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
  #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
  #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp"
  #include "gc/shenandoah/shenandoahUtils.hpp"
  #include "gc/shenandoah/shenandoahVerifier.hpp"
  
! ShenandoahMarkRefsSuperClosure::ShenandoahMarkRefsSuperClosure(ShenandoahObjToScanQueue* q,  ShenandoahReferenceProcessor* rp) :
    MetadataVisitingOopIterateClosure(rp),
    _queue(q),
    _mark_context(ShenandoahHeap::heap()->marking_context()),
    _weak(false)
  { }
  
! ShenandoahMark::ShenandoahMark() :
!   _task_queues(ShenandoahHeap::heap()->marking_context()->task_queues()) {
  }
  
! void ShenandoahMark::clear() {
!   // Clean up marking stacks.
-   ShenandoahObjToScanQueueSet* queues = ShenandoahHeap::heap()->marking_context()->task_queues();
-   queues->clear();
- 
-   // Cancel SATB buffers.
-   ShenandoahBarrierSet::satb_mark_queue_set().abandon_partial_marking();
- }
- 
- template <bool CANCELLABLE, StringDedupMode STRING_DEDUP>
- void ShenandoahMark::mark_loop_prework(uint w, TaskTerminator *t, ShenandoahReferenceProcessor *rp, StringDedup::Requests* const req) {
    ShenandoahObjToScanQueue* q = get_queue(w);
  
    ShenandoahHeap* const heap = ShenandoahHeap::heap();
    ShenandoahLiveData* ld = heap->get_liveness_cache(w);
  
    // TODO: We can clean up this if we figure out how to do templated oop closures that
    // play nice with specialized_oop_iterators.
    if (heap->unload_classes()) {
!     if (heap->has_forwarded_objects()) {
!       using Closure = ShenandoahMarkUpdateRefsMetadataClosure;
!       Closure cl(q, rp);
!       mark_loop_work<Closure, CANCELLABLE, STRING_DEDUP>(&cl, ld, w, t, req);
      } else {
!       using Closure = ShenandoahMarkRefsMetadataClosure;
!       Closure cl(q, rp);
!       mark_loop_work<Closure, CANCELLABLE, STRING_DEDUP>(&cl, ld, w, t, req);
      }
    } else {
!     if (heap->has_forwarded_objects()) {
!       using Closure = ShenandoahMarkUpdateRefsClosure;
!       Closure cl(q, rp);
!       mark_loop_work<Closure, CANCELLABLE, STRING_DEDUP>(&cl, ld, w, t, req);
      } else {
!       using Closure = ShenandoahMarkRefsClosure;
!       Closure cl(q, rp);
!       mark_loop_work<Closure, CANCELLABLE, STRING_DEDUP>(&cl, ld, w, t, req);
      }
    }
  
    heap->flush_liveness_cache(w);
  }
  
! void ShenandoahMark::mark_loop(uint worker_id, TaskTerminator* terminator, ShenandoahReferenceProcessor *rp,
                 bool cancellable, StringDedupMode dedup_mode, StringDedup::Requests* const req) {
    if (cancellable) {
      switch(dedup_mode) {
        case NO_DEDUP:
!         mark_loop_prework<true, NO_DEDUP>(worker_id, terminator, rp, req);
          break;
        case ENQUEUE_DEDUP:
!         mark_loop_prework<true, ENQUEUE_DEDUP>(worker_id, terminator, rp, req);
          break;
        case ALWAYS_DEDUP:
!         mark_loop_prework<true, ALWAYS_DEDUP>(worker_id, terminator, rp, req);
          break;
      }
    } else {
      switch(dedup_mode) {
        case NO_DEDUP:
!         mark_loop_prework<false, NO_DEDUP>(worker_id, terminator, rp, req);
          break;
        case ENQUEUE_DEDUP:
!         mark_loop_prework<false, ENQUEUE_DEDUP>(worker_id, terminator, rp, req);
          break;
        case ALWAYS_DEDUP:
!         mark_loop_prework<false, ALWAYS_DEDUP>(worker_id, terminator, rp, req);
          break;
      }
    }
  }
  
! template <class T, bool CANCELLABLE, StringDedupMode STRING_DEDUP>
  void ShenandoahMark::mark_loop_work(T* cl, ShenandoahLiveData* live_data, uint worker_id, TaskTerminator *terminator, StringDedup::Requests* const req) {
    uintx stride = ShenandoahMarkLoopStride;
  
    ShenandoahHeap* heap = ShenandoahHeap::heap();
    ShenandoahObjToScanQueueSet* queues = task_queues();
    ShenandoahObjToScanQueue* q;
    ShenandoahMarkTask t;
  
!   heap->ref_processor()->set_mark_closure(worker_id, cl);
  
    /*
     * Process outstanding queues, if any.
     *
     * There can be more queues than workers. To deal with the imbalance, we claim
--- 25,127 ---
  
  #include "precompiled.hpp"
  
  #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  #include "gc/shenandoah/shenandoahClosures.inline.hpp"
+ #include "gc/shenandoah/shenandoahGeneration.hpp"
  #include "gc/shenandoah/shenandoahMark.inline.hpp"
  #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
  #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
  #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp"
  #include "gc/shenandoah/shenandoahUtils.hpp"
  #include "gc/shenandoah/shenandoahVerifier.hpp"
  
! ShenandoahMarkRefsSuperClosure::ShenandoahMarkRefsSuperClosure(ShenandoahObjToScanQueue* q,  ShenandoahReferenceProcessor* rp, ShenandoahObjToScanQueue* old_q) :
    MetadataVisitingOopIterateClosure(rp),
    _queue(q),
+   _old_queue(old_q),
    _mark_context(ShenandoahHeap::heap()->marking_context()),
    _weak(false)
  { }
  
! ShenandoahMark::ShenandoahMark(ShenandoahGeneration* generation) :
!   _generation(generation),
+   _task_queues(generation->task_queues()),
+   _old_gen_task_queues(generation->old_gen_task_queues()) {
  }
  
! template <GenerationMode GENERATION, bool CANCELLABLE, StringDedupMode STRING_DEDUP>
! void ShenandoahMark::mark_loop_prework(uint w, TaskTerminator *t, ShenandoahReferenceProcessor *rp, StringDedup::Requests* const req, bool update_refs) {
    ShenandoahObjToScanQueue* q = get_queue(w);
+   ShenandoahObjToScanQueue* old = get_old_queue(w);
  
    ShenandoahHeap* const heap = ShenandoahHeap::heap();
    ShenandoahLiveData* ld = heap->get_liveness_cache(w);
  
    // TODO: We can clean up this if we figure out how to do templated oop closures that
    // play nice with specialized_oop_iterators.
    if (heap->unload_classes()) {
!     if (update_refs) {
!       using Closure = ShenandoahMarkUpdateRefsMetadataClosure<GENERATION>;
!       Closure cl(q, rp, old);
!       mark_loop_work<Closure, GENERATION, CANCELLABLE, STRING_DEDUP>(&cl, ld, w, t, req);
      } else {
!       using Closure = ShenandoahMarkRefsMetadataClosure<GENERATION>;
!       Closure cl(q, rp, old);
!       mark_loop_work<Closure, GENERATION, CANCELLABLE, STRING_DEDUP>(&cl, ld, w, t, req);
      }
    } else {
!     if (update_refs) {
!       using Closure = ShenandoahMarkUpdateRefsClosure<GENERATION>;
!       Closure cl(q, rp, old);
!       mark_loop_work<Closure, GENERATION, CANCELLABLE, STRING_DEDUP>(&cl, ld, w, t, req);
      } else {
!       using Closure = ShenandoahMarkRefsClosure<GENERATION>;
!       Closure cl(q, rp, old);
!       mark_loop_work<Closure, GENERATION, CANCELLABLE, STRING_DEDUP>(&cl, ld, w, t, req);
      }
    }
  
    heap->flush_liveness_cache(w);
  }
  
! template<bool CANCELLABLE, StringDedupMode STRING_DEDUP>
+ void ShenandoahMark::mark_loop(GenerationMode generation, uint worker_id, TaskTerminator* terminator, ShenandoahReferenceProcessor *rp, StringDedup::Requests* const req) {
+   bool update_refs = ShenandoahHeap::heap()->has_forwarded_objects();
+   switch (generation) {
+     case YOUNG:
+       mark_loop_prework<YOUNG, CANCELLABLE, STRING_DEDUP>(worker_id, terminator, rp, req, update_refs);
+       break;
+     case OLD:
+       // Old generation collection only performs marking, it should not update references.
+       mark_loop_prework<OLD, CANCELLABLE, STRING_DEDUP>(worker_id, terminator, rp, req, false);
+       break;
+     case GLOBAL:
+       mark_loop_prework<GLOBAL, CANCELLABLE, STRING_DEDUP>(worker_id, terminator, rp, req, update_refs);
+       break;
+     default:
+       ShouldNotReachHere();
+       break;
+   }
+ }
+ 
+ void ShenandoahMark::mark_loop(GenerationMode generation, uint worker_id, TaskTerminator* terminator, ShenandoahReferenceProcessor *rp,
                 bool cancellable, StringDedupMode dedup_mode, StringDedup::Requests* const req) {
    if (cancellable) {
      switch(dedup_mode) {
        case NO_DEDUP:
!         mark_loop<true, NO_DEDUP>(generation, worker_id, terminator, rp, req);
          break;
        case ENQUEUE_DEDUP:
!         mark_loop<true, ENQUEUE_DEDUP>(generation, worker_id, terminator, rp, req);
          break;
        case ALWAYS_DEDUP:
!         mark_loop<true, ALWAYS_DEDUP>(generation, worker_id, terminator, rp, req);
          break;
      }
    } else {
      switch(dedup_mode) {
        case NO_DEDUP:
!         mark_loop<false, NO_DEDUP>(generation, worker_id, terminator, rp, req);
          break;
        case ENQUEUE_DEDUP:
!         mark_loop<false, ENQUEUE_DEDUP>(generation, worker_id, terminator, rp, req);
          break;
        case ALWAYS_DEDUP:
!         mark_loop<false, ALWAYS_DEDUP>(generation, worker_id, terminator, rp, req);
          break;
      }
    }
  }
  
! template <class T, GenerationMode GENERATION, bool CANCELLABLE, StringDedupMode STRING_DEDUP>
  void ShenandoahMark::mark_loop_work(T* cl, ShenandoahLiveData* live_data, uint worker_id, TaskTerminator *terminator, StringDedup::Requests* const req) {
    uintx stride = ShenandoahMarkLoopStride;
  
    ShenandoahHeap* heap = ShenandoahHeap::heap();
    ShenandoahObjToScanQueueSet* queues = task_queues();
    ShenandoahObjToScanQueue* q;
    ShenandoahMarkTask t;
  
!   assert(heap->active_generation()->generation_mode() == GENERATION, "Sanity");
+   heap->active_generation()->ref_processor()->set_mark_closure(worker_id, cl);
  
    /*
     * Process outstanding queues, if any.
     *
     * There can be more queues than workers. To deal with the imbalance, we claim

*** 153,22 ***
          break;
        }
      }
    }
    q = get_queue(worker_id);
  
!   ShenandoahSATBBufferClosure drain_satb(q);
    SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
  
    /*
     * Normal marking loop:
     */
    while (true) {
      if (CANCELLABLE && heap->check_cancelled_gc_and_yield()) {
        return;
      }
- 
      while (satb_mq_set.completed_buffers_num() > 0) {
        satb_mq_set.apply_closure_to_completed_buffer(&drain_satb);
      }
  
      uint work = 0;
--- 170,22 ---
          break;
        }
      }
    }
    q = get_queue(worker_id);
+   ShenandoahObjToScanQueue* old = get_old_queue(worker_id);
  
!   ShenandoahSATBBufferClosure<GENERATION> drain_satb(q, old);
    SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
  
    /*
     * Normal marking loop:
     */
    while (true) {
      if (CANCELLABLE && heap->check_cancelled_gc_and_yield()) {
        return;
      }
      while (satb_mq_set.completed_buffers_num() > 0) {
        satb_mq_set.apply_closure_to_completed_buffer(&drain_satb);
      }
  
      uint work = 0;
< prev index next >