mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-29 01:00:29 +00:00
8379511: G1: G1CollectorState should derive concurrent cycle state from G1ConcurrentMark
Reviewed-by: iwalulya, ayang
This commit is contained in:
parent
02001567f0
commit
a0c8fce9d7
@ -2554,7 +2554,7 @@ HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size,
|
||||
|
||||
void G1CollectedHeap::start_concurrent_cycle(bool concurrent_operation_is_full_mark) {
|
||||
assert(_cm->is_fully_initialized(), "sanity");
|
||||
assert(!_cm->in_progress(), "Can not start concurrent operation while in progress");
|
||||
assert(!collector_state()->is_in_concurrent_cycle(), "Can not start concurrent cycle when already running");
|
||||
MutexLocker x(G1CGC_lock, Mutex::_no_safepoint_check_flag);
|
||||
if (concurrent_operation_is_full_mark) {
|
||||
_cm->start_full_concurrent_cycle();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,7 +22,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1CollectorState.hpp"
|
||||
#include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
|
||||
#include "gc/g1/g1GCPauseType.hpp"
|
||||
|
||||
G1GCPauseType G1CollectorState::young_gc_pause_type(bool concurrent_operation_is_full_mark) const {
|
||||
@ -44,3 +46,24 @@ G1GCPauseType G1CollectorState::young_gc_pause_type(bool concurrent_operation_is
|
||||
return G1GCPauseType::YoungGC;
|
||||
}
|
||||
}
|
||||
|
||||
bool G1CollectorState::is_in_concurrent_cycle() const {
|
||||
G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark();
|
||||
return cm->is_in_concurrent_cycle();
|
||||
}
|
||||
|
||||
bool G1CollectorState::is_in_marking() const {
|
||||
G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark();
|
||||
return cm->is_in_marking();
|
||||
}
|
||||
|
||||
bool G1CollectorState::is_in_mark_or_rebuild() const {
|
||||
G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark();
|
||||
return is_in_marking() || cm->is_in_rebuild_or_scrub();
|
||||
}
|
||||
|
||||
bool G1CollectorState::is_in_reset_for_next_cycle() const {
|
||||
G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark();
|
||||
return cm->is_in_reset_for_next_cycle();
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -60,16 +60,6 @@ class G1CollectorState {
|
||||
// do the concurrent start phase work.
|
||||
volatile bool _initiate_conc_mark_if_possible;
|
||||
|
||||
// Marking is in progress. Set from start of the concurrent start pause to the
|
||||
// end of the Remark pause.
|
||||
bool _mark_in_progress;
|
||||
// Marking or rebuilding remembered set work is in progress. Set from the end
|
||||
// of the concurrent start pause to the end of the Cleanup pause.
|
||||
bool _mark_or_rebuild_in_progress;
|
||||
|
||||
// The marking bitmap is currently being cleared or about to be cleared.
|
||||
bool _clear_bitmap_in_progress;
|
||||
|
||||
// Set during a full gc pause.
|
||||
bool _in_full_gc;
|
||||
|
||||
@ -81,9 +71,6 @@ public:
|
||||
_in_concurrent_start_gc(false),
|
||||
_initiate_conc_mark_if_possible(false),
|
||||
|
||||
_mark_in_progress(false),
|
||||
_mark_or_rebuild_in_progress(false),
|
||||
_clear_bitmap_in_progress(false),
|
||||
_in_full_gc(false) { }
|
||||
|
||||
// Phase setters
|
||||
@ -96,10 +83,6 @@ public:
|
||||
|
||||
void set_initiate_conc_mark_if_possible(bool v) { _initiate_conc_mark_if_possible = v; }
|
||||
|
||||
void set_mark_in_progress(bool v) { _mark_in_progress = v; }
|
||||
void set_mark_or_rebuild_in_progress(bool v) { _mark_or_rebuild_in_progress = v; }
|
||||
void set_clear_bitmap_in_progress(bool v) { _clear_bitmap_in_progress = v; }
|
||||
|
||||
// Phase getters
|
||||
bool in_young_only_phase() const { return _in_young_only_phase && !_in_full_gc; }
|
||||
bool in_mixed_phase() const { return !_in_young_only_phase && !_in_full_gc; }
|
||||
@ -111,9 +94,10 @@ public:
|
||||
|
||||
bool initiate_conc_mark_if_possible() const { return _initiate_conc_mark_if_possible; }
|
||||
|
||||
bool mark_in_progress() const { return _mark_in_progress; }
|
||||
bool mark_or_rebuild_in_progress() const { return _mark_or_rebuild_in_progress; }
|
||||
bool clear_bitmap_in_progress() const { return _clear_bitmap_in_progress; }
|
||||
bool is_in_concurrent_cycle() const;
|
||||
bool is_in_marking() const;
|
||||
bool is_in_mark_or_rebuild() const;
|
||||
bool is_in_reset_for_next_cycle() const;
|
||||
|
||||
// Calculate GC Pause Type from internal state.
|
||||
G1GCPauseType young_gc_pause_type(bool concurrent_operation_is_full_mark) const;
|
||||
|
||||
@ -573,8 +573,20 @@ void G1ConcurrentMark::fully_initialize() {
|
||||
reset_at_marking_complete();
|
||||
}
|
||||
|
||||
bool G1ConcurrentMark::in_progress() const {
|
||||
return is_fully_initialized() ? _cm_thread->in_progress() : false;
|
||||
bool G1ConcurrentMark::is_in_concurrent_cycle() const {
|
||||
return is_fully_initialized() ? _cm_thread->is_in_progress() : false;
|
||||
}
|
||||
|
||||
bool G1ConcurrentMark::is_in_marking() const {
|
||||
return is_fully_initialized() ? cm_thread()->is_in_marking() : false;
|
||||
}
|
||||
|
||||
bool G1ConcurrentMark::is_in_rebuild_or_scrub() const {
|
||||
return cm_thread()->is_in_rebuild_or_scrub();
|
||||
}
|
||||
|
||||
bool G1ConcurrentMark::is_in_reset_for_next_cycle() const {
|
||||
return cm_thread()->is_in_reset_for_next_cycle();
|
||||
}
|
||||
|
||||
PartialArrayStateManager* G1ConcurrentMark::partial_array_state_manager() const {
|
||||
@ -622,7 +634,7 @@ void G1ConcurrentMark::humongous_object_eagerly_reclaimed(G1HeapRegion* r) {
|
||||
// Need to clear mark bit of the humongous object. Doing this unconditionally is fine.
|
||||
mark_bitmap()->clear(r->bottom());
|
||||
|
||||
if (!_g1h->collector_state()->mark_or_rebuild_in_progress()) {
|
||||
if (!_g1h->collector_state()->is_in_mark_or_rebuild()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -729,7 +741,7 @@ private:
|
||||
}
|
||||
|
||||
bool is_clear_concurrent_undo() {
|
||||
return suspendible() && _cm->cm_thread()->in_undo_mark();
|
||||
return suspendible() && _cm->cm_thread()->is_in_undo_cycle();
|
||||
}
|
||||
|
||||
bool has_aborted() {
|
||||
@ -785,8 +797,7 @@ private:
|
||||
// as asserts here to minimize their overhead on the product. However, we
|
||||
// will have them as guarantees at the beginning / end of the bitmap
|
||||
// clearing to get some checking in the product.
|
||||
assert(!suspendible() || _cm->in_progress(), "invariant");
|
||||
assert(!suspendible() || !G1CollectedHeap::heap()->collector_state()->mark_or_rebuild_in_progress(), "invariant");
|
||||
assert(!suspendible() || _cm->is_in_reset_for_next_cycle(), "invariant");
|
||||
|
||||
// Abort iteration if necessary.
|
||||
if (has_aborted()) {
|
||||
@ -836,23 +847,14 @@ void G1ConcurrentMark::clear_bitmap(WorkerThreads* workers, bool may_yield) {
|
||||
void G1ConcurrentMark::cleanup_for_next_mark() {
|
||||
// Make sure that the concurrent mark thread looks to still be in
|
||||
// the current cycle.
|
||||
guarantee(is_fully_initialized(), "should be initializd");
|
||||
guarantee(in_progress(), "invariant");
|
||||
|
||||
// We are finishing up the current cycle by clearing the next
|
||||
// marking bitmap and getting it ready for the next cycle. During
|
||||
// this time no other cycle can start. So, let's make sure that this
|
||||
// is the case.
|
||||
guarantee(!_g1h->collector_state()->mark_or_rebuild_in_progress(), "invariant");
|
||||
guarantee(is_in_reset_for_next_cycle(), "invariant");
|
||||
|
||||
clear_bitmap(_concurrent_workers, true);
|
||||
|
||||
reset_partial_array_state_manager();
|
||||
|
||||
// Repeat the asserts from above.
|
||||
guarantee(is_fully_initialized(), "should be initializd");
|
||||
guarantee(in_progress(), "invariant");
|
||||
guarantee(!_g1h->collector_state()->mark_or_rebuild_in_progress(), "invariant");
|
||||
// Should not have changed state yet (even if a Full GC interrupted us).
|
||||
guarantee(is_in_reset_for_next_cycle(), "invariant");
|
||||
}
|
||||
|
||||
void G1ConcurrentMark::reset_partial_array_state_manager() {
|
||||
@ -977,14 +979,14 @@ void G1ConcurrentMark::start_full_concurrent_cycle() {
|
||||
// during it. No need to call it here.
|
||||
|
||||
// Signal the thread to start work.
|
||||
cm_thread()->start_full_mark();
|
||||
cm_thread()->start_full_cycle();
|
||||
}
|
||||
|
||||
void G1ConcurrentMark::start_undo_concurrent_cycle() {
|
||||
root_regions()->cancel_scan();
|
||||
|
||||
// Signal the thread to start work.
|
||||
cm_thread()->start_undo_mark();
|
||||
cm_thread()->start_undo_cycle();
|
||||
}
|
||||
|
||||
void G1ConcurrentMark::notify_concurrent_cycle_completed() {
|
||||
@ -1186,8 +1188,6 @@ uint G1ConcurrentMark::completed_mark_cycles() const {
|
||||
}
|
||||
|
||||
void G1ConcurrentMark::concurrent_cycle_end(bool mark_cycle_completed) {
|
||||
_g1h->collector_state()->set_clear_bitmap_in_progress(false);
|
||||
|
||||
_g1h->trace_heap_after_gc(_gc_tracer_cm);
|
||||
|
||||
if (mark_cycle_completed) {
|
||||
@ -1372,6 +1372,9 @@ void G1ConcurrentMark::remark() {
|
||||
G1ObjectCountIsAliveClosure is_alive(_g1h);
|
||||
_gc_tracer_cm->report_object_count_after_gc(&is_alive, _g1h->workers());
|
||||
}
|
||||
|
||||
// Successfully completed marking, advance state.
|
||||
cm_thread()->set_full_cycle_rebuild_and_scrub();
|
||||
} else {
|
||||
// We overflowed. Restart concurrent marking.
|
||||
_restart_for_overflow.store_relaxed(true);
|
||||
@ -1392,6 +1395,8 @@ void G1ConcurrentMark::remark() {
|
||||
_g1h->update_perf_counter_cpu_time();
|
||||
|
||||
policy->record_concurrent_mark_remark_end();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void G1ConcurrentMark::compute_new_sizes() {
|
||||
@ -1454,6 +1459,10 @@ void G1ConcurrentMark::cleanup() {
|
||||
GCTraceTime(Debug, gc, phases) debug("Finalize Concurrent Mark Cleanup", _gc_timer_cm);
|
||||
policy->record_concurrent_mark_cleanup_end(needs_remembered_set_rebuild());
|
||||
}
|
||||
|
||||
// Advance state.
|
||||
cm_thread()->set_full_cycle_reset_for_next_cycle();
|
||||
return;
|
||||
}
|
||||
|
||||
// 'Keep Alive' oop closure used by both serial parallel reference processing.
|
||||
@ -1880,7 +1889,7 @@ public:
|
||||
void G1ConcurrentMark::verify_no_collection_set_oops() {
|
||||
assert(SafepointSynchronize::is_at_safepoint() || !is_init_completed(),
|
||||
"should be at a safepoint or initializing");
|
||||
if (!_g1h->collector_state()->mark_or_rebuild_in_progress()) {
|
||||
if (!is_fully_initialized() || !_g1h->collector_state()->is_in_mark_or_rebuild()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1958,7 +1967,7 @@ bool G1ConcurrentMark::concurrent_cycle_abort() {
|
||||
// has been signalled is already rare), and this work should be negligible compared
|
||||
// to actual full gc work.
|
||||
|
||||
if (!is_fully_initialized() || (!cm_thread()->in_progress() && !cm_thread()->should_terminate())) {
|
||||
if (!is_fully_initialized() || (!cm_thread()->is_in_progress() && !cm_thread()->should_terminate())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -353,6 +353,7 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
|
||||
friend class G1CMRootRegionScanTask;
|
||||
friend class G1CMTask;
|
||||
friend class G1ClearBitMapTask;
|
||||
friend class G1CollectorState;
|
||||
friend class G1ConcurrentMarkThread;
|
||||
|
||||
G1ConcurrentMarkThread* _cm_thread; // The thread doing the work
|
||||
@ -528,6 +529,12 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
|
||||
|
||||
G1ConcurrentMarkThread* cm_thread() const;
|
||||
|
||||
// Concurrent cycle state queries.
|
||||
bool is_in_concurrent_cycle() const;
|
||||
bool is_in_marking() const;
|
||||
bool is_in_rebuild_or_scrub() const;
|
||||
bool is_in_reset_for_next_cycle() const;
|
||||
|
||||
public:
|
||||
// To be called when an object is marked the first time, e.g. after a successful
|
||||
// mark_in_bitmap call. Updates various statistics data.
|
||||
@ -561,7 +568,7 @@ public:
|
||||
|
||||
void fully_initialize();
|
||||
bool is_fully_initialized() const { return _cm_thread != nullptr; }
|
||||
bool in_progress() const;
|
||||
|
||||
uint max_num_tasks() const {return _max_num_tasks; }
|
||||
|
||||
// Clear statistics gathered during the concurrent cycle for the given region after
|
||||
@ -666,8 +673,10 @@ public:
|
||||
// Do concurrent preclean work.
|
||||
void preclean();
|
||||
|
||||
// Executes the Remark pause.
|
||||
void remark();
|
||||
|
||||
// Executes the Cleanup pause.
|
||||
void cleanup();
|
||||
|
||||
// Mark in the marking bitmap. Used during evacuation failure to
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -112,22 +112,22 @@ class G1ConcPhaseTimer : public GCTraceConcTimeImpl<LogLevel::Info, LOG_TAGS(gc,
|
||||
|
||||
void G1ConcurrentMarkThread::run_service() {
|
||||
while (wait_for_next_cycle()) {
|
||||
assert(in_progress(), "must be");
|
||||
assert(is_in_progress(), "must be");
|
||||
|
||||
GCIdMark gc_id_mark;
|
||||
FormatBuffer<128> title("Concurrent %s Cycle", _state == FullMark ? "Mark" : "Undo");
|
||||
FormatBuffer<128> title("Concurrent %s Cycle", is_in_full_concurrent_cycle() ? "Mark" : "Undo");
|
||||
GCTraceConcTime(Info, gc) tt(title);
|
||||
|
||||
concurrent_cycle_start();
|
||||
|
||||
if (_state == FullMark) {
|
||||
if (_state == FullCycleMarking) {
|
||||
concurrent_mark_cycle_do();
|
||||
} else {
|
||||
assert(_state == UndoMark, "Must do undo mark but is %d", _state);
|
||||
assert(_state == UndoCycleResetForNextCycle, "Must do undo mark but is %d", _state);
|
||||
concurrent_undo_cycle_do();
|
||||
}
|
||||
|
||||
concurrent_cycle_end(_state == FullMark && !_cm->has_aborted());
|
||||
concurrent_cycle_end(is_in_full_concurrent_cycle() && !_cm->has_aborted());
|
||||
|
||||
update_perf_counter_cpu_time();
|
||||
}
|
||||
@ -135,7 +135,7 @@ void G1ConcurrentMarkThread::run_service() {
|
||||
}
|
||||
|
||||
void G1ConcurrentMarkThread::stop_service() {
|
||||
if (in_progress()) {
|
||||
if (is_in_progress()) {
|
||||
// We are not allowed to abort the marking threads during root region scan.
|
||||
// Needs to be done separately.
|
||||
_cm->root_region_scan_abort_and_wait();
|
||||
@ -149,7 +149,7 @@ void G1ConcurrentMarkThread::stop_service() {
|
||||
|
||||
bool G1ConcurrentMarkThread::wait_for_next_cycle() {
|
||||
MonitorLocker ml(G1CGC_lock, Mutex::_no_safepoint_check_flag);
|
||||
while (!in_progress() && !should_terminate()) {
|
||||
while (!is_in_progress() && !should_terminate()) {
|
||||
ml.wait();
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,25 +32,34 @@ class G1Policy;
|
||||
|
||||
// The concurrent mark thread triggers the various steps of the concurrent marking
|
||||
// cycle, including various marking cleanup.
|
||||
//
|
||||
// The concurrent cycle may either be "Full" (i.e. include marking, rebuilding and
|
||||
// scrubbing, resetting for the next cycle) or "Undo", i.e. shortened to just the
|
||||
// reset part.
|
||||
class G1ConcurrentMarkThread: public ConcurrentGCThread {
|
||||
G1ConcurrentMark* _cm;
|
||||
|
||||
enum ServiceState : uint {
|
||||
Idle,
|
||||
FullMark,
|
||||
UndoMark
|
||||
FullCycleMarking,
|
||||
FullCycleRebuildOrScrub,
|
||||
FullCycleResetForNextCycle,
|
||||
UndoCycleResetForNextCycle
|
||||
};
|
||||
|
||||
volatile ServiceState _state;
|
||||
|
||||
// Returns whether we are in a "Full" cycle.
|
||||
bool is_in_full_concurrent_cycle() const;
|
||||
|
||||
// Wait for next cycle. Returns the command passed over.
|
||||
bool wait_for_next_cycle();
|
||||
|
||||
bool mark_loop_needs_restart() const;
|
||||
|
||||
// Phases and subphases for the full concurrent marking cycle in order.
|
||||
// Phases and subphases for the full concurrent cycle in order.
|
||||
//
|
||||
// All these methods return true if the marking should be aborted.
|
||||
// All these methods return true if the cycle should be aborted.
|
||||
bool phase_clear_cld_claimed_marks();
|
||||
bool phase_scan_root_regions();
|
||||
|
||||
@ -88,22 +97,25 @@ class G1ConcurrentMarkThread: public ConcurrentGCThread {
|
||||
double total_mark_cpu_time_s();
|
||||
// Cpu time used by all marking worker threads in seconds.
|
||||
double worker_threads_cpu_time_s();
|
||||
|
||||
G1ConcurrentMark* cm() { return _cm; }
|
||||
|
||||
// State management.
|
||||
void set_idle();
|
||||
void start_full_mark();
|
||||
void start_undo_mark();
|
||||
void start_full_cycle();
|
||||
void start_undo_cycle();
|
||||
|
||||
bool idle() const;
|
||||
void set_full_cycle_rebuild_and_scrub();
|
||||
void set_full_cycle_reset_for_next_cycle();
|
||||
|
||||
bool is_idle() const;
|
||||
// Returns true from the moment a concurrent cycle is
|
||||
// initiated (during the concurrent start pause when started() is set)
|
||||
// to the moment when the cycle completes (just after the next
|
||||
// marking bitmap has been cleared and in_progress() is
|
||||
// cleared).
|
||||
bool in_progress() const;
|
||||
// initiated (during the concurrent start pause when calling one of the
|
||||
// start_*_cycle() methods) to the moment when the cycle completes.
|
||||
bool is_in_progress() const;
|
||||
|
||||
bool in_undo_mark() const;
|
||||
bool is_in_marking() const;
|
||||
bool is_in_rebuild_or_scrub() const;
|
||||
bool is_in_reset_for_next_cycle() const;
|
||||
|
||||
bool is_in_undo_cycle() const;
|
||||
|
||||
// Update the perf data counter for concurrent mark.
|
||||
void update_perf_counter_cpu_time();
|
||||
|
||||
@ -40,29 +40,64 @@ inline double G1ConcurrentMarkThread::worker_threads_cpu_time_s() {
|
||||
return _cm->worker_threads_cpu_time_s();
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::is_in_full_concurrent_cycle() const {
|
||||
ServiceState state = _state;
|
||||
return (state == FullCycleMarking || state == FullCycleRebuildOrScrub || state == FullCycleResetForNextCycle);
|
||||
}
|
||||
|
||||
inline void G1ConcurrentMarkThread::set_idle() {
|
||||
assert(_state == FullMark || _state == UndoMark, "must not be starting a new cycle");
|
||||
// Concurrent cycle may be aborted any time.
|
||||
assert(!is_idle(), "must not be idle");
|
||||
_state = Idle;
|
||||
}
|
||||
|
||||
inline void G1ConcurrentMarkThread::start_full_mark() {
|
||||
assert(_state == Idle, "cycle in progress");
|
||||
_state = FullMark;
|
||||
inline void G1ConcurrentMarkThread::start_full_cycle() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be");
|
||||
assert(is_idle(), "cycle in progress");
|
||||
_state = FullCycleMarking;
|
||||
}
|
||||
|
||||
inline void G1ConcurrentMarkThread::start_undo_mark() {
|
||||
assert(_state == Idle, "cycle in progress");
|
||||
_state = UndoMark;
|
||||
inline void G1ConcurrentMarkThread::start_undo_cycle() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be");
|
||||
assert(is_idle(), "cycle in progress");
|
||||
_state = UndoCycleResetForNextCycle;
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::idle() const { return _state == Idle; }
|
||||
|
||||
inline bool G1ConcurrentMarkThread::in_progress() const {
|
||||
return !idle();
|
||||
inline void G1ConcurrentMarkThread::set_full_cycle_rebuild_and_scrub() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be");
|
||||
assert(_state == FullCycleMarking, "must be");
|
||||
_state = FullCycleRebuildOrScrub;
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::in_undo_mark() const {
|
||||
return _state == UndoMark;
|
||||
inline void G1ConcurrentMarkThread::set_full_cycle_reset_for_next_cycle() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be");
|
||||
assert(_state == FullCycleRebuildOrScrub, "must be");
|
||||
_state = FullCycleResetForNextCycle;
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::is_in_marking() const {
|
||||
return _state == FullCycleMarking;
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::is_in_rebuild_or_scrub() const {
|
||||
return _state == FullCycleRebuildOrScrub;
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::is_in_reset_for_next_cycle() const {
|
||||
ServiceState state = _state;
|
||||
return state == FullCycleResetForNextCycle || state == UndoCycleResetForNextCycle;
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::is_idle() const {
|
||||
return _state == Idle;
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::is_in_progress() const {
|
||||
return !is_idle();
|
||||
}
|
||||
|
||||
inline bool G1ConcurrentMarkThread::is_in_undo_cycle() const {
|
||||
return _state == UndoCycleResetForNextCycle;
|
||||
}
|
||||
|
||||
#endif // SHARE_GC_G1_G1CONCURRENTMARKTHREAD_INLINE_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,8 +38,8 @@ bool G1PeriodicGCTask::should_start_periodic_gc(G1CollectedHeap* g1h,
|
||||
// Ensure no GC safepoints while we're doing the checks, to avoid data races.
|
||||
SuspendibleThreadSetJoiner sts;
|
||||
|
||||
// If we are currently in a concurrent mark we are going to uncommit memory soon.
|
||||
if (g1h->concurrent_mark()->in_progress()) {
|
||||
// If we are currently in a concurrent cycle we are going to uncommit memory soon.
|
||||
if (g1h->collector_state()->is_in_concurrent_cycle()) {
|
||||
log_debug(gc, periodic)("Concurrent cycle in progress. Skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -579,9 +579,6 @@ void G1Policy::record_full_collection_end(size_t allocation_word_size) {
|
||||
collector_state()->set_in_young_gc_before_mixed(false);
|
||||
collector_state()->set_initiate_conc_mark_if_possible(need_to_start_conc_mark("end of Full GC", allocation_word_size));
|
||||
collector_state()->set_in_concurrent_start_gc(false);
|
||||
collector_state()->set_mark_in_progress(false);
|
||||
collector_state()->set_mark_or_rebuild_in_progress(false);
|
||||
collector_state()->set_clear_bitmap_in_progress(false);
|
||||
|
||||
_eden_surv_rate_group->start_adding_regions();
|
||||
// also call this on any additional surv rate groups
|
||||
@ -709,7 +706,6 @@ void G1Policy::record_concurrent_mark_remark_end() {
|
||||
double elapsed_time_ms = (end_time_sec - start_time_sec) * 1000.0;
|
||||
_analytics->report_concurrent_mark_remark_times_ms(elapsed_time_ms);
|
||||
record_pause(G1GCPauseType::Remark, start_time_sec, end_time_sec);
|
||||
collector_state()->set_mark_in_progress(false);
|
||||
}
|
||||
|
||||
G1CollectionSetCandidates* G1Policy::candidates() const {
|
||||
@ -739,7 +735,7 @@ double G1Policy::constant_other_time_ms(double pause_time_ms) const {
|
||||
}
|
||||
|
||||
bool G1Policy::about_to_start_mixed_phase() const {
|
||||
return _g1h->concurrent_mark()->in_progress() || collector_state()->in_young_gc_before_mixed();
|
||||
return collector_state()->is_in_concurrent_cycle() || collector_state()->in_young_gc_before_mixed();
|
||||
}
|
||||
|
||||
bool G1Policy::need_to_start_conc_mark(const char* source, size_t allocation_word_size) {
|
||||
@ -971,12 +967,8 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
|
||||
|
||||
_eden_surv_rate_group->start_adding_regions();
|
||||
|
||||
assert(!(G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause) && collector_state()->mark_or_rebuild_in_progress()),
|
||||
"If the last pause has been concurrent start, we should not have been in the marking window");
|
||||
if (G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause)) {
|
||||
collector_state()->set_mark_in_progress(concurrent_operation_is_full_mark);
|
||||
collector_state()->set_mark_or_rebuild_in_progress(concurrent_operation_is_full_mark);
|
||||
}
|
||||
assert(!(G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause) && collector_state()->is_in_concurrent_cycle()),
|
||||
"If the last pause has been concurrent start, we should not have been in the marking cycle");
|
||||
|
||||
_free_regions_at_end_of_collection = _g1h->num_free_regions();
|
||||
|
||||
@ -1235,7 +1227,7 @@ bool G1Policy::force_concurrent_start_if_outside_cycle(GCCause::Cause gc_cause)
|
||||
// We actually check whether we are marking here and not if we are in a
|
||||
// reclamation phase. This means that we will schedule a concurrent mark
|
||||
// even while we are still in the process of reclaiming memory.
|
||||
bool during_cycle = _g1h->concurrent_mark()->in_progress();
|
||||
bool during_cycle = collector_state()->is_in_concurrent_cycle();
|
||||
if (!during_cycle) {
|
||||
log_debug(gc, ergo)("Request concurrent cycle initiation (requested by GC cause). "
|
||||
"GC cause: %s",
|
||||
@ -1328,8 +1320,8 @@ void G1Policy::decide_on_concurrent_start_pause() {
|
||||
// We do not allow concurrent start to be piggy-backed on a mixed GC.
|
||||
assert(!collector_state()->in_concurrent_start_gc() ||
|
||||
collector_state()->in_young_only_phase(), "sanity");
|
||||
// We also do not allow mixed GCs during marking.
|
||||
assert(!collector_state()->mark_or_rebuild_in_progress() || collector_state()->in_young_only_phase(), "sanity");
|
||||
// We also do not allow mixed GCs during marking/rebuilding.
|
||||
assert(!collector_state()->is_in_mark_or_rebuild() || collector_state()->in_young_only_phase(), "sanity %d %d", collector_state()->is_in_concurrent_cycle(), collector_state()->in_young_only_phase());
|
||||
}
|
||||
|
||||
void G1Policy::record_concurrent_mark_cleanup_end(bool has_rebuilt_remembered_sets) {
|
||||
@ -1349,8 +1341,6 @@ void G1Policy::record_concurrent_mark_cleanup_end(bool has_rebuilt_remembered_se
|
||||
log_debug(gc, ergo)("request young-only gcs (candidate old regions not available)");
|
||||
}
|
||||
collector_state()->set_in_young_gc_before_mixed(mixed_gc_pending);
|
||||
collector_state()->set_mark_or_rebuild_in_progress(false);
|
||||
collector_state()->set_clear_bitmap_in_progress(true);
|
||||
|
||||
double end_sec = os::elapsedTime();
|
||||
double start_sec = cur_pause_start_sec();
|
||||
|
||||
@ -115,7 +115,7 @@ class G1Policy: public CHeapObj<mtGC> {
|
||||
G1ConcurrentStartToMixedTimeTracker _concurrent_start_to_mixed;
|
||||
|
||||
bool should_update_surv_rate_group_predictors() {
|
||||
return collector_state()->in_young_only_phase() && !collector_state()->mark_or_rebuild_in_progress();
|
||||
return collector_state()->in_young_only_phase() && !collector_state()->is_in_mark_or_rebuild();
|
||||
}
|
||||
|
||||
double pending_cards_processing_time() const;
|
||||
|
||||
@ -1026,7 +1026,7 @@ class G1MergeHeapRootsTask : public WorkerTask {
|
||||
// the pause occurs during the Concurrent Cleanup for Next Mark phase.
|
||||
// Only at that point the region's bitmap may contain marks while being in the collection
|
||||
// set at the same time.
|
||||
return _g1h->collector_state()->clear_bitmap_in_progress() &&
|
||||
return _g1h->collector_state()->is_in_reset_for_next_cycle() &&
|
||||
hr->is_old();
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -84,8 +84,9 @@ void VM_G1TryInitiateConcMark::doit() {
|
||||
|
||||
GCCauseSetter x(g1h, _gc_cause);
|
||||
|
||||
_mark_in_progress = g1h->collector_state()->mark_in_progress();
|
||||
_cycle_already_in_progress = g1h->concurrent_mark()->in_progress();
|
||||
G1CollectorState* state = g1h->collector_state();
|
||||
_mark_in_progress = state->is_in_marking();
|
||||
_cycle_already_in_progress = state->is_in_concurrent_cycle();
|
||||
|
||||
if (!g1h->policy()->force_concurrent_start_if_outside_cycle(_gc_cause)) {
|
||||
// Failure to force the next GC pause to be a concurrent start indicates
|
||||
@ -166,11 +167,11 @@ void VM_G1PauseConcurrent::doit_epilogue() {
|
||||
}
|
||||
|
||||
void VM_G1PauseRemark::work() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
g1h->concurrent_mark()->remark();
|
||||
G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark();
|
||||
cm->remark();
|
||||
}
|
||||
|
||||
void VM_G1PauseCleanup::work() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
g1h->concurrent_mark()->cleanup();
|
||||
G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark();
|
||||
cm->cleanup();
|
||||
}
|
||||
|
||||
@ -391,7 +391,7 @@ class G1PrepareEvacuationTask : public WorkerTask {
|
||||
if (!obj->is_typeArray()) {
|
||||
// All regions that were allocated before marking have a TAMS != bottom.
|
||||
bool allocated_before_mark_start = region->bottom() != _g1h->concurrent_mark()->top_at_mark_start(region);
|
||||
bool mark_in_progress = _g1h->collector_state()->mark_in_progress();
|
||||
bool mark_in_progress = _g1h->collector_state()->is_in_marking();
|
||||
|
||||
if (allocated_before_mark_start && mark_in_progress) {
|
||||
return false;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -61,9 +61,9 @@ void G1YoungGCAllocationFailureInjector::select_allocation_failure_regions() {
|
||||
|
||||
bool G1YoungGCAllocationFailureInjector::arm_if_needed_for_gc_type(bool for_young_only_phase,
|
||||
bool during_concurrent_start,
|
||||
bool mark_or_rebuild_in_progress) {
|
||||
bool in_concurrent_cycle) {
|
||||
bool res = false;
|
||||
if (mark_or_rebuild_in_progress) {
|
||||
if (in_concurrent_cycle) {
|
||||
res |= G1GCAllocationFailureALotDuringConcMark;
|
||||
}
|
||||
if (during_concurrent_start) {
|
||||
@ -91,12 +91,12 @@ void G1YoungGCAllocationFailureInjector::arm_if_needed() {
|
||||
G1CollectorState* collector_state = g1h->collector_state();
|
||||
const bool in_young_only_phase = collector_state->in_young_only_phase();
|
||||
const bool in_concurrent_start_gc = collector_state->in_concurrent_start_gc();
|
||||
const bool mark_or_rebuild_in_progress = collector_state->mark_or_rebuild_in_progress();
|
||||
const bool in_concurrent_cycle = collector_state->is_in_concurrent_cycle();
|
||||
|
||||
_inject_allocation_failure_for_current_gc &=
|
||||
arm_if_needed_for_gc_type(in_young_only_phase,
|
||||
in_concurrent_start_gc,
|
||||
mark_or_rebuild_in_progress);
|
||||
in_concurrent_cycle);
|
||||
|
||||
if (_inject_allocation_failure_for_current_gc) {
|
||||
select_allocation_failure_regions();
|
||||
|
||||
@ -395,7 +395,7 @@ public:
|
||||
{
|
||||
ResourceMark rm;
|
||||
bool allocated_after_mark_start = r->bottom() == _g1h->concurrent_mark()->top_at_mark_start(r);
|
||||
bool mark_in_progress = _g1h->collector_state()->mark_in_progress();
|
||||
bool mark_in_progress = _g1h->collector_state()->is_in_marking();
|
||||
guarantee(obj->is_typeArray() || (allocated_after_mark_start || !mark_in_progress),
|
||||
"Only eagerly reclaiming primitive arrays is supported, other humongous objects only if allocated after mark start, but the object "
|
||||
PTR_FORMAT " (%s) is not (mark %d allocated after mark: %d).",
|
||||
|
||||
@ -578,7 +578,7 @@ WB_END
|
||||
WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
|
||||
if (UseG1GC) {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
return g1h->concurrent_mark()->in_progress();
|
||||
return g1h->collector_state()->is_in_concurrent_cycle();
|
||||
}
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1InConcurrentMark: G1 GC is not enabled");
|
||||
WB_END
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user