--- old/src/share/vm/gc/shenandoah/shenandoahHeap.cpp 2017-05-03 18:44:41.857101890 +0200 +++ new/src/share/vm/gc/shenandoah/shenandoahHeap.cpp 2017-05-03 18:44:41.797102934 +0200 @@ -2406,17 +2406,16 @@ 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); @@ -2427,20 +2426,29 @@ _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 task; + ShenandoahUpdateHeapRefsTask task(update_regions); workers()->run_task(&task); } else { - ShenandoahUpdateHeapRefsTask task; + ShenandoahUpdateHeapRefsTask 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); } @@ -2449,7 +2457,9 @@ set_evacuation_in_progress_at_safepoint(false); set_update_refs_in_progress(true); ensure_parsability(true); - connection_matrix()->clear_all(); + 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()); @@ -2459,26 +2469,32 @@ void ShenandoahHeap::finish_update_refs() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - if (! cancelled_concgc()) { - concurrentMark()->update_roots(ShenandoahCollectorPolicy::final_update_refs_roots); - recycle_dirty_regions(); - set_need_update_refs(false); + if (cancelled_concgc()) { + // Finish updating references where we left off. + clear_cancelled_concgc(); + ShenandoahHeapRegionSet* update_regions = regions(); + update_heap_references(update_regions); + } - if (ShenandoahVerify) { - verify_update_refs(); - } + 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); - { - // Rebuild the free set - ShenandoahHeapLock hl(this); - _free_regions->clear(); - size_t end = _ordered_regions->active_regions(); - for (size_t i = 0; i < end; i++) { - ShenandoahHeapRegion* r = _ordered_regions->get(i); - if (!r->is_humongous()) { - assert (!in_collection_set(r), "collection set should be clear"); - _free_regions->add_region(r); - } + if (ShenandoahVerify) { + verify_update_refs(); + } + + { + // Rebuild the free set + ShenandoahHeapLock hl(this); + _free_regions->clear(); + size_t end = _ordered_regions->active_regions(); + for (size_t i = 0; i < end; i++) { + ShenandoahHeapRegion* r = _ordered_regions->get(i); + if (!r->is_humongous()) { + assert (!in_collection_set(r), "collection set should be clear"); + _free_regions->add_region(r); } } }