# HG changeset patch # User tonyp # Date 1462463487 25200 # Node ID 8144ec8f789e49fc8e7fdfc603db5df27006bfec # Parent d51ca2fac8d6687ac7b3483cb8e237705eb493e5 8155257: ParNew/CMS: Clean up promoted object tracking Reviewed-by: jmasa, ysr diff -r d51ca2fac8d6 -r 8144ec8f789e hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Tue May 03 07:23:23 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Thu May 05 08:51:27 2016 -0700 @@ -1019,7 +1019,7 @@ return NULL; } } - assert(promoInfo->has_spooling_space(), "Control point invariant"); + assert(!promoInfo->tracking() || promoInfo->has_spooling_space(), "Control point invariant"); const size_t alloc_sz = CompactibleFreeListSpace::adjustObjectSize(word_sz); HeapWord* obj_ptr = ps->lab.alloc(alloc_sz); if (obj_ptr == NULL) { @@ -1094,6 +1094,12 @@ CMSParGCThreadState* ps = _par_gc_thread_states[thread_num]; ParScanWithoutBarrierClosure* dummy_cl = NULL; ps->promo.promoted_oops_iterate_nv(dummy_cl); + + // Because card-scanning has been completed, subsequent phases + // (e.g., reference processing) will not need to recognize which + // objects have been promoted during this GC. So, we can now disable + // promotion tracking. + ps->promo.stopTrackingPromotions(); } bool ConcurrentMarkSweepGeneration::should_collect(bool full, @@ -2032,6 +2038,12 @@ _capacity_at_prologue = capacity(); _used_at_prologue = used(); + // We enable promotion tracking so that card-scanning can recognize + // which objects have been promoted during this GC and skip them. + for (uint i = 0; i < ParallelGCThreads; i++) { + _par_gc_thread_states[i]->promo.startTrackingPromotions(); + } + // Delegate to CMScollector which knows how to coordinate between // this and any other CMS generations that it is responsible for // collecting. @@ -2118,9 +2130,15 @@ void ConcurrentMarkSweepGeneration::gc_epilogue(bool full) { collector()->gc_epilogue(full); - // Also reset promotion tracking in par gc thread states. + // When using ParNew, promotion tracking should have already been + // disabled. However, the prologue (which enables promotion + // tracking) and epilogue are called irrespective of the type of + // GC. So they will also be called before and after Full GCs, during + // which promotion tracking will not be explicitly disabled. So, + // it's safer to also disable it here too (to be symmetric with + // enabling it in the prologue). for (uint i = 0; i < ParallelGCThreads; i++) { - _par_gc_thread_states[i]->promo.stopTrackingPromotions(i); + _par_gc_thread_states[i]->promo.stopTrackingPromotions(); } } @@ -2431,9 +2449,6 @@ void ConcurrentMarkSweepGeneration::save_marks() { // delegate to CMS space cmsSpace()->save_marks(); - for (uint i = 0; i < ParallelGCThreads; i++) { - _par_gc_thread_states[i]->promo.startTrackingPromotions(); - } } bool ConcurrentMarkSweepGeneration::no_allocs_since_save_marks() { diff -r d51ca2fac8d6 -r 8144ec8f789e hotspot/src/share/vm/gc/cms/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Tue May 03 07:23:23 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Thu May 05 08:51:27 2016 -0700 @@ -476,7 +476,6 @@ // Inform old gen that we're done. _old_gen.par_promote_alloc_done(i); - _old_gen.par_oop_since_save_marks_iterate_done(i); } if (UseConcMarkSweepGC) { @@ -619,6 +618,16 @@ // "evacuate followers". par_scan_state.evacuate_followers_closure().do_void(); + + // This will collapse this worker's promoted object list that's + // created during the main ParNew parallel phase of ParNew. This has + // to be called after all workers have finished promoting objects + // and scanning promoted objects. It should be safe calling it from + // here, given that we can only reach here after all thread have + // offered termination, i.e., after there is no more work to be + // done. It will also disable promotion tracking for the rest of + // this GC as it's not necessary to be on during reference processing. + _old_gen->par_oop_since_save_marks_iterate_done((int) worker_id); } ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) diff -r d51ca2fac8d6 -r 8144ec8f789e hotspot/src/share/vm/gc/cms/promotionInfo.cpp --- a/hotspot/src/share/vm/gc/cms/promotionInfo.cpp Tue May 03 07:23:23 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/promotionInfo.cpp Thu May 05 08:51:27 2016 -0700 @@ -252,13 +252,15 @@ } void PromotionInfo::startTrackingPromotions() { + assert(noPromotions(), "sanity"); assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, "spooling inconsistency?"); _firstIndex = _nextIndex = 1; _tracking = true; } -void PromotionInfo::stopTrackingPromotions(uint worker_id) { +void PromotionInfo::stopTrackingPromotions() { + assert(noPromotions(), "we should have torn down the lists by now"); assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, "spooling inconsistency?"); _firstIndex = _nextIndex = 1; diff -r d51ca2fac8d6 -r 8144ec8f789e hotspot/src/share/vm/gc/cms/promotionInfo.hpp --- a/hotspot/src/share/vm/gc/cms/promotionInfo.hpp Tue May 03 07:23:23 2016 -0700 +++ b/hotspot/src/share/vm/gc/cms/promotionInfo.hpp Thu May 05 08:51:27 2016 -0700 @@ -144,7 +144,7 @@ return _promoHead == NULL; } void startTrackingPromotions(); - void stopTrackingPromotions(uint worker_id = 0); + void stopTrackingPromotions(); bool tracking() const { return _tracking; } void track(PromotedObject* trackOop); // keep track of a promoted oop // The following variant must be used when trackOop is not fully