8337267: [REDO] G1: Refactor G1RebuildRSAndScrubTask

Reviewed-by: gli, tschatzl
This commit is contained in:
Albert Mingkun Yang 2024-07-29 12:30:57 +00:00
parent 9124a94e38
commit cd52ad80a8

View File

@ -87,14 +87,19 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
_processed_words += processed;
}
// Yield if enough has been processed; returns if the concurrent marking cycle
// has been aborted for any reason.
bool yield_if_necessary() {
// Yield if enough has been processed. Return whether we should stop
// processing this region because either the concurrent marking cycle has been
// aborted or the region has been reclaimed.
bool yield_if_necessary(G1HeapRegion* hr) {
if (_processed_words >= ProcessingYieldLimitInWords) {
reset_processed_words();
_cm->do_yield_check();
// If a yield occurs (potential young-gc pause), must recheck for
// potential regions reclamation.
if (_cm->do_yield_check() && !should_rebuild_or_scrub(hr)) {
return true;
}
}
return _cm->has_aborted();
return _cm->has_aborted() || !should_rebuild_or_scrub(hr);
}
// Returns whether the top at rebuild start value for the given region indicates
@ -111,8 +116,7 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
// Helper used by both humongous objects and when chunking an object larger than the
// G1RebuildRemSetChunkSize. The heap region is needed check whether the region has
// been reclaimed during yielding.
// Returns true if marking has been aborted or false if completed.
bool scan_large_object(G1HeapRegion* hr, const oop obj, MemRegion scan_range) {
void scan_large_object(G1HeapRegion* hr, const oop obj, MemRegion scan_range) {
HeapWord* start = scan_range.start();
HeapWord* limit = scan_range.end();
do {
@ -122,20 +126,14 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
// Update processed words and yield, for humongous objects we will yield
// after each chunk.
add_processed_words(mr.word_size());
bool mark_aborted = yield_if_necessary();
if (mark_aborted) {
return true;
} else if (!should_rebuild_or_scrub(hr)) {
// We need to check should_rebuild_or_scrub() again because the region might
// have been reclaimed during above yield/safepoint.
log_trace(gc, marking)("Rebuild aborted for reclaimed region: %u", hr->hrm_index());
return false;
if (yield_if_necessary(hr)) {
return;
}
// Step to next chunk of the large object.
start = mr.end();
} while (start < limit);
return false;
}
// Scan for references into regions that need remembered set update for the given
@ -165,102 +163,66 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
return obj_size;
}
// Scrub a range of dead objects starting at scrub_start. Will never scrub past limit.
HeapWord* scrub_to_next_live(G1HeapRegion* hr, HeapWord* scrub_start, HeapWord* limit) {
assert(!_bitmap->is_marked(scrub_start), "Should not scrub live object");
HeapWord* scrub_end = _bitmap->get_next_marked_addr(scrub_start, limit);
hr->fill_range_with_dead_objects(scrub_start, scrub_end);
// Return the next object to handle.
return scrub_end;
}
// Scan the given region from bottom to parsable_bottom. Returns whether marking has
// been aborted.
bool scan_and_scrub_to_pb(G1HeapRegion* hr, HeapWord* start, HeapWord* const limit) {
while (start < limit) {
if (_bitmap->is_marked(start)) {
// Live object, need to scan to rebuild remembered sets for this object.
start += scan_object(hr, start);
} else {
// Found dead object (which klass has potentially been unloaded). Scrub to next
// marked object and continue.
start = scrub_to_next_live(hr, start, limit);
}
bool mark_aborted = yield_if_necessary();
if (mark_aborted) {
return true;
} else if (!should_rebuild_or_scrub(hr)) {
// We need to check should_rebuild_or_scrub() again because the region might
// have been reclaimed during above yield/safepoint.
log_trace(gc, marking)("Scan and scrub aborted for reclaimed region: %u", hr->hrm_index());
return false;
}
// Scan or scrub depending on if addr is marked.
HeapWord* scan_or_scrub(G1HeapRegion* hr, HeapWord* addr, HeapWord* limit) {
if (_bitmap->is_marked(addr)) {
// Live object, need to scan to rebuild remembered sets for this object.
return addr + scan_object(hr, addr);
} else {
// Found dead object (which klass has potentially been unloaded). Scrub to next marked object.
HeapWord* scrub_end = _bitmap->get_next_marked_addr(addr, limit);
hr->fill_range_with_dead_objects(addr, scrub_end);
// Return the next object to handle.
return scrub_end;
}
return false;
}
// Scan the given region from parsable_bottom to tars. Returns whether marking has
// been aborted.
bool scan_from_pb_to_tars(G1HeapRegion* hr, HeapWord* start, HeapWord* const limit) {
while (start < limit) {
start += scan_object(hr, start);
// Avoid stalling safepoints and stop iteration if mark cycle has been aborted.
bool mark_aborted = yield_if_necessary();
if (mark_aborted) {
return true;
} else if (!should_rebuild_or_scrub(hr)) {
// We need to check should_rebuild_or_scrub() again because the region might
// have been reclaimed during above yield/safepoint.
log_trace(gc, marking)("Scan aborted for reclaimed region: %u", hr->hrm_index());
return false;
}
}
return false;
}
// Scan and scrub the given region to tars. Returns whether marking has
// been aborted.
bool scan_and_scrub_region(G1HeapRegion* hr, HeapWord* const pb) {
// Scan and scrub the given region to tars.
void scan_and_scrub_region(G1HeapRegion* hr, HeapWord* const pb) {
assert(should_rebuild_or_scrub(hr), "must be");
log_trace(gc, marking)("Scrub and rebuild region: " HR_FORMAT " pb: " PTR_FORMAT " TARS: " PTR_FORMAT " TAMS: " PTR_FORMAT,
HR_FORMAT_PARAMS(hr), p2i(pb), p2i(_cm->top_at_rebuild_start(hr)), p2i(_cm->top_at_mark_start(hr)));
if (scan_and_scrub_to_pb(hr, hr->bottom(), pb)) {
log_trace(gc, marking)("Scan and scrub aborted for region: %u", hr->hrm_index());
return true;
{
// Step 1: Scan the given region from bottom to parsable_bottom.
HeapWord* start = hr->bottom();
HeapWord* limit = pb;
while (start < limit) {
start = scan_or_scrub(hr, start, limit);
if (yield_if_necessary(hr)) {
return;
}
}
}
// Yielding during scrubbing and scanning might have reclaimed the region, so need to
// re-check after above.
if (!should_rebuild_or_scrub(hr)) {
return false;
}
// Scrubbing completed for this region - notify that we are done with it, resetting
// pb to bottom.
hr->note_end_of_scrubbing();
// Rebuild from TAMS (= parsable_bottom) to TARS.
if (scan_from_pb_to_tars(hr, pb, _cm->top_at_rebuild_start(hr))) {
log_trace(gc, marking)("Rebuild aborted for region: %u (%s)", hr->hrm_index(), hr->get_short_type_str());
return true;
{
// Step 2: Rebuild from TAMS (= parsable_bottom) to TARS.
HeapWord* start = pb;
HeapWord* limit = _cm->top_at_rebuild_start(hr);
while (start < limit) {
start += scan_object(hr, start);
if (yield_if_necessary(hr)) {
return;
}
}
}
return false;
}
// Scan a humongous region for remembered set updates. Scans in chunks to avoid
// stalling safepoints. Returns whether the concurrent marking phase has been aborted.
bool scan_humongous_region(G1HeapRegion* hr, HeapWord* const pb) {
// stalling safepoints.
void scan_humongous_region(G1HeapRegion* hr, HeapWord* const pb) {
assert(should_rebuild_or_scrub(hr), "must be");
if (!_should_rebuild_remset) {
// When not rebuilding there is nothing to do for humongous objects.
return false;
return;
}
// At this point we should only have live humongous objects, that
@ -278,12 +240,7 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
HeapWord* humongous_end = hr->humongous_start_region()->bottom() + humongous->size();
MemRegion mr(hr->bottom(), MIN2(hr->top(), humongous_end));
bool mark_aborted = scan_large_object(hr, humongous, mr);
if (mark_aborted) {
log_trace(gc, marking)("Rebuild aborted for region: %u (%s)", hr->hrm_index(), hr->get_short_type_str());
return true;
}
return false;
scan_large_object(hr, humongous, mr);
}
public:
@ -312,17 +269,16 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
return false;
}
bool mark_aborted;
if (hr->needs_scrubbing()) {
// This is a region with potentially unparsable (dead) objects.
mark_aborted = scan_and_scrub_region(hr, pb);
scan_and_scrub_region(hr, pb);
} else {
assert(hr->is_humongous(), "must be, but %u is %s", hr->hrm_index(), hr->get_short_type_str());
// No need to scrub humongous, but we should scan it to rebuild remsets.
mark_aborted = scan_humongous_region(hr, pb);
scan_humongous_region(hr, pb);
}
return mark_aborted;
return _cm->has_aborted();
}
};