diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp index 33c91e27be5..0789fd5cb1c 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp @@ -576,7 +576,7 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() { } else if (has_coalesce_and_fill_candidates()) { _old_generation->transition_to(ShenandoahOldGeneration::FILLING); } else { - _old_generation->transition_to(ShenandoahOldGeneration::WAITING_FOR_BOOTSTRAP); + _old_generation->transition_to(ShenandoahOldGeneration::IDLE); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index 8cd8a390c4a..1873d818093 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -55,7 +55,7 @@ bool ShenandoahDegenGC::collect(GCCause::Cause cause) { vmop_degenerated(); ShenandoahHeap* heap = ShenandoahHeap::heap(); if (heap->mode()->is_generational()) { - bool is_bootstrap_gc = heap->old_generation()->is_bootstrapping(); + bool is_bootstrap_gc = heap->young_generation()->is_bootstrap_cycle(); heap->mmu_tracker()->record_degenerated(GCId::current(), is_bootstrap_gc); const char* msg = is_bootstrap_gc? "At end of Degenerated Bootstrap Old GC": "At end of Degenerated Young GC"; heap->log_heap_status(msg); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 064f43ffd6b..aa6a4a9bab2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -422,12 +422,11 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(const She } // Coalescing threads completed and nothing was cancelled. it is safe to transition from this state. - old_generation->transition_to(ShenandoahOldGeneration::WAITING_FOR_BOOTSTRAP); + old_generation->transition_to(ShenandoahOldGeneration::IDLE); return; } - case ShenandoahOldGeneration::WAITING_FOR_BOOTSTRAP: - old_generation->transition_to(ShenandoahOldGeneration::BOOTSTRAPPING); - case ShenandoahOldGeneration::BOOTSTRAPPING: { + case ShenandoahOldGeneration::IDLE: + old_generation->transition_to(ShenandoahOldGeneration::MARKING); // Configure the young generation's concurrent mark to put objects in // old regions into the concurrent mark queues associated with the old // generation. The young cycle will run as normal except that rather than @@ -450,8 +449,6 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(const She // and init mark for the concurrent mark. All of that work will have been // done by the bootstrapping young cycle. set_gc_mode(servicing_old); - old_generation->transition_to(ShenandoahOldGeneration::MARKING); - } case ShenandoahOldGeneration::MARKING: { ShenandoahGCSession session(request.cause, old_generation); bool marking_complete = resume_concurrent_old_cycle(old_generation, request.cause); @@ -644,12 +641,6 @@ void ShenandoahGenerationalControlThread::service_stw_degenerated_cycle(const Sh if (request.generation->is_global()) { assert(_heap->old_generation()->task_queues()->is_empty(), "Unexpected old generation marking tasks"); assert(_heap->global_generation()->task_queues()->is_empty(), "Unexpected global generation marking tasks"); - } else { - assert(request.generation->is_young(), "Expected degenerated young cycle, if not global."); - ShenandoahOldGeneration* old = _heap->old_generation(); - if (old->is_bootstrapping()) { - old->transition_to(ShenandoahOldGeneration::MARKING); - } } } @@ -681,7 +672,7 @@ bool ShenandoahGenerationalControlThread::request_concurrent_gc(ShenandoahGenera // Cancel the old GC and wait for the control thread to start servicing the new request. log_info(gc)("Preempting old generation mark to allow %s GC", generation->name()); while (gc_mode() == servicing_old) { - ShenandoahHeap::heap()->cancel_gc(GCCause::_shenandoah_concurrent_gc); + _heap->cancel_gc(GCCause::_shenandoah_concurrent_gc); notify_control_thread(ml, GCCause::_shenandoah_concurrent_gc, generation); ml.wait(); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index 16a24da8b1c..bbfa0961e86 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -114,7 +114,7 @@ ShenandoahOldGeneration::ShenandoahOldGeneration(uint max_queues) _promotable_regular_regions(0), _is_parsable(true), _card_scan(nullptr), - _state(WAITING_FOR_BOOTSTRAP), + _state(IDLE), _growth_percent_before_collection(INITIAL_GROWTH_PERCENT_BEFORE_COLLECTION) { assert(type() == ShenandoahGenerationType::OLD, "OO sanity"); @@ -339,7 +339,7 @@ void ShenandoahOldGeneration::cancel_gc() { shenandoah_assert_safepoint(); if (is_idle()) { #ifdef ASSERT - validate_waiting_for_bootstrap(); + validate_idle(); #endif } else { log_info(gc)("Terminating old gc cycle."); @@ -350,7 +350,7 @@ void ShenandoahOldGeneration::cancel_gc() { // Remove old generation access to young generation mark queues ShenandoahHeap::heap()->young_generation()->set_old_gen_task_queues(nullptr); // Transition to IDLE now. - transition_to(ShenandoahOldGeneration::WAITING_FOR_BOOTSTRAP); + transition_to(ShenandoahOldGeneration::IDLE); } } @@ -477,9 +477,8 @@ void ShenandoahOldGeneration::prepare_regions_and_collection_set(bool concurrent const char* ShenandoahOldGeneration::state_name(State state) { switch (state) { - case WAITING_FOR_BOOTSTRAP: return "Waiting for Bootstrap"; + case IDLE: return "Idle"; case FILLING: return "Coalescing"; - case BOOTSTRAPPING: return "Bootstrapping"; case MARKING: return "Marking"; case EVACUATING: return "Evacuating"; case EVACUATING_AFTER_GLOBAL: return "Evacuating (G)"; @@ -517,7 +516,7 @@ void ShenandoahOldGeneration::transition_to(State new_state) { // the old generation in the respective states (EVACUATING or FILLING). After a Full GC, // the mark bitmaps are all reset, all regions are parsable and the mark context will // not be "complete". After a Full GC, remembered set scans will _not_ use the mark bitmap -// and we expect the old generation to be waiting for bootstrap. +// and we expect the old generation to be idle. // // +-----------------+ // +------------> | FILLING | <---+ @@ -526,19 +525,12 @@ void ShenandoahOldGeneration::transition_to(State new_state) { // | | | | // | | | Filling Complete | <-> A global collection may // | | v | move the old generation -// | | +-----------------+ | directly from waiting for -// +-- |-- |--------> | WAITING | | bootstrap to filling or -// | | | +---- | FOR BOOTSTRAP | ----+ evacuating. It may also -// | | | | +-----------------+ move from filling to waiting -// | | | | | for bootstrap. -// | | | | | Reset Bitmap -// | | | | v -// | | | | +-----------------+ +----------------------+ -// | | | | | BOOTSTRAP | <-> | YOUNG GC | -// | | | | | | | (RSet Parses Region) | -// | | | | +-----------------+ +----------------------+ +// | | +-----------------+ | directly from idle to +// +-- |-- |--------> | IDLE | | filling or evacuating. +// | | | +---- | | ----+ It may also move from +// | | | | +-----------------+ filling to idle. // | | | | | -// | | | | | Old Marking +// | | | | | Reset Bitmap + Start Marking // | | | | v // | | | | +-----------------+ +----------------------+ // | | | | | MARKING | <-> | YOUNG GC | @@ -564,29 +556,23 @@ void ShenandoahOldGeneration::validate_transition(State new_state) { ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); switch (new_state) { case FILLING: - assert(_state != BOOTSTRAPPING, "Cannot begin making old regions parsable after bootstrapping"); assert(is_mark_complete(), "Cannot begin filling without first completing marking, state is '%s'", state_name(_state)); assert(_old_heuristics->has_coalesce_and_fill_candidates(), "Cannot begin filling without something to fill."); break; - case WAITING_FOR_BOOTSTRAP: + case IDLE: // GC cancellation can send us back here from any state. - validate_waiting_for_bootstrap(); - break; - case BOOTSTRAPPING: - assert(_state == WAITING_FOR_BOOTSTRAP, "Cannot reset bitmap without making old regions parsable, state is '%s'", state_name(_state)); - assert(_old_heuristics->unprocessed_old_collection_candidates() == 0, "Cannot bootstrap with mixed collection candidates"); - assert(!heap->is_prepare_for_old_mark_in_progress(), "Cannot still be making old regions parsable."); + validate_idle(); break; case MARKING: - assert(_state == BOOTSTRAPPING, "Must have finished bootstrapping before marking, state is '%s'", state_name(_state)); - assert(heap->young_generation()->old_gen_task_queues() != nullptr, "Young generation needs old mark queues."); - assert(heap->is_concurrent_old_mark_in_progress(), "Should be marking old now."); + assert(_state == IDLE, "Must be idle before marking, state is '%s'", state_name(_state)); + assert(_old_heuristics->unprocessed_old_collection_candidates() == 0, "Cannot start marking with mixed collection candidates"); + assert(!heap->is_prepare_for_old_mark_in_progress(), "Cannot still be making old regions parsable."); break; case EVACUATING_AFTER_GLOBAL: assert(_state == EVACUATING, "Must have been evacuating, state is '%s'", state_name(_state)); break; case EVACUATING: - assert(_state == WAITING_FOR_BOOTSTRAP || _state == MARKING, "Cannot have old collection candidates without first marking, state is '%s'", state_name(_state)); + assert(_state == IDLE || _state == MARKING, "Cannot have old collection candidates without first marking, state is '%s'", state_name(_state)); assert(_old_heuristics->unprocessed_old_collection_candidates() > 0, "Must have collection candidates here."); break; default: @@ -594,10 +580,10 @@ void ShenandoahOldGeneration::validate_transition(State new_state) { } } -bool ShenandoahOldGeneration::validate_waiting_for_bootstrap() { +bool ShenandoahOldGeneration::validate_idle() { ShenandoahHeap* heap = ShenandoahHeap::heap(); - assert(!heap->is_concurrent_old_mark_in_progress(), "Cannot become ready for bootstrap during old mark."); - assert(heap->young_generation()->old_gen_task_queues() == nullptr, "Cannot become ready for bootstrap when still setup for bootstrapping."); + assert(!heap->is_concurrent_old_mark_in_progress(), "Cannot be idle during old mark."); + assert(heap->young_generation()->old_gen_task_queues() == nullptr, "Cannot be idle when still setup for bootstrapping."); assert(!is_concurrent_mark_in_progress(), "Cannot be marking in IDLE"); assert(!heap->young_generation()->is_bootstrap_cycle(), "Cannot have old mark queues if IDLE"); assert(!_old_heuristics->has_coalesce_and_fill_candidates(), "Cannot have coalesce and fill candidates in IDLE"); @@ -733,7 +719,7 @@ void ShenandoahOldGeneration::set_parsable(bool parsable) { // that we would unload classes and make everything parsable. But, we know // that now so we can override this state. abandon_collection_candidates(); - transition_to(ShenandoahOldGeneration::WAITING_FOR_BOOTSTRAP); + transition_to(ShenandoahOldGeneration::IDLE); break; default: // We can get here during a full GC. The full GC will cancel anything @@ -750,7 +736,7 @@ void ShenandoahOldGeneration::complete_mixed_evacuations() { assert(is_doing_mixed_evacuations(), "Mixed evacuations should be in progress"); if (!_old_heuristics->has_coalesce_and_fill_candidates()) { // No candidate regions to coalesce and fill - transition_to(ShenandoahOldGeneration::WAITING_FOR_BOOTSTRAP); + transition_to(ShenandoahOldGeneration::IDLE); return; } @@ -764,7 +750,7 @@ void ShenandoahOldGeneration::complete_mixed_evacuations() { // more to do. assert(state() == ShenandoahOldGeneration::EVACUATING_AFTER_GLOBAL, "Should be evacuating after a global cycle"); abandon_collection_candidates(); - transition_to(ShenandoahOldGeneration::WAITING_FOR_BOOTSTRAP); + transition_to(ShenandoahOldGeneration::IDLE); } void ShenandoahOldGeneration::abandon_mixed_evacuations() { @@ -774,7 +760,7 @@ void ShenandoahOldGeneration::abandon_mixed_evacuations() { break; case ShenandoahOldGeneration::EVACUATING_AFTER_GLOBAL: abandon_collection_candidates(); - transition_to(ShenandoahOldGeneration::WAITING_FOR_BOOTSTRAP); + transition_to(ShenandoahOldGeneration::IDLE); break; default: log_warning(gc)("Abandon mixed evacuations in unexpected state: %s", state_name(state())); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp index 12e046a1afc..8a356fc9b92 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp @@ -256,11 +256,7 @@ public: } bool is_idle() const { - return state() == WAITING_FOR_BOOTSTRAP; - } - - bool is_bootstrapping() const { - return state() == BOOTSTRAPPING; + return state() == IDLE; } // Amount of live memory (bytes) in regions waiting for mixed collections @@ -271,11 +267,11 @@ public: public: enum State { - FILLING, WAITING_FOR_BOOTSTRAP, BOOTSTRAPPING, MARKING, EVACUATING, EVACUATING_AFTER_GLOBAL + FILLING, IDLE, MARKING, EVACUATING, EVACUATING_AFTER_GLOBAL }; #ifdef ASSERT - bool validate_waiting_for_bootstrap(); + bool validate_idle(); #endif private: @@ -318,7 +314,7 @@ public: size_t usage_trigger_threshold() const; bool can_start_gc() { - return _state == WAITING_FOR_BOOTSTRAP; + return _state == IDLE; } static const char* state_name(State state);