mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
Make sure that two marking cycles do not overlap, i.e., a new one can only start after the concurrent marking thread finishes all its work. In the fix I piggy-back a couple of minor extra fixes: some general code reformatting for consistency (only around the code I modified), the removal of a field (G1CollectorPolicy::_should_initiate_conc_mark) which doesn't seem to be used at all (it's only set but never read), as well as moving the "is GC locker active" test earlier into the G1 pause / Full GC and using a more appropriate method for it. Reviewed-by: johnc, jmasa, jcoomes, ysr
This commit is contained in:
parent
2e3363d109
commit
719e7f0926
5 changed files with 186 additions and 59 deletions
|
@ -178,8 +178,8 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
|||
// so the hack is to do the cast QQQ FIXME
|
||||
_pauses_btwn_concurrent_mark((size_t)G1PausesBtwnConcMark),
|
||||
_n_marks_since_last_pause(0),
|
||||
_conc_mark_initiated(false),
|
||||
_should_initiate_conc_mark(false),
|
||||
_initiate_conc_mark_if_possible(false),
|
||||
_during_initial_mark_pause(false),
|
||||
_should_revert_to_full_young_gcs(false),
|
||||
_last_full_young_gc(false),
|
||||
|
||||
|
@ -793,7 +793,7 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) {
|
|||
elapsed_time_ms,
|
||||
calculations,
|
||||
full_young_gcs() ? "full" : "partial",
|
||||
should_initiate_conc_mark() ? " i-m" : "",
|
||||
during_initial_mark_pause() ? " i-m" : "",
|
||||
_in_marking_window,
|
||||
_in_marking_window_im);
|
||||
#endif // TRACE_CALC_YOUNG_CONFIG
|
||||
|
@ -1040,7 +1040,8 @@ void G1CollectorPolicy::record_full_collection_end() {
|
|||
set_full_young_gcs(true);
|
||||
_last_full_young_gc = false;
|
||||
_should_revert_to_full_young_gcs = false;
|
||||
_should_initiate_conc_mark = false;
|
||||
clear_initiate_conc_mark_if_possible();
|
||||
clear_during_initial_mark_pause();
|
||||
_known_garbage_bytes = 0;
|
||||
_known_garbage_ratio = 0.0;
|
||||
_in_marking_window = false;
|
||||
|
@ -1186,7 +1187,8 @@ void G1CollectorPolicy::record_concurrent_mark_init_start() {
|
|||
void G1CollectorPolicy::record_concurrent_mark_init_end_pre(double
|
||||
mark_init_elapsed_time_ms) {
|
||||
_during_marking = true;
|
||||
_should_initiate_conc_mark = false;
|
||||
assert(!initiate_conc_mark_if_possible(), "we should have cleared it by now");
|
||||
clear_during_initial_mark_pause();
|
||||
_cur_mark_stop_world_time_ms = mark_init_elapsed_time_ms;
|
||||
}
|
||||
|
||||
|
@ -1257,7 +1259,6 @@ void G1CollectorPolicy::record_concurrent_mark_cleanup_end_work2() {
|
|||
}
|
||||
_n_pauses_at_mark_end = _n_pauses;
|
||||
_n_marks_since_last_pause++;
|
||||
_conc_mark_initiated = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1453,17 +1454,24 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
|
|||
#endif // PRODUCT
|
||||
|
||||
if (in_young_gc_mode()) {
|
||||
last_pause_included_initial_mark = _should_initiate_conc_mark;
|
||||
last_pause_included_initial_mark = during_initial_mark_pause();
|
||||
if (last_pause_included_initial_mark)
|
||||
record_concurrent_mark_init_end_pre(0.0);
|
||||
|
||||
size_t min_used_targ =
|
||||
(_g1->capacity() / 100) * InitiatingHeapOccupancyPercent;
|
||||
|
||||
if (cur_used_bytes > min_used_targ) {
|
||||
if (cur_used_bytes <= _prev_collection_pause_used_at_end_bytes) {
|
||||
} else if (!_g1->mark_in_progress() && !_last_full_young_gc) {
|
||||
_should_initiate_conc_mark = true;
|
||||
|
||||
if (!_g1->mark_in_progress() && !_last_full_young_gc) {
|
||||
assert(!last_pause_included_initial_mark, "invariant");
|
||||
if (cur_used_bytes > min_used_targ &&
|
||||
cur_used_bytes > _prev_collection_pause_used_at_end_bytes) {
|
||||
assert(!during_initial_mark_pause(), "we should not see this here");
|
||||
|
||||
// Note: this might have already been set, if during the last
|
||||
// pause we decided to start a cycle but at the beginning of
|
||||
// this pause we decided to postpone it. That's OK.
|
||||
set_initiate_conc_mark_if_possible();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1754,7 +1762,7 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
|
|||
|
||||
bool new_in_marking_window = _in_marking_window;
|
||||
bool new_in_marking_window_im = false;
|
||||
if (_should_initiate_conc_mark) {
|
||||
if (during_initial_mark_pause()) {
|
||||
new_in_marking_window = true;
|
||||
new_in_marking_window_im = true;
|
||||
}
|
||||
|
@ -2173,7 +2181,13 @@ void G1CollectorPolicy::check_if_region_is_too_expensive(double
|
|||
if (predicted_time_ms > _expensive_region_limit_ms) {
|
||||
if (!in_young_gc_mode()) {
|
||||
set_full_young_gcs(true);
|
||||
_should_initiate_conc_mark = true;
|
||||
// We might want to do something different here. However,
|
||||
// right now we don't support the non-generational G1 mode
|
||||
// (and in fact we are planning to remove the associated code,
|
||||
// see CR 6814390). So, let's leave it as is and this will be
|
||||
// removed some time in the future
|
||||
ShouldNotReachHere();
|
||||
set_during_initial_mark_pause();
|
||||
} else
|
||||
// no point in doing another partial one
|
||||
_should_revert_to_full_young_gcs = true;
|
||||
|
@ -2696,6 +2710,50 @@ bool G1CollectorPolicy_BestRegionsFirst::assertMarkedBytesDataOK() {
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
G1CollectorPolicy::decide_on_conc_mark_initiation() {
|
||||
// We are about to decide on whether this pause will be an
|
||||
// initial-mark pause.
|
||||
|
||||
// First, during_initial_mark_pause() 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(!during_initial_mark_pause(), "pre-condition");
|
||||
|
||||
if (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.
|
||||
|
||||
bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle();
|
||||
if (!during_cycle) {
|
||||
// The concurrent marking thread is not "during a cycle", i.e.,
|
||||
// it has completed the last one. So we can go ahead and
|
||||
// initiate a new cycle.
|
||||
|
||||
set_during_initial_mark_pause();
|
||||
|
||||
// And we can now clear initiate_conc_mark_if_possible() as
|
||||
// we've already acted on it.
|
||||
clear_initiate_conc_mark_if_possible();
|
||||
} else {
|
||||
// The concurrent marking thread is still finishing up the
|
||||
// previous cycle. If we start one right now the two cycles
|
||||
// overlap. In particular, the concurrent marking thread might
|
||||
// be in the process of clearing the next marking bitmap (which
|
||||
// we will use for the next cycle if we start one). Starting a
|
||||
// cycle now will be bad given that parts of the marking
|
||||
// information might get cleared by the marking thread. And we
|
||||
// cannot wait for the marking thread to finish the cycle as it
|
||||
// periodically yields while clearing the next marking bitmap
|
||||
// and, if it's in a yield point, it's waiting for us to
|
||||
// finish. So, at this point we will not start a cycle and we'll
|
||||
// let the concurrent marking thread complete the last one.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
G1CollectorPolicy_BestRegionsFirst::
|
||||
record_collection_pause_start(double start_time_sec, size_t start_used) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue