< prev index next >

src/share/vm/gc/shenandoah/shenandoahHeap.cpp

Print this page

        

@@ -2404,64 +2404,81 @@
   T cl;
   ShenandoahHeap* _heap;
   ShenandoahHeapRegionSet* _regions;
 
 public:
-  ShenandoahUpdateHeapRefsTask() :
+  ShenandoahUpdateHeapRefsTask(ShenandoahHeapRegionSet* regions) :
     AbstractGangTask("Concurrent Update References Task"),
     cl(T()),
     _heap(ShenandoahHeap::heap()),
-    _regions(ShenandoahHeap::heap()->regions()) {
-    _regions->clear_current_index();
+    _regions(regions) {
   }
 
   void work(uint worker_id) {
     ShenandoahHeapRegion* r = _regions->claim_next();
-    while (r != NULL && ! _heap->cancelled_concgc()) {
+    while (r != NULL) {
       if (! _heap->in_collection_set(r) &&
           ! r->is_empty()) {
         _heap->marked_object_oop_safe_iterate(r, &cl);
       } else if (_heap->in_collection_set(r)) {
         HeapWord* bottom = r->bottom();
         HeapWord* top = _heap->complete_top_at_mark_start(r->bottom());
         if (top > bottom) {
           _heap->complete_mark_bit_map()->clear_range_large(MemRegion(bottom, top));
         }
       }
+      if (_heap->cancelled_concgc()) {
+        return;
+      }
       r = _regions->claim_next();
     }
   }
 };
 
-void ShenandoahHeap::concurrent_update_heap_references() {
-  _shenandoah_policy->record_phase_start(ShenandoahCollectorPolicy::conc_update_refs);
+void ShenandoahHeap::update_heap_references(ShenandoahHeapRegionSet* update_regions) {
   if (UseShenandoahMatrix) {
-    ShenandoahUpdateHeapRefsTask<ShenandoahUpdateHeapRefsMatrixClosure> task;
+    ShenandoahUpdateHeapRefsTask<ShenandoahUpdateHeapRefsMatrixClosure> task(update_regions);
     workers()->run_task(&task);
   } else {
-    ShenandoahUpdateHeapRefsTask<ShenandoahUpdateHeapRefsClosure> task;
+    ShenandoahUpdateHeapRefsTask<ShenandoahUpdateHeapRefsClosure> task(update_regions);
     workers()->run_task(&task);
   }
+}
+
+void ShenandoahHeap::concurrent_update_heap_references() {
+  _shenandoah_policy->record_phase_start(ShenandoahCollectorPolicy::conc_update_refs);
+  ShenandoahHeapRegionSet* update_regions = regions();
+  update_regions->clear_current_index();
+  update_heap_references(update_regions);
   _shenandoah_policy->record_phase_end(ShenandoahCollectorPolicy::conc_update_refs);
 }
 
 void ShenandoahHeap::prepare_update_refs() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   set_evacuation_in_progress_at_safepoint(false);
   set_update_refs_in_progress(true);
   ensure_parsability(true);
+  if (UseShenandoahMatrix) {
   connection_matrix()->clear_all();
+  }
   for (uint i = 0; i < _num_regions; i++) {
     ShenandoahHeapRegion* r = _ordered_regions->get(i);
     r->set_concurrent_iteration_safe_limit(r->top());
   }
 }
 
 void ShenandoahHeap::finish_update_refs() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 
-  if (! cancelled_concgc()) {
+  if (cancelled_concgc()) {
+    // Finish updating references where we left off.
+    clear_cancelled_concgc();
+    ShenandoahHeapRegionSet* update_regions = regions();
+    update_heap_references(update_regions);
+  }
+
+  assert(! cancelled_concgc(), "Should have been done right before");
     concurrentMark()->update_roots(ShenandoahCollectorPolicy::final_update_refs_roots);
     recycle_dirty_regions();
     set_need_update_refs(false);
 
     if (ShenandoahVerify) {

@@ -2479,11 +2496,10 @@
           assert (!in_collection_set(r), "collection set should be clear");
           _free_regions->add_region(r);
         }
       }
     }
-  }
   set_update_refs_in_progress(false);
 }
 
 class ShenandoahVerifyUpdateRefsClosure : public ExtendedOopClosure {
 private:
< prev index next >