diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp index 7fb048f876e..e54d3a9b6e3 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp @@ -192,7 +192,11 @@ bool ShenandoahOldHeuristics::prime_collection_set(ShenandoahCollectionSet* coll // We have added the last of our collection candidates to a mixed collection. // Any triggers that occurred during mixed evacuations may no longer be valid. They can retrigger if appropriate. clear_triggers(); - _old_generation->transition_to(ShenandoahOldGeneration::IDLE); + if (has_coalesce_and_fill_candidates()) { + _old_generation->transition_to(ShenandoahOldGeneration::WAITING_FOR_FILL); + } else { + _old_generation->transition_to(ShenandoahOldGeneration::IDLE); + } } else if (included_old_regions == 0) { // We have candidates, but none were included for evacuation - are they all pinned? // or did we just not have enough room for any of them in this collection set? diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index 174a81d1dd1..263d520fea0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -852,8 +852,9 @@ bool ShenandoahControlThread::is_explicit_gc(GCCause::Cause cause) const { } bool ShenandoahControlThread::is_implicit_gc(GCCause::Cause cause) const { - return !is_explicit_gc(cause) && - (cause != GCCause::_shenandoah_concurrent_gc); + return !is_explicit_gc(cause) + && cause != GCCause::_shenandoah_concurrent_gc + && cause != GCCause::_no_gc; } void ShenandoahControlThread::request_gc(GCCause::Cause cause) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 4438a1725ce..ecf4f2ab1b3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -1302,7 +1302,7 @@ void ShenandoahFreeSet::log_status() { #ifdef ASSERT // Dump of the FreeSet details is only enabled if assertions are enabled - { + if (LogTarget(Debug, gc, free)::is_enabled()) { #define BUFFER_SIZE 80 size_t retired_old = 0; size_t retired_old_humongous = 0; @@ -1324,10 +1324,10 @@ void ShenandoahFreeSet::log_status() { for (uint i = 0; i < BUFFER_SIZE; i++) { buffer[i] = '\0'; } - log_info(gc, free)("FreeSet map legend:" + log_debug(gc, free)("FreeSet map legend:" " M:mutator_free C:collector_free O:old_collector_free" " H:humongous ~:retired old _:retired young"); - log_info(gc, free)(" mutator free range [" SIZE_FORMAT ".." SIZE_FORMAT "], " + log_debug(gc, free)(" mutator free range [" SIZE_FORMAT ".." SIZE_FORMAT "], " " collector free range [" SIZE_FORMAT ".." SIZE_FORMAT "], " "old collector free range [" SIZE_FORMAT ".." SIZE_FORMAT "] allocates from %s", _free_sets.leftmost(Mutator), _free_sets.rightmost(Mutator), @@ -1339,7 +1339,7 @@ void ShenandoahFreeSet::log_status() { ShenandoahHeapRegion *r = _heap->get_region(i); uint idx = i % 64; if ((i != 0) && (idx == 0)) { - log_info(gc, free)(" %6u: %s", i-64, buffer); + log_debug(gc, free)(" %6u: %s", i-64, buffer); } if (_free_sets.in_free_set(i, Mutator)) { assert(!r->is_old(), "Old regions should not be in mutator_free set"); @@ -1384,7 +1384,7 @@ void ShenandoahFreeSet::log_status() { } else { remnant = 64; } - log_info(gc, free)(" %6u: %s", (uint) (_heap->num_regions() - remnant), buffer); + log_debug(gc, free)(" %6u: %s", (uint) (_heap->num_regions() - remnant), buffer); size_t total_young = retired_young + retired_young_humongous; size_t total_old = retired_old + retired_old_humongous; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp index 982d3525f80..59163d1f29c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp @@ -74,7 +74,7 @@ void ShenandoahGlobalGeneration::set_concurrent_mark_in_progress(bool in_progres // because the global generation includes the old generation, but we // want the global collect to start from a clean slate and we don't want // any stale state in the old generation. - heap->cancel_old_gc(); + assert(!heap->is_concurrent_old_mark_in_progress(), "Old cycle should not be running."); } heap->set_concurrent_young_mark_in_progress(in_progress); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 55420e2625e..a3c9dce3ee9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1163,18 +1163,24 @@ void ShenandoahHeap::retire_plab(PLAB* plab) { void ShenandoahHeap::cancel_old_gc() { shenandoah_assert_safepoint(); assert(_old_generation != nullptr, "Should only have mixed collections in generation mode."); - log_info(gc)("Terminating old gc cycle."); - - // Stop marking - old_generation()->cancel_marking(); - // Stop coalescing undead objects - set_prepare_for_old_mark_in_progress(false); - // Stop tracking old regions - old_heuristics()->abandon_collection_candidates(); - // Remove old generation access to young generation mark queues - young_generation()->set_old_gen_task_queues(nullptr); - // Transition to IDLE now. - _old_generation->transition_to(ShenandoahOldGeneration::IDLE); + if (_old_generation->state() == ShenandoahOldGeneration::IDLE) { + assert(!old_generation()->is_concurrent_mark_in_progress(), "Cannot be marking in IDLE"); + assert(!old_heuristics()->has_coalesce_and_fill_candidates(), "Cannot have coalesce and fill candidates in IDLE"); + assert(!old_heuristics()->unprocessed_old_collection_candidates(), "Cannot have mixed collection candidates in IDLE"); + assert(!young_generation()->is_bootstrap_cycle(), "Cannot have old mark queues if IDLE"); + } else { + log_info(gc)("Terminating old gc cycle."); + // Stop marking + old_generation()->cancel_marking(); + // Stop coalescing undead objects + set_prepare_for_old_mark_in_progress(false); + // Stop tracking old regions + old_heuristics()->abandon_collection_candidates(); + // Remove old generation access to young generation mark queues + young_generation()->set_old_gen_task_queues(nullptr); + // Transition to IDLE now. + _old_generation->transition_to(ShenandoahOldGeneration::IDLE); + } } // xfer_limit is the maximum we're able to transfer from young to old diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp index e082cdcde12..8e4ec64e0a5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp @@ -76,10 +76,12 @@ void ShenandoahRegulatorThread::regulate_concurrent_cycles() { log_info(gc)("Heuristics request for global (unload classes) accepted."); } } else { - if (start_old_cycle()) { - log_info(gc)("Heuristics request for old collection accepted"); - } else if (start_young_cycle()) { - log_info(gc)("Heuristics request for young collection accepted"); + if (_young_heuristics->should_start_gc()) { + if (start_old_cycle()) { + log_info(gc)("Heuristics request for old collection accepted"); + } else if (request_concurrent_gc(YOUNG)) { + log_info(gc)("Heuristics request for young collection accepted"); + } } } } else if (mode == ShenandoahControlThread::servicing_old) {