mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-19 01:47:52 +00:00
8199742: Clean up state flags in G1CollectorState
Remove, merge and update naming of flags in G1CollectorState Reviewed-by: sangheki, sjohanss
This commit is contained in:
parent
b04f1fe8f6
commit
5524494066
@ -79,7 +79,7 @@ void G1Allocator::reuse_retained_old_region(EvacuationInfo& evacuation_info,
|
||||
// we allocate to in the region sets. We'll re-add it later, when
|
||||
// it's retired again.
|
||||
_g1h->old_set_remove(retained_region);
|
||||
bool during_im = _g1h->collector_state()->during_initial_mark_pause();
|
||||
bool during_im = _g1h->collector_state()->in_initial_mark_gc();
|
||||
retained_region->note_start_of_copying(during_im);
|
||||
old->set(retained_region);
|
||||
_g1h->hr_printer()->reuse(retained_region);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2018, 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
|
||||
@ -166,16 +166,16 @@ void G1Analytics::report_cost_scan_hcc(double cost_scan_hcc) {
|
||||
_cost_scan_hcc_seq->add(cost_scan_hcc);
|
||||
}
|
||||
|
||||
void G1Analytics::report_cost_per_entry_ms(double cost_per_entry_ms, bool last_gc_was_young) {
|
||||
if (last_gc_was_young) {
|
||||
void G1Analytics::report_cost_per_entry_ms(double cost_per_entry_ms, bool for_young_gc) {
|
||||
if (for_young_gc) {
|
||||
_cost_per_entry_ms_seq->add(cost_per_entry_ms);
|
||||
} else {
|
||||
_mixed_cost_per_entry_ms_seq->add(cost_per_entry_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void G1Analytics::report_cards_per_entry_ratio(double cards_per_entry_ratio, bool last_gc_was_young) {
|
||||
if (last_gc_was_young) {
|
||||
void G1Analytics::report_cards_per_entry_ratio(double cards_per_entry_ratio, bool for_young_gc) {
|
||||
if (for_young_gc) {
|
||||
_young_cards_per_entry_ratio_seq->add(cards_per_entry_ratio);
|
||||
} else {
|
||||
_mixed_cards_per_entry_ratio_seq->add(cards_per_entry_ratio);
|
||||
@ -186,8 +186,8 @@ void G1Analytics::report_rs_length_diff(double rs_length_diff) {
|
||||
_rs_length_diff_seq->add(rs_length_diff);
|
||||
}
|
||||
|
||||
void G1Analytics::report_cost_per_byte_ms(double cost_per_byte_ms, bool in_marking_window) {
|
||||
if (in_marking_window) {
|
||||
void G1Analytics::report_cost_per_byte_ms(double cost_per_byte_ms, bool mark_or_rebuild_in_progress) {
|
||||
if (mark_or_rebuild_in_progress) {
|
||||
_cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms);
|
||||
} else {
|
||||
_cost_per_byte_ms_seq->add(cost_per_byte_ms);
|
||||
@ -246,16 +246,16 @@ double G1Analytics::predict_mixed_cards_per_entry_ratio() const {
|
||||
}
|
||||
}
|
||||
|
||||
size_t G1Analytics::predict_card_num(size_t rs_length, bool gcs_are_young) const {
|
||||
if (gcs_are_young) {
|
||||
size_t G1Analytics::predict_card_num(size_t rs_length, bool for_young_gc) const {
|
||||
if (for_young_gc) {
|
||||
return (size_t) (rs_length * predict_young_cards_per_entry_ratio());
|
||||
} else {
|
||||
return (size_t) (rs_length * predict_mixed_cards_per_entry_ratio());
|
||||
}
|
||||
}
|
||||
|
||||
double G1Analytics::predict_rs_scan_time_ms(size_t card_num, bool gcs_are_young) const {
|
||||
if (gcs_are_young) {
|
||||
double G1Analytics::predict_rs_scan_time_ms(size_t card_num, bool for_young_gc) const {
|
||||
if (for_young_gc) {
|
||||
return card_num * get_new_prediction(_cost_per_entry_ms_seq);
|
||||
} else {
|
||||
return predict_mixed_rs_scan_time_ms(card_num);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2018, 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
|
||||
@ -101,10 +101,10 @@ public:
|
||||
void report_alloc_rate_ms(double alloc_rate);
|
||||
void report_cost_per_card_ms(double cost_per_card_ms);
|
||||
void report_cost_scan_hcc(double cost_scan_hcc);
|
||||
void report_cost_per_entry_ms(double cost_per_entry_ms, bool last_gc_was_young);
|
||||
void report_cards_per_entry_ratio(double cards_per_entry_ratio, bool last_gc_was_young);
|
||||
void report_cost_per_entry_ms(double cost_per_entry_ms, bool for_young_gc);
|
||||
void report_cards_per_entry_ratio(double cards_per_entry_ratio, bool for_young_gc);
|
||||
void report_rs_length_diff(double rs_length_diff);
|
||||
void report_cost_per_byte_ms(double cost_per_byte_ms, bool in_marking_window);
|
||||
void report_cost_per_byte_ms(double cost_per_byte_ms, bool mark_or_rebuild_in_progress);
|
||||
void report_young_other_cost_per_region_ms(double other_cost_per_region_ms);
|
||||
void report_non_young_other_cost_per_region_ms(double other_cost_per_region_ms);
|
||||
void report_constant_other_time_ms(double constant_other_time_ms);
|
||||
@ -126,9 +126,9 @@ public:
|
||||
|
||||
double predict_mixed_cards_per_entry_ratio() const;
|
||||
|
||||
size_t predict_card_num(size_t rs_length, bool gcs_are_young) const;
|
||||
size_t predict_card_num(size_t rs_length, bool for_young_gc) const;
|
||||
|
||||
double predict_rs_scan_time_ms(size_t card_num, bool gcs_are_young) const;
|
||||
double predict_rs_scan_time_ms(size_t card_num, bool for_young_gc) const;
|
||||
|
||||
double predict_mixed_rs_scan_time_ms(size_t card_num) const;
|
||||
|
||||
|
||||
@ -997,7 +997,6 @@ void G1CollectedHeap::prepare_heap_for_full_collection() {
|
||||
abandon_collection_set(collection_set());
|
||||
|
||||
tear_down_region_sets(false /* free_list_only */);
|
||||
collector_state()->set_gcs_are_young(true);
|
||||
}
|
||||
|
||||
void G1CollectedHeap::verify_before_full_collection(bool explicit_gc) {
|
||||
@ -2756,28 +2755,28 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
// We should not be doing initial mark unless the conc mark thread is running
|
||||
if (!_cmThread->should_terminate()) {
|
||||
// This call will decide whether this pause is an initial-mark
|
||||
// pause. If it is, during_initial_mark_pause() will return true
|
||||
// pause. If it is, in_initial_mark_gc() will return true
|
||||
// for the duration of this pause.
|
||||
g1_policy()->decide_on_conc_mark_initiation();
|
||||
}
|
||||
|
||||
// We do not allow initial-mark to be piggy-backed on a mixed GC.
|
||||
assert(!collector_state()->during_initial_mark_pause() ||
|
||||
collector_state()->gcs_are_young(), "sanity");
|
||||
assert(!collector_state()->in_initial_mark_gc() ||
|
||||
collector_state()->in_young_only_phase(), "sanity");
|
||||
|
||||
// We also do not allow mixed GCs during marking.
|
||||
assert(!collector_state()->mark_in_progress() || collector_state()->gcs_are_young(), "sanity");
|
||||
assert(!collector_state()->mark_or_rebuild_in_progress() || collector_state()->in_young_only_phase(), "sanity");
|
||||
|
||||
// Record whether this pause is an initial mark. When the current
|
||||
// thread has completed its logging output and it's safe to signal
|
||||
// the CM thread, the flag's value in the policy has been reset.
|
||||
bool should_start_conc_mark = collector_state()->during_initial_mark_pause();
|
||||
bool should_start_conc_mark = collector_state()->in_initial_mark_gc();
|
||||
|
||||
// Inner scope for scope based logging, timers, and stats collection
|
||||
{
|
||||
EvacuationInfo evacuation_info;
|
||||
|
||||
if (collector_state()->during_initial_mark_pause()) {
|
||||
if (collector_state()->in_initial_mark_gc()) {
|
||||
// We are about to start a marking cycle, so we increment the
|
||||
// full collection counter.
|
||||
increment_old_marking_cycles_started();
|
||||
@ -2790,10 +2789,10 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
|
||||
G1HeapVerifier::G1VerifyType verify_type;
|
||||
FormatBuffer<> gc_string("Pause ");
|
||||
if (collector_state()->during_initial_mark_pause()) {
|
||||
if (collector_state()->in_initial_mark_gc()) {
|
||||
gc_string.append("Initial Mark");
|
||||
verify_type = G1HeapVerifier::G1VerifyInitialMark;
|
||||
} else if (collector_state()->gcs_are_young()) {
|
||||
} else if (collector_state()->in_young_only_phase()) {
|
||||
gc_string.append("Young");
|
||||
verify_type = G1HeapVerifier::G1VerifyYoungOnly;
|
||||
} else {
|
||||
@ -2871,7 +2870,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
|
||||
g1_policy()->record_collection_pause_start(sample_start_time_sec);
|
||||
|
||||
if (collector_state()->during_initial_mark_pause()) {
|
||||
if (collector_state()->in_initial_mark_gc()) {
|
||||
concurrent_mark()->checkpoint_roots_initial_pre();
|
||||
}
|
||||
|
||||
@ -2939,12 +2938,11 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
increase_used(g1_policy()->bytes_copied_during_gc());
|
||||
}
|
||||
|
||||
if (collector_state()->during_initial_mark_pause()) {
|
||||
if (collector_state()->in_initial_mark_gc()) {
|
||||
// We have to do this before we notify the CM threads that
|
||||
// they can start working to make sure that all the
|
||||
// appropriate initialization is done on the CM object.
|
||||
concurrent_mark()->checkpoint_roots_initial_post();
|
||||
collector_state()->set_mark_in_progress(true);
|
||||
// Note that we don't actually trigger the CM thread at
|
||||
// this point. We do that later when we're sure that
|
||||
// the current thread has completed its logging output.
|
||||
@ -4107,7 +4105,7 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per
|
||||
|
||||
// If during an initial mark pause we install a pending list head which is not otherwise reachable
|
||||
// ensure that it is marked in the bitmap for concurrent marking to discover.
|
||||
if (collector_state()->during_initial_mark_pause()) {
|
||||
if (collector_state()->in_initial_mark_gc()) {
|
||||
oop pll_head = Universe::reference_pending_list();
|
||||
if (pll_head != NULL) {
|
||||
// Any valid worker id is fine here as we are in the VM thread and single-threaded.
|
||||
@ -4144,7 +4142,7 @@ void G1CollectedHeap::pre_evacuate_collection_set() {
|
||||
G1GCPhaseTimes* phase_times = g1_policy()->phase_times();
|
||||
|
||||
// InitialMark needs claim bits to keep track of the marked-through CLDs.
|
||||
if (collector_state()->during_initial_mark_pause()) {
|
||||
if (collector_state()->in_initial_mark_gc()) {
|
||||
double start_clear_claimed_marks = os::elapsedTime();
|
||||
|
||||
ClassLoaderDataGraph::clear_claimed_marks();
|
||||
@ -5011,7 +5009,7 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, InCSetState d
|
||||
}
|
||||
_g1_policy->remset_tracker()->update_at_allocate(new_alloc_region);
|
||||
_hr_printer.alloc(new_alloc_region);
|
||||
bool during_im = collector_state()->during_initial_mark_pause();
|
||||
bool during_im = collector_state()->in_initial_mark_gc();
|
||||
new_alloc_region->note_start_of_copying(during_im);
|
||||
return new_alloc_region;
|
||||
}
|
||||
@ -5021,7 +5019,7 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, InCSetState d
|
||||
void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region,
|
||||
size_t allocated_bytes,
|
||||
InCSetState dest) {
|
||||
bool during_im = collector_state()->during_initial_mark_pause();
|
||||
bool during_im = collector_state()->in_initial_mark_gc();
|
||||
alloc_region->note_end_of_copying(during_im);
|
||||
g1_policy()->record_bytes_copied_during_gc(allocated_bytes);
|
||||
if (dest.is_old()) {
|
||||
|
||||
@ -812,9 +812,9 @@ private:
|
||||
// Set whether G1EvacuationFailureALot should be in effect
|
||||
// for the current GC (based upon the type of GC and which
|
||||
// command line flags are set);
|
||||
inline bool evacuation_failure_alot_for_gc_type(bool gcs_are_young,
|
||||
inline bool evacuation_failure_alot_for_gc_type(bool for_young_gc,
|
||||
bool during_initial_mark,
|
||||
bool during_marking);
|
||||
bool mark_or_rebuild_in_progress);
|
||||
|
||||
inline void set_evacuation_failure_alot_for_current_gc();
|
||||
|
||||
|
||||
@ -152,17 +152,17 @@ void G1CollectedHeap::register_humongous_region_with_cset(uint index) {
|
||||
// Support for G1EvacuationFailureALot
|
||||
|
||||
inline bool
|
||||
G1CollectedHeap::evacuation_failure_alot_for_gc_type(bool gcs_are_young,
|
||||
G1CollectedHeap::evacuation_failure_alot_for_gc_type(bool for_young_gc,
|
||||
bool during_initial_mark,
|
||||
bool during_marking) {
|
||||
bool mark_or_rebuild_in_progress) {
|
||||
bool res = false;
|
||||
if (during_marking) {
|
||||
if (mark_or_rebuild_in_progress) {
|
||||
res |= G1EvacuationFailureALotDuringConcMark;
|
||||
}
|
||||
if (during_initial_mark) {
|
||||
res |= G1EvacuationFailureALotDuringInitialMark;
|
||||
}
|
||||
if (gcs_are_young) {
|
||||
if (for_young_gc) {
|
||||
res |= G1EvacuationFailureALotDuringYoungGC;
|
||||
} else {
|
||||
// GCs are mixed
|
||||
@ -186,14 +186,14 @@ G1CollectedHeap::set_evacuation_failure_alot_for_current_gc() {
|
||||
_evacuation_failure_alot_for_current_gc = (elapsed_gcs >= G1EvacuationFailureALotInterval);
|
||||
|
||||
// Now check if G1EvacuationFailureALot is enabled for the current GC type.
|
||||
const bool gcs_are_young = collector_state()->gcs_are_young();
|
||||
const bool during_im = collector_state()->during_initial_mark_pause();
|
||||
const bool during_marking = collector_state()->mark_in_progress();
|
||||
const bool in_young_only_phase = collector_state()->in_young_only_phase();
|
||||
const bool in_initial_mark_gc = collector_state()->in_initial_mark_gc();
|
||||
const bool mark_or_rebuild_in_progress = collector_state()->mark_or_rebuild_in_progress();
|
||||
|
||||
_evacuation_failure_alot_for_current_gc &=
|
||||
evacuation_failure_alot_for_gc_type(gcs_are_young,
|
||||
during_im,
|
||||
during_marking);
|
||||
evacuation_failure_alot_for_gc_type(in_young_only_phase,
|
||||
in_initial_mark_gc,
|
||||
mark_or_rebuild_in_progress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ CollectionSetChooser* G1CollectionSet::cset_chooser() {
|
||||
}
|
||||
|
||||
double G1CollectionSet::predict_region_elapsed_time_ms(HeapRegion* hr) {
|
||||
return _policy->predict_region_elapsed_time_ms(hr, collector_state()->gcs_are_young());
|
||||
return _policy->predict_region_elapsed_time_ms(hr, collector_state()->in_young_only_phase());
|
||||
}
|
||||
|
||||
G1CollectionSet::G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy) :
|
||||
@ -255,21 +255,23 @@ void G1CollectionSet::add_young_region_common(HeapRegion* hr) {
|
||||
// are calculated, aggregated with the policy collection set info,
|
||||
// and cached in the heap region here (initially) and (subsequently)
|
||||
// by the Young List sampling code.
|
||||
// Ignore calls to this due to retirement during full gc.
|
||||
|
||||
size_t rs_length = hr->rem_set()->occupied();
|
||||
double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr);
|
||||
if (!G1CollectedHeap::heap()->collector_state()->in_full_gc()) {
|
||||
size_t rs_length = hr->rem_set()->occupied();
|
||||
double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr);
|
||||
|
||||
// Cache the values we have added to the aggregated information
|
||||
// in the heap region in case we have to remove this region from
|
||||
// the incremental collection set, or it is updated by the
|
||||
// rset sampling code
|
||||
hr->set_recorded_rs_length(rs_length);
|
||||
hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms);
|
||||
// Cache the values we have added to the aggregated information
|
||||
// in the heap region in case we have to remove this region from
|
||||
// the incremental collection set, or it is updated by the
|
||||
// rset sampling code
|
||||
hr->set_recorded_rs_length(rs_length);
|
||||
hr->set_predicted_elapsed_time_ms(region_elapsed_time_ms);
|
||||
|
||||
size_t used_bytes = hr->used();
|
||||
_inc_recorded_rs_lengths += rs_length;
|
||||
_inc_predicted_elapsed_time_ms += region_elapsed_time_ms;
|
||||
_inc_bytes_used_before += used_bytes;
|
||||
_inc_recorded_rs_lengths += rs_length;
|
||||
_inc_predicted_elapsed_time_ms += region_elapsed_time_ms;
|
||||
_inc_bytes_used_before += hr->used();
|
||||
}
|
||||
|
||||
assert(!hr->in_collection_set(), "invariant");
|
||||
_g1->register_young_region_with_cset(hr);
|
||||
@ -366,8 +368,6 @@ double G1CollectionSet::finalize_young_part(double target_pause_time_ms, G1Survi
|
||||
log_trace(gc, ergo, cset)("Start choosing CSet. pending cards: " SIZE_FORMAT " predicted base time: %1.2fms remaining time: %1.2fms target pause time: %1.2fms",
|
||||
pending_cards, base_time_ms, time_remaining_ms, target_pause_time_ms);
|
||||
|
||||
collector_state()->set_last_gc_was_young(collector_state()->gcs_are_young());
|
||||
|
||||
// The young list is laid with the survivor regions from the previous
|
||||
// pause are appended to the RHS of the young list, i.e.
|
||||
// [Newly Young Regions ++ Survivors from last pause].
|
||||
@ -411,7 +411,7 @@ void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
|
||||
double non_young_start_time_sec = os::elapsedTime();
|
||||
double predicted_old_time_ms = 0.0;
|
||||
|
||||
if (!collector_state()->gcs_are_young()) {
|
||||
if (collector_state()->in_mixed_phase()) {
|
||||
cset_chooser()->verify();
|
||||
const uint min_old_cset_length = _policy->calc_min_old_cset_length();
|
||||
const uint max_old_cset_length = _policy->calc_max_old_cset_length();
|
||||
|
||||
@ -28,18 +28,17 @@
|
||||
#include "gc/g1/g1YCTypes.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
// Various state variables that indicate
|
||||
// the phase of the G1 collection.
|
||||
// State of the G1 collection.
|
||||
class G1CollectorState {
|
||||
// Indicates whether we are in "full young" or "mixed" GC mode.
|
||||
bool _gcs_are_young;
|
||||
// Was the last GC "young"?
|
||||
bool _last_gc_was_young;
|
||||
// Is this the "last young GC" before we start doing mixed GCs?
|
||||
// Set after a concurrent mark has completed.
|
||||
bool _last_young_gc;
|
||||
// Indicates whether we are in the phase where we do partial gcs that only contain
|
||||
// the young generation. Not set while _in_full_gc is set.
|
||||
bool _in_young_only_phase;
|
||||
|
||||
// If initiate_conc_mark_if_possible() is set at the beginning of a
|
||||
// Indicates whether we are in the last young gc before the mixed gc phase. This GC
|
||||
// is required to keep pause time requirements.
|
||||
bool _in_young_gc_before_mixed;
|
||||
|
||||
// If _initiate_conc_mark_if_possible is set at the beginning of a
|
||||
// pause, it is a suggestion that the pause should start a marking
|
||||
// cycle by doing the initial-mark work. However, it is possible
|
||||
// that the concurrent marking thread is still finishing up the
|
||||
@ -48,81 +47,68 @@ class G1CollectorState {
|
||||
// we'll have to wait for the concurrent marking thread to finish
|
||||
// what it is doing. In this case we will postpone the marking cycle
|
||||
// initiation decision for the next pause. When we eventually decide
|
||||
// to start a cycle, we will set _during_initial_mark_pause which
|
||||
// will stay true until the end of the initial-mark pause and it's
|
||||
// the condition that indicates that a pause is doing the
|
||||
// to start a cycle, we will set _in_initial_mark_gc which
|
||||
// will stay true until the end of the initial-mark pause doing the
|
||||
// initial-mark work.
|
||||
volatile bool _during_initial_mark_pause;
|
||||
volatile bool _in_initial_mark_gc;
|
||||
|
||||
// At the end of a pause we check the heap occupancy and we decide
|
||||
// whether we will start a marking cycle during the next pause. If
|
||||
// we decide that we want to do that, we will set this parameter to
|
||||
// true. So, this parameter will stay true between the end of a
|
||||
// pause and the beginning of a subsequent pause (not necessarily
|
||||
// the next one, see the comments on the next field) when we decide
|
||||
// that we will indeed start a marking cycle and do the initial-mark
|
||||
// work.
|
||||
// we decide that we want to do that, set this parameter. This parameter will
|
||||
// stay set until the beginning of a subsequent pause (not necessarily
|
||||
// the next one) when we decide that we will indeed start a marking cycle and
|
||||
// do the initial-mark work.
|
||||
volatile bool _initiate_conc_mark_if_possible;
|
||||
|
||||
// NOTE: if some of these are synonyms for others,
|
||||
// the redundant fields should be eliminated. XXX
|
||||
bool _during_marking;
|
||||
bool _mark_in_progress;
|
||||
bool _in_marking_window;
|
||||
bool _in_marking_window_im;
|
||||
// Marking or rebuilding remembered set work is in progress. Set from the end
|
||||
// of the initial mark pause to the end of the Cleanup pause.
|
||||
bool _mark_or_rebuild_in_progress;
|
||||
|
||||
bool _full_collection;
|
||||
// Set during a full gc pause.
|
||||
bool _in_full_gc;
|
||||
|
||||
public:
|
||||
G1CollectorState() :
|
||||
_gcs_are_young(true),
|
||||
_last_gc_was_young(false),
|
||||
_last_young_gc(false),
|
||||
public:
|
||||
G1CollectorState() :
|
||||
_in_young_only_phase(true),
|
||||
_in_young_gc_before_mixed(false),
|
||||
|
||||
_during_initial_mark_pause(false),
|
||||
_initiate_conc_mark_if_possible(false),
|
||||
_in_initial_mark_gc(false),
|
||||
_initiate_conc_mark_if_possible(false),
|
||||
|
||||
_during_marking(false),
|
||||
_mark_in_progress(false),
|
||||
_in_marking_window(false),
|
||||
_in_marking_window_im(false),
|
||||
_full_collection(false) {}
|
||||
_mark_or_rebuild_in_progress(false),
|
||||
_in_full_gc(false) { }
|
||||
|
||||
// Phase setters
|
||||
void set_in_young_only_phase(bool v) { _in_young_only_phase = v; }
|
||||
|
||||
// Pause setters
|
||||
void set_in_young_gc_before_mixed(bool v) { _in_young_gc_before_mixed = v; }
|
||||
void set_in_initial_mark_gc(bool v) { _in_initial_mark_gc = v; }
|
||||
void set_in_full_gc(bool v) { _in_full_gc = v; }
|
||||
|
||||
// Setters
|
||||
void set_gcs_are_young(bool v) { _gcs_are_young = v; }
|
||||
void set_last_gc_was_young(bool v) { _last_gc_was_young = v; }
|
||||
void set_last_young_gc(bool v) { _last_young_gc = v; }
|
||||
void set_during_initial_mark_pause(bool v) { _during_initial_mark_pause = v; }
|
||||
void set_initiate_conc_mark_if_possible(bool v) { _initiate_conc_mark_if_possible = v; }
|
||||
void set_during_marking(bool v) { _during_marking = v; }
|
||||
void set_mark_in_progress(bool v) { _mark_in_progress = v; }
|
||||
void set_in_marking_window(bool v) { _in_marking_window = v; }
|
||||
void set_in_marking_window_im(bool v) { _in_marking_window_im = v; }
|
||||
void set_full_collection(bool v) { _full_collection = v; }
|
||||
|
||||
// Getters
|
||||
bool gcs_are_young() const { return _gcs_are_young; }
|
||||
bool last_gc_was_young() const { return _last_gc_was_young; }
|
||||
bool last_young_gc() const { return _last_young_gc; }
|
||||
bool during_initial_mark_pause() const { return _during_initial_mark_pause; }
|
||||
void set_mark_or_rebuild_in_progress(bool v) { _mark_or_rebuild_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; }
|
||||
|
||||
// Specific pauses
|
||||
bool in_young_gc_before_mixed() const { return _in_young_gc_before_mixed; }
|
||||
bool in_full_gc() const { return _in_full_gc; }
|
||||
bool in_initial_mark_gc() const { return _in_initial_mark_gc; }
|
||||
|
||||
bool initiate_conc_mark_if_possible() const { return _initiate_conc_mark_if_possible; }
|
||||
bool during_marking() const { return _during_marking; }
|
||||
bool mark_in_progress() const { return _mark_in_progress; }
|
||||
bool in_marking_window() const { return _in_marking_window; }
|
||||
bool in_marking_window_im() const { return _in_marking_window_im; }
|
||||
bool full_collection() const { return _full_collection; }
|
||||
|
||||
// Composite booleans (clients worry about flickering)
|
||||
bool during_concurrent_mark() const {
|
||||
return (_in_marking_window && !_in_marking_window_im);
|
||||
}
|
||||
bool mark_or_rebuild_in_progress() const { return _mark_or_rebuild_in_progress; }
|
||||
|
||||
G1YCType yc_type() const {
|
||||
if (during_initial_mark_pause()) {
|
||||
if (in_initial_mark_gc()) {
|
||||
return InitialMark;
|
||||
} else if (mark_in_progress()) {
|
||||
return DuringMark;
|
||||
} else if (gcs_are_young()) {
|
||||
} else if (mark_or_rebuild_in_progress()) {
|
||||
return DuringMarkOrRebuild;
|
||||
} else if (in_young_only_phase()) {
|
||||
return Normal;
|
||||
} else {
|
||||
return Mixed;
|
||||
|
||||
@ -656,7 +656,7 @@ private:
|
||||
// will have them as guarantees at the beginning / end of the bitmap
|
||||
// clearing to get some checking in the product.
|
||||
assert(_cm == NULL || _cm->cm_thread()->during_cycle(), "invariant");
|
||||
assert(_cm == NULL || !G1CollectedHeap::heap()->collector_state()->mark_in_progress(), "invariant");
|
||||
assert(_cm == NULL || !G1CollectedHeap::heap()->collector_state()->mark_or_rebuild_in_progress(), "invariant");
|
||||
}
|
||||
assert(cur == end, "Must have completed iteration over the bitmap for region %u.", r->hrm_index());
|
||||
|
||||
@ -710,13 +710,13 @@ void G1ConcurrentMark::cleanup_for_next_mark() {
|
||||
// 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_in_progress(), "invariant");
|
||||
guarantee(!_g1h->collector_state()->mark_or_rebuild_in_progress(), "invariant");
|
||||
|
||||
clear_bitmap(_next_mark_bitmap, _concurrent_workers, true);
|
||||
|
||||
// Repeat the asserts from above.
|
||||
guarantee(cm_thread()->during_cycle(), "invariant");
|
||||
guarantee(!_g1h->collector_state()->mark_in_progress(), "invariant");
|
||||
guarantee(!_g1h->collector_state()->mark_or_rebuild_in_progress(), "invariant");
|
||||
}
|
||||
|
||||
void G1ConcurrentMark::clear_prev_bitmap(WorkGang* workers) {
|
||||
@ -1063,7 +1063,6 @@ void G1ConcurrentMark::checkpoint_roots_final(bool clear_all_soft_refs) {
|
||||
|
||||
// If a full collection has happened, we shouldn't do this.
|
||||
if (has_aborted()) {
|
||||
g1h->collector_state()->set_mark_in_progress(false); // So bitmap clearing isn't confused
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1251,7 +1250,6 @@ void G1ConcurrentMark::cleanup() {
|
||||
|
||||
// If a full collection has happened, we shouldn't do this.
|
||||
if (has_aborted()) {
|
||||
g1h->collector_state()->set_mark_in_progress(false); // So bitmap clearing isn't confused
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1273,8 +1271,6 @@ void G1ConcurrentMark::cleanup() {
|
||||
g1h->heap_region_iterate(&cl);
|
||||
}
|
||||
|
||||
g1h->collector_state()->set_mark_in_progress(false);
|
||||
|
||||
double count_end = os::elapsedTime();
|
||||
double this_final_counting_time = (count_end - start);
|
||||
_total_counting_time += this_final_counting_time;
|
||||
@ -1900,7 +1896,7 @@ public:
|
||||
|
||||
void G1ConcurrentMark::verify_no_cset_oops() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
|
||||
if (!G1CollectedHeap::heap()->collector_state()->mark_in_progress()) {
|
||||
if (!G1CollectedHeap::heap()->collector_state()->mark_or_rebuild_in_progress()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -228,8 +228,8 @@ public:
|
||||
|
||||
if (_hrclaimer->claim_region(hr->hrm_index())) {
|
||||
if (hr->evacuation_failed()) {
|
||||
bool during_initial_mark = _g1h->collector_state()->during_initial_mark_pause();
|
||||
bool during_conc_mark = _g1h->collector_state()->mark_in_progress();
|
||||
bool during_initial_mark = _g1h->collector_state()->in_initial_mark_gc();
|
||||
bool during_conc_mark = _g1h->collector_state()->mark_or_rebuild_in_progress();
|
||||
|
||||
hr->note_self_forwarding_removal_start(during_initial_mark,
|
||||
during_conc_mark);
|
||||
|
||||
@ -424,7 +424,7 @@ void G1HeapVerifier::verify(VerifyOption vo) {
|
||||
|
||||
bool failures = rootsCl.failures() || codeRootsCl.failures();
|
||||
|
||||
if (!_g1h->g1_policy()->collector_state()->full_collection()) {
|
||||
if (!_g1h->g1_policy()->collector_state()->in_full_gc()) {
|
||||
// If we're verifying during a full GC then the region sets
|
||||
// will have been torn down at the start of the GC. Therefore
|
||||
// verifying the region sets will fail. So we only verify
|
||||
@ -651,10 +651,10 @@ bool G1HeapVerifier::verify_bitmaps(const char* caller, HeapRegion* hr) {
|
||||
bool res_p = verify_no_bits_over_tams("prev", prev_bitmap, ptams, end);
|
||||
|
||||
bool res_n = true;
|
||||
// We reset mark_in_progress() before we reset _cmThread->in_progress() and in this window
|
||||
// We reset mark_or_rebuild_in_progress() before we reset _cmThread->in_progress() and in this window
|
||||
// we do the clearing of the next bitmap concurrently. Thus, we can not verify the bitmap
|
||||
// if we happen to be in that state.
|
||||
if (_g1h->collector_state()->mark_in_progress() || !_g1h->_cmThread->in_progress()) {
|
||||
if (_g1h->collector_state()->mark_or_rebuild_in_progress() || !_g1h->_cmThread->in_progress()) {
|
||||
res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end);
|
||||
}
|
||||
if (!res_p || !res_n) {
|
||||
|
||||
@ -229,7 +229,7 @@ G1Policy::YoungTargetLengths G1Policy::young_list_target_lengths(size_t rs_lengt
|
||||
|
||||
uint young_list_target_length = 0;
|
||||
if (adaptive_young_list_length()) {
|
||||
if (collector_state()->gcs_are_young()) {
|
||||
if (collector_state()->in_young_only_phase()) {
|
||||
young_list_target_length =
|
||||
calculate_young_list_target_length(rs_lengths,
|
||||
base_min_length,
|
||||
@ -281,7 +281,7 @@ G1Policy::calculate_young_list_target_length(size_t rs_lengths,
|
||||
uint desired_min_length,
|
||||
uint desired_max_length) const {
|
||||
assert(adaptive_young_list_length(), "pre-condition");
|
||||
assert(collector_state()->gcs_are_young(), "only call this for young GCs");
|
||||
assert(collector_state()->in_young_only_phase(), "only call this for young GCs");
|
||||
|
||||
// In case some edge-condition makes the desired max length too small...
|
||||
if (desired_max_length <= desired_min_length) {
|
||||
@ -302,7 +302,7 @@ G1Policy::calculate_young_list_target_length(size_t rs_lengths,
|
||||
const double survivor_regions_evac_time = predict_survivor_regions_evac_time();
|
||||
const size_t pending_cards = _analytics->predict_pending_cards();
|
||||
const size_t adj_rs_lengths = rs_lengths + _analytics->predict_rs_length_diff();
|
||||
const size_t scanned_cards = _analytics->predict_card_num(adj_rs_lengths, /* gcs_are_young */ true);
|
||||
const size_t scanned_cards = _analytics->predict_card_num(adj_rs_lengths, true /* for_young_gc */);
|
||||
const double base_time_ms =
|
||||
predict_base_elapsed_time_ms(pending_cards, scanned_cards) +
|
||||
survivor_regions_evac_time;
|
||||
@ -313,7 +313,7 @@ G1Policy::calculate_young_list_target_length(size_t rs_lengths,
|
||||
// Here, we will make sure that the shortest young length that
|
||||
// makes sense fits within the target pause time.
|
||||
|
||||
G1YoungLengthPredictor p(collector_state()->during_concurrent_mark(),
|
||||
G1YoungLengthPredictor p(collector_state()->mark_or_rebuild_in_progress(),
|
||||
base_time_ms,
|
||||
base_free_regions,
|
||||
target_pause_time_ms,
|
||||
@ -384,7 +384,7 @@ double G1Policy::predict_survivor_regions_evac_time() const {
|
||||
for (GrowableArrayIterator<HeapRegion*> it = survivor_regions->begin();
|
||||
it != survivor_regions->end();
|
||||
++it) {
|
||||
survivor_regions_evac_time += predict_region_elapsed_time_ms(*it, collector_state()->gcs_are_young());
|
||||
survivor_regions_evac_time += predict_region_elapsed_time_ms(*it, collector_state()->in_young_only_phase());
|
||||
}
|
||||
return survivor_regions_evac_time;
|
||||
}
|
||||
@ -406,7 +406,7 @@ void G1Policy::update_rs_lengths_prediction() {
|
||||
}
|
||||
|
||||
void G1Policy::update_rs_lengths_prediction(size_t prediction) {
|
||||
if (collector_state()->gcs_are_young() && adaptive_young_list_length()) {
|
||||
if (collector_state()->in_young_only_phase() && adaptive_young_list_length()) {
|
||||
_rs_lengths_prediction = prediction;
|
||||
}
|
||||
}
|
||||
@ -414,7 +414,8 @@ void G1Policy::update_rs_lengths_prediction(size_t prediction) {
|
||||
void G1Policy::record_full_collection_start() {
|
||||
_full_collection_start_sec = os::elapsedTime();
|
||||
// Release the future to-space so that it is available for compaction into.
|
||||
collector_state()->set_full_collection(true);
|
||||
collector_state()->set_in_young_only_phase(false);
|
||||
collector_state()->set_in_full_gc(true);
|
||||
cset_chooser()->clear();
|
||||
}
|
||||
|
||||
@ -427,16 +428,15 @@ void G1Policy::record_full_collection_end() {
|
||||
|
||||
_analytics->update_recent_gc_times(end_sec, full_gc_time_ms);
|
||||
|
||||
collector_state()->set_full_collection(false);
|
||||
collector_state()->set_in_full_gc(false);
|
||||
|
||||
// "Nuke" the heuristics that control the young/mixed GC
|
||||
// transitions and make sure we start with young GCs after the Full GC.
|
||||
collector_state()->set_gcs_are_young(true);
|
||||
collector_state()->set_last_young_gc(false);
|
||||
collector_state()->set_in_young_only_phase(true);
|
||||
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", 0));
|
||||
collector_state()->set_during_initial_mark_pause(false);
|
||||
collector_state()->set_in_marking_window(false);
|
||||
collector_state()->set_in_marking_window_im(false);
|
||||
collector_state()->set_in_initial_mark_gc(false);
|
||||
collector_state()->set_mark_or_rebuild_in_progress(false);
|
||||
|
||||
_short_lived_surv_rate_group->start_adding_regions();
|
||||
// also call this on any additional surv rate groups
|
||||
@ -468,8 +468,6 @@ void G1Policy::record_collection_pause_start(double start_time_sec) {
|
||||
_collection_set->reset_bytes_used_before();
|
||||
_bytes_copied_during_gc = 0;
|
||||
|
||||
collector_state()->set_last_gc_was_young(false);
|
||||
|
||||
// do that for any other surv rate groups
|
||||
_short_lived_surv_rate_group->stop_adding_regions();
|
||||
_survivors_age_table.clear();
|
||||
@ -478,14 +476,12 @@ void G1Policy::record_collection_pause_start(double start_time_sec) {
|
||||
}
|
||||
|
||||
void G1Policy::record_concurrent_mark_init_end(double mark_init_elapsed_time_ms) {
|
||||
collector_state()->set_during_marking(true);
|
||||
assert(!collector_state()->initiate_conc_mark_if_possible(), "we should have cleared it by now");
|
||||
collector_state()->set_during_initial_mark_pause(false);
|
||||
collector_state()->set_in_initial_mark_gc(false);
|
||||
}
|
||||
|
||||
void G1Policy::record_concurrent_mark_remark_start() {
|
||||
_mark_remark_start_sec = os::elapsedTime();
|
||||
collector_state()->set_during_marking(false);
|
||||
}
|
||||
|
||||
void G1Policy::record_concurrent_mark_remark_end() {
|
||||
@ -528,7 +524,7 @@ CollectionSetChooser* G1Policy::cset_chooser() const {
|
||||
}
|
||||
|
||||
bool G1Policy::about_to_start_mixed_phase() const {
|
||||
return _g1->concurrent_mark()->cm_thread()->during_cycle() || collector_state()->last_young_gc();
|
||||
return _g1->concurrent_mark()->cm_thread()->during_cycle() || collector_state()->in_young_gc_before_mixed();
|
||||
}
|
||||
|
||||
bool G1Policy::need_to_start_conc_mark(const char* source, size_t alloc_word_size) {
|
||||
@ -544,7 +540,7 @@ bool G1Policy::need_to_start_conc_mark(const char* source, size_t alloc_word_siz
|
||||
|
||||
bool result = false;
|
||||
if (marking_request_bytes > marking_initiating_used_threshold) {
|
||||
result = collector_state()->gcs_are_young() && !collector_state()->last_young_gc();
|
||||
result = collector_state()->in_young_only_phase() && !collector_state()->in_young_gc_before_mixed();
|
||||
log_debug(gc, ergo, ihop)("%s occupancy: " SIZE_FORMAT "B allocation request: " SIZE_FORMAT "B threshold: " SIZE_FORMAT "B (%1.2f) source: %s",
|
||||
result ? "Request concurrent cycle initiation (occupancy higher than threshold)" : "Do not request concurrent cycle initiation (still doing mixed collections)",
|
||||
cur_used_bytes, alloc_byte_size, marking_initiating_used_threshold, (double) marking_initiating_used_threshold / _g1->capacity() * 100, source);
|
||||
@ -561,15 +557,17 @@ void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_sc
|
||||
|
||||
size_t cur_used_bytes = _g1->used();
|
||||
assert(cur_used_bytes == _g1->recalculate_used(), "It should!");
|
||||
bool last_pause_included_initial_mark = false;
|
||||
bool this_pause_included_initial_mark = false;
|
||||
bool this_pause_was_young_only = collector_state()->in_young_only_phase();
|
||||
|
||||
bool update_stats = !_g1->evacuation_failed();
|
||||
|
||||
record_pause(young_gc_pause_kind(), end_time_sec - pause_time_ms / 1000.0, end_time_sec);
|
||||
|
||||
_collection_pause_end_millis = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
|
||||
|
||||
last_pause_included_initial_mark = collector_state()->during_initial_mark_pause();
|
||||
if (last_pause_included_initial_mark) {
|
||||
this_pause_included_initial_mark = collector_state()->in_initial_mark_gc();
|
||||
if (this_pause_included_initial_mark) {
|
||||
record_concurrent_mark_init_end(0.0);
|
||||
} else {
|
||||
maybe_start_marking();
|
||||
@ -602,28 +600,19 @@ void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_sc
|
||||
_analytics->compute_pause_time_ratio(interval_ms, pause_time_ms);
|
||||
}
|
||||
|
||||
bool new_in_marking_window = collector_state()->in_marking_window();
|
||||
bool new_in_marking_window_im = false;
|
||||
if (last_pause_included_initial_mark) {
|
||||
new_in_marking_window = true;
|
||||
new_in_marking_window_im = true;
|
||||
}
|
||||
|
||||
if (collector_state()->last_young_gc()) {
|
||||
assert(!last_pause_included_initial_mark, "The last young GC is not allowed to be an initial mark GC");
|
||||
// This has been the "last young GC" before we start doing mixed GCs. We already
|
||||
if (collector_state()->in_young_gc_before_mixed()) {
|
||||
assert(!this_pause_included_initial_mark, "The young GC before mixed is not allowed to be an initial mark GC");
|
||||
// This has been the young GC before we start doing mixed GCs. We already
|
||||
// decided to start mixed GCs much earlier, so there is nothing to do except
|
||||
// advancing the state.
|
||||
collector_state()->set_gcs_are_young(false);
|
||||
collector_state()->set_last_young_gc(false);
|
||||
}
|
||||
|
||||
if (!collector_state()->last_gc_was_young()) {
|
||||
collector_state()->set_in_young_only_phase(false);
|
||||
collector_state()->set_in_young_gc_before_mixed(false);
|
||||
} else if (!this_pause_was_young_only) {
|
||||
// This is a mixed GC. Here we decide whether to continue doing more
|
||||
// mixed GCs or not.
|
||||
if (!next_gc_should_be_mixed("continue mixed GCs",
|
||||
"do not continue mixed GCs")) {
|
||||
collector_state()->set_gcs_are_young(true);
|
||||
collector_state()->set_in_young_only_phase(true);
|
||||
|
||||
clear_collection_set_candidates();
|
||||
maybe_start_marking();
|
||||
@ -646,13 +635,13 @@ void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_sc
|
||||
double cost_per_entry_ms = 0.0;
|
||||
if (cards_scanned > 10) {
|
||||
cost_per_entry_ms = average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
|
||||
_analytics->report_cost_per_entry_ms(cost_per_entry_ms, collector_state()->last_gc_was_young());
|
||||
_analytics->report_cost_per_entry_ms(cost_per_entry_ms, this_pause_was_young_only);
|
||||
}
|
||||
|
||||
if (_max_rs_lengths > 0) {
|
||||
double cards_per_entry_ratio =
|
||||
(double) cards_scanned / (double) _max_rs_lengths;
|
||||
_analytics->report_cards_per_entry_ratio(cards_per_entry_ratio, collector_state()->last_gc_was_young());
|
||||
_analytics->report_cards_per_entry_ratio(cards_per_entry_ratio, this_pause_was_young_only);
|
||||
}
|
||||
|
||||
// This is defensive. For a while _max_rs_lengths could get
|
||||
@ -681,7 +670,7 @@ void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_sc
|
||||
|
||||
if (copied_bytes > 0) {
|
||||
cost_per_byte_ms = average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes;
|
||||
_analytics->report_cost_per_byte_ms(cost_per_byte_ms, collector_state()->in_marking_window());
|
||||
_analytics->report_cost_per_byte_ms(cost_per_byte_ms, collector_state()->mark_or_rebuild_in_progress());
|
||||
}
|
||||
|
||||
if (_collection_set->young_region_length() > 0) {
|
||||
@ -700,8 +689,12 @@ void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_sc
|
||||
_analytics->report_rs_lengths((double) _max_rs_lengths);
|
||||
}
|
||||
|
||||
collector_state()->set_in_marking_window(new_in_marking_window);
|
||||
collector_state()->set_in_marking_window_im(new_in_marking_window_im);
|
||||
assert(!(this_pause_included_initial_mark && collector_state()->mark_or_rebuild_in_progress()),
|
||||
"If the last pause has been an initial mark, we should not have been in the marking window");
|
||||
if (this_pause_included_initial_mark) {
|
||||
collector_state()->set_mark_or_rebuild_in_progress(true);
|
||||
}
|
||||
|
||||
_free_regions_at_end_of_collection = _g1->num_free_regions();
|
||||
// IHOP control wants to know the expected young gen length if it were not
|
||||
// restrained by the heap reserve. Using the actual length would make the
|
||||
@ -712,7 +705,8 @@ void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_sc
|
||||
|
||||
update_ihop_prediction(app_time_ms / 1000.0,
|
||||
_bytes_allocated_in_old_since_last_gc,
|
||||
last_unrestrained_young_length * HeapRegion::GrainBytes);
|
||||
last_unrestrained_young_length * HeapRegion::GrainBytes,
|
||||
this_pause_was_young_only);
|
||||
_bytes_allocated_in_old_since_last_gc = 0;
|
||||
|
||||
_ihop_control->send_trace_event(_g1->gc_tracer_stw());
|
||||
@ -730,8 +724,8 @@ void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_sc
|
||||
update_rs_time_goal_ms -= scan_hcc_time_ms;
|
||||
}
|
||||
_g1->concurrent_refine()->adjust(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
|
||||
phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
|
||||
update_rs_time_goal_ms);
|
||||
phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
|
||||
update_rs_time_goal_ms);
|
||||
|
||||
cset_chooser()->verify();
|
||||
}
|
||||
@ -749,7 +743,8 @@ G1IHOPControl* G1Policy::create_ihop_control(const G1Predictions* predictor){
|
||||
|
||||
void G1Policy::update_ihop_prediction(double mutator_time_s,
|
||||
size_t mutator_alloc_bytes,
|
||||
size_t young_gen_size) {
|
||||
size_t young_gen_size,
|
||||
bool this_gc_was_young_only) {
|
||||
// Always try to update IHOP prediction. Even evacuation failures give information
|
||||
// about e.g. whether to start IHOP earlier next time.
|
||||
|
||||
@ -760,7 +755,7 @@ void G1Policy::update_ihop_prediction(double mutator_time_s,
|
||||
bool report = false;
|
||||
|
||||
double marking_to_mixed_time = -1.0;
|
||||
if (!collector_state()->last_gc_was_young() && _initial_mark_to_mixed.has_result()) {
|
||||
if (!this_gc_was_young_only && _initial_mark_to_mixed.has_result()) {
|
||||
marking_to_mixed_time = _initial_mark_to_mixed.last_marking_time();
|
||||
assert(marking_to_mixed_time > 0.0,
|
||||
"Initial mark to mixed time must be larger than zero but is %.3f",
|
||||
@ -775,7 +770,7 @@ void G1Policy::update_ihop_prediction(double mutator_time_s,
|
||||
// all of them. In many applications there are only a few if any young gcs during
|
||||
// marking, which makes any prediction useless. This increases the accuracy of the
|
||||
// prediction.
|
||||
if (collector_state()->last_gc_was_young() && mutator_time_s > min_valid_time) {
|
||||
if (this_gc_was_young_only && mutator_time_s > min_valid_time) {
|
||||
_ihop_control->update_allocation_info(mutator_time_s, mutator_alloc_bytes, young_gen_size);
|
||||
report = true;
|
||||
}
|
||||
@ -811,13 +806,13 @@ double G1Policy::predict_base_elapsed_time_ms(size_t pending_cards,
|
||||
size_t scanned_cards) const {
|
||||
return
|
||||
_analytics->predict_rs_update_time_ms(pending_cards) +
|
||||
_analytics->predict_rs_scan_time_ms(scanned_cards, collector_state()->gcs_are_young()) +
|
||||
_analytics->predict_rs_scan_time_ms(scanned_cards, collector_state()->in_young_only_phase()) +
|
||||
_analytics->predict_constant_other_time_ms();
|
||||
}
|
||||
|
||||
double G1Policy::predict_base_elapsed_time_ms(size_t pending_cards) const {
|
||||
size_t rs_length = _analytics->predict_rs_lengths() + _analytics->predict_rs_length_diff();
|
||||
size_t card_num = _analytics->predict_card_num(rs_length, collector_state()->gcs_are_young());
|
||||
size_t card_num = _analytics->predict_card_num(rs_length, collector_state()->in_young_only_phase());
|
||||
return predict_base_elapsed_time_ms(pending_cards, card_num);
|
||||
}
|
||||
|
||||
@ -843,8 +838,8 @@ double G1Policy::predict_region_elapsed_time_ms(HeapRegion* hr,
|
||||
size_t bytes_to_copy = predict_bytes_to_copy(hr);
|
||||
|
||||
double region_elapsed_time_ms =
|
||||
_analytics->predict_rs_scan_time_ms(card_num, collector_state()->gcs_are_young()) +
|
||||
_analytics->predict_object_copy_time_ms(bytes_to_copy, collector_state()->during_concurrent_mark());
|
||||
_analytics->predict_rs_scan_time_ms(card_num, collector_state()->in_young_only_phase()) +
|
||||
_analytics->predict_object_copy_time_ms(bytes_to_copy, collector_state()->mark_or_rebuild_in_progress());
|
||||
|
||||
// The prediction of the "other" time for this region is based
|
||||
// upon the region type and NOT the GC type.
|
||||
@ -927,7 +922,7 @@ bool G1Policy::force_initial_mark_if_outside_cycle(GCCause::Cause gc_cause) {
|
||||
}
|
||||
|
||||
void G1Policy::initiate_conc_mark() {
|
||||
collector_state()->set_during_initial_mark_pause(true);
|
||||
collector_state()->set_in_initial_mark_gc(true);
|
||||
collector_state()->set_initiate_conc_mark_if_possible(false);
|
||||
}
|
||||
|
||||
@ -935,26 +930,26 @@ void G1Policy::decide_on_conc_mark_initiation() {
|
||||
// We are about to decide on whether this pause will be an
|
||||
// initial-mark pause.
|
||||
|
||||
// First, collector_state()->during_initial_mark_pause() should not be already set. We
|
||||
// First, collector_state()->in_initial_mark_gc() should not be already set. We
|
||||
// will set it here if we have to. However, it should be cleared by
|
||||
// the end of the pause (it's only set for the duration of an
|
||||
// initial-mark pause).
|
||||
assert(!collector_state()->during_initial_mark_pause(), "pre-condition");
|
||||
assert(!collector_state()->in_initial_mark_gc(), "pre-condition");
|
||||
|
||||
if (collector_state()->initiate_conc_mark_if_possible()) {
|
||||
// We had noticed on a previous pause that the heap occupancy has
|
||||
// gone over the initiating threshold and we should start a
|
||||
// concurrent marking cycle. So we might initiate one.
|
||||
|
||||
if (!about_to_start_mixed_phase() && collector_state()->gcs_are_young()) {
|
||||
if (!about_to_start_mixed_phase() && collector_state()->in_young_only_phase()) {
|
||||
// Initiate a new initial mark if there is no marking or reclamation going on.
|
||||
initiate_conc_mark();
|
||||
log_debug(gc, ergo)("Initiate concurrent cycle (concurrent cycle initiation requested)");
|
||||
} else if (_g1->is_user_requested_concurrent_full_gc(_g1->gc_cause())) {
|
||||
// Initiate a user requested initial mark. An initial mark must be young only
|
||||
// GC, so the collector state must be updated to reflect this.
|
||||
collector_state()->set_gcs_are_young(true);
|
||||
collector_state()->set_last_young_gc(false);
|
||||
collector_state()->set_in_young_only_phase(true);
|
||||
collector_state()->set_in_young_gc_before_mixed(false);
|
||||
|
||||
// We might have ended up coming here about to start a mixed phase with a collection set
|
||||
// active. The following remark might change the change the "evacuation efficiency" of
|
||||
@ -990,8 +985,8 @@ void G1Policy::record_concurrent_mark_cleanup_end() {
|
||||
clear_collection_set_candidates();
|
||||
abort_time_to_mixed_tracking();
|
||||
}
|
||||
collector_state()->set_last_young_gc(mixed_gc_pending);
|
||||
collector_state()->set_in_marking_window(false);
|
||||
collector_state()->set_in_young_gc_before_mixed(mixed_gc_pending);
|
||||
collector_state()->set_mark_or_rebuild_in_progress(false);
|
||||
|
||||
double end_sec = os::elapsedTime();
|
||||
double elapsed_time_ms = (end_sec - _mark_cleanup_start_sec) * 1000.0;
|
||||
@ -1030,23 +1025,20 @@ void G1Policy::maybe_start_marking() {
|
||||
}
|
||||
|
||||
G1Policy::PauseKind G1Policy::young_gc_pause_kind() const {
|
||||
assert(!collector_state()->full_collection(), "must be");
|
||||
if (collector_state()->during_initial_mark_pause()) {
|
||||
assert(collector_state()->last_gc_was_young(), "must be");
|
||||
assert(!collector_state()->last_young_gc(), "must be");
|
||||
assert(!collector_state()->in_full_gc(), "must be");
|
||||
if (collector_state()->in_initial_mark_gc()) {
|
||||
assert(!collector_state()->in_young_gc_before_mixed(), "must be");
|
||||
return InitialMarkGC;
|
||||
} else if (collector_state()->last_young_gc()) {
|
||||
assert(!collector_state()->during_initial_mark_pause(), "must be");
|
||||
assert(collector_state()->last_gc_was_young(), "must be");
|
||||
} else if (collector_state()->in_young_gc_before_mixed()) {
|
||||
assert(!collector_state()->in_initial_mark_gc(), "must be");
|
||||
return LastYoungGC;
|
||||
} else if (!collector_state()->last_gc_was_young()) {
|
||||
assert(!collector_state()->during_initial_mark_pause(), "must be");
|
||||
assert(!collector_state()->last_young_gc(), "must be");
|
||||
} else if (collector_state()->in_mixed_phase()) {
|
||||
assert(!collector_state()->in_initial_mark_gc(), "must be");
|
||||
assert(!collector_state()->in_young_gc_before_mixed(), "must be");
|
||||
return MixedGC;
|
||||
} else {
|
||||
assert(collector_state()->last_gc_was_young(), "must be");
|
||||
assert(!collector_state()->during_initial_mark_pause(), "must be");
|
||||
assert(!collector_state()->last_young_gc(), "must be");
|
||||
assert(!collector_state()->in_initial_mark_gc(), "must be");
|
||||
assert(!collector_state()->in_young_gc_before_mixed(), "must be");
|
||||
return YoungOnlyGC;
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +58,8 @@ class G1Policy: public CHeapObj<mtGC> {
|
||||
// Update the IHOP control with necessary statistics.
|
||||
void update_ihop_prediction(double mutator_time_s,
|
||||
size_t mutator_alloc_bytes,
|
||||
size_t young_gen_size);
|
||||
size_t young_gen_size,
|
||||
bool this_gc_was_young_only);
|
||||
void report_ihop_statistics();
|
||||
|
||||
G1Predictions _predictor;
|
||||
@ -105,6 +106,10 @@ class G1Policy: public CHeapObj<mtGC> {
|
||||
size_t _bytes_allocated_in_old_since_last_gc;
|
||||
|
||||
G1InitialMarkToMixedTimeTracker _initial_mark_to_mixed;
|
||||
|
||||
bool should_update_surv_rate_group_predictors() {
|
||||
return collector_state()->in_young_only_phase() && !collector_state()->mark_or_rebuild_in_progress();
|
||||
}
|
||||
public:
|
||||
const G1Predictions& predictor() const { return _predictor; }
|
||||
const G1Analytics* analytics() const { return const_cast<const G1Analytics*>(_analytics); }
|
||||
@ -136,10 +141,6 @@ public:
|
||||
|
||||
double predict_survivor_regions_evac_time() const;
|
||||
|
||||
bool should_update_surv_rate_group_predictors() {
|
||||
return collector_state()->last_gc_was_young() && !collector_state()->in_marking_window();
|
||||
}
|
||||
|
||||
void cset_regions_freed() {
|
||||
bool update = should_update_surv_rate_group_predictors();
|
||||
|
||||
@ -358,7 +359,7 @@ public:
|
||||
// has to be the first thing that the pause does). If
|
||||
// initiate_conc_mark_if_possible() is true, and the concurrent
|
||||
// marking thread has completed its work during the previous cycle,
|
||||
// it will set during_initial_mark_pause() to so that the pause does
|
||||
// it will set in_initial_mark_gc() to so that the pause does
|
||||
// the initial-mark work and start a marking cycle.
|
||||
void decide_on_conc_mark_initiation();
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2018, 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
|
||||
@ -34,8 +34,8 @@ class G1EvacuationClosures : public G1EvacuationRootClosures {
|
||||
public:
|
||||
G1EvacuationClosures(G1CollectedHeap* g1h,
|
||||
G1ParScanThreadState* pss,
|
||||
bool gcs_are_young) :
|
||||
_closures(g1h, pss, gcs_are_young, /* must_claim_cld */ false) {}
|
||||
bool in_young_gc) :
|
||||
_closures(g1h, pss, in_young_gc, /* must_claim_cld */ false) {}
|
||||
|
||||
OopClosure* weak_oops() { return &_closures._buffered_oops; }
|
||||
OopClosure* strong_oops() { return &_closures._buffered_oops; }
|
||||
@ -112,14 +112,14 @@ public:
|
||||
|
||||
G1EvacuationRootClosures* G1EvacuationRootClosures::create_root_closures(G1ParScanThreadState* pss, G1CollectedHeap* g1h) {
|
||||
G1EvacuationRootClosures* res = NULL;
|
||||
if (g1h->collector_state()->during_initial_mark_pause()) {
|
||||
if (g1h->collector_state()->in_initial_mark_gc()) {
|
||||
if (ClassUnloadingWithConcurrentMark) {
|
||||
res = new G1InitialMarkClosures<G1MarkPromotedFromRoot>(g1h, pss);
|
||||
} else {
|
||||
res = new G1InitialMarkClosures<G1MarkFromRoot>(g1h, pss);
|
||||
}
|
||||
} else {
|
||||
res = new G1EvacuationClosures(g1h, pss, g1h->collector_state()->gcs_are_young());
|
||||
res = new G1EvacuationClosures(g1h, pss, g1h->collector_state()->in_young_only_phase());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2018, 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
|
||||
@ -133,7 +133,7 @@ void G1RootProcessor::evacuate_roots(G1EvacuationRootClosures* closures, uint wo
|
||||
// as implicitly live).
|
||||
{
|
||||
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SATBFiltering, worker_i);
|
||||
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_filter_satb_buffers) && _g1h->collector_state()->mark_in_progress()) {
|
||||
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_filter_satb_buffers) && _g1h->collector_state()->mark_or_rebuild_in_progress()) {
|
||||
JavaThread::satb_mark_queue_set().filter_thread_buffers();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018, 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
|
||||
@ -30,7 +30,7 @@
|
||||
enum G1YCType {
|
||||
Normal,
|
||||
InitialMark,
|
||||
DuringMark,
|
||||
DuringMarkOrRebuild,
|
||||
Mixed,
|
||||
G1YCTypeEndSentinel
|
||||
};
|
||||
@ -41,7 +41,7 @@ class G1YCTypeHelper {
|
||||
switch(type) {
|
||||
case Normal: return "Normal";
|
||||
case InitialMark: return "Initial Mark";
|
||||
case DuringMark: return "During Mark";
|
||||
case DuringMarkOrRebuild: return "During Mark";
|
||||
case Mixed: return "Mixed";
|
||||
default: ShouldNotReachHere(); return NULL;
|
||||
}
|
||||
|
||||
@ -653,7 +653,7 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
return;
|
||||
} else {
|
||||
vl_cl.set_containing_obj(obj);
|
||||
if (!g1->collector_state()->full_collection() || G1VerifyRSetsDuringFullGC) {
|
||||
if (!g1->collector_state()->in_full_gc() || G1VerifyRSetsDuringFullGC) {
|
||||
// verify liveness and rem_set
|
||||
vr_cl.set_containing_obj(obj);
|
||||
G1Mux2Closure mux(&vl_cl, &vr_cl);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user