Skip to content

Commit 00b5348

Browse files
committed
8337192: [BACKOUT] JDK-8336098 G1: Refactor G1RebuildRSAndScrubTask
Reviewed-by: tschatzl
1 parent 3baff2a commit 00b5348

File tree

1 file changed

+97
-52
lines changed

1 file changed

+97
-52
lines changed

src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp

Lines changed: 97 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,10 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
8989

9090
// Yield if enough has been processed; returns if the concurrent marking cycle
9191
// has been aborted for any reason.
92-
bool yield_if_necessary(G1HeapRegion* hr) {
92+
bool yield_if_necessary() {
9393
if (_processed_words >= ProcessingYieldLimitInWords) {
9494
reset_processed_words();
95-
// If a yield occurs (potential young-gc pause), must recheck for
96-
// potential regions reclamation.
97-
if (_cm->do_yield_check() && !should_rebuild_or_scrub(hr)) {
98-
return true;
99-
}
95+
_cm->do_yield_check();
10096
}
10197
return _cm->has_aborted();
10298
}
@@ -115,7 +111,8 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
115111
// Helper used by both humongous objects and when chunking an object larger than the
116112
// G1RebuildRemSetChunkSize. The heap region is needed check whether the region has
117113
// been reclaimed during yielding.
118-
void scan_large_object(G1HeapRegion* hr, const oop obj, MemRegion scan_range) {
114+
// Returns true if marking has been aborted or false if completed.
115+
bool scan_large_object(G1HeapRegion* hr, const oop obj, MemRegion scan_range) {
119116
HeapWord* start = scan_range.start();
120117
HeapWord* limit = scan_range.end();
121118
do {
@@ -125,14 +122,20 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
125122
// Update processed words and yield, for humongous objects we will yield
126123
// after each chunk.
127124
add_processed_words(mr.word_size());
128-
129-
if (yield_if_necessary(hr)) {
130-
return;
125+
bool mark_aborted = yield_if_necessary();
126+
if (mark_aborted) {
127+
return true;
128+
} else if (!should_rebuild_or_scrub(hr)) {
129+
// We need to check should_rebuild_or_scrub() again because the region might
130+
// have been reclaimed during above yield/safepoint.
131+
log_trace(gc, marking)("Rebuild aborted for reclaimed region: %u", hr->hrm_index());
132+
return false;
131133
}
132134

133135
// Step to next chunk of the large object.
134136
start = mr.end();
135137
} while (start < limit);
138+
return false;
136139
}
137140

138141
// Scan for references into regions that need remembered set update for the given
@@ -162,66 +165,102 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
162165
return obj_size;
163166
}
164167

165-
// Scan or scrub depending on if addr is marked.
166-
HeapWord* scan_or_scrub(G1HeapRegion* hr, HeapWord* addr, HeapWord* limit) {
167-
if (_bitmap->is_marked(addr)) {
168-
// Live object, need to scan to rebuild remembered sets for this object.
169-
return addr + scan_object(hr, addr);
170-
} else {
171-
// Found dead object (which klass has potentially been unloaded). Scrub to next marked object.
172-
HeapWord* scrub_end = _bitmap->get_next_marked_addr(addr, limit);
173-
hr->fill_range_with_dead_objects(addr, scrub_end);
174-
// Return the next object to handle.
175-
return scrub_end;
168+
// Scrub a range of dead objects starting at scrub_start. Will never scrub past limit.
169+
HeapWord* scrub_to_next_live(G1HeapRegion* hr, HeapWord* scrub_start, HeapWord* limit) {
170+
assert(!_bitmap->is_marked(scrub_start), "Should not scrub live object");
171+
172+
HeapWord* scrub_end = _bitmap->get_next_marked_addr(scrub_start, limit);
173+
hr->fill_range_with_dead_objects(scrub_start, scrub_end);
174+
175+
// Return the next object to handle.
176+
return scrub_end;
177+
}
178+
179+
// Scan the given region from bottom to parsable_bottom. Returns whether marking has
180+
// been aborted.
181+
bool scan_and_scrub_to_pb(G1HeapRegion* hr, HeapWord* start, HeapWord* const limit) {
182+
183+
while (start < limit) {
184+
if (_bitmap->is_marked(start)) {
185+
// Live object, need to scan to rebuild remembered sets for this object.
186+
start += scan_object(hr, start);
187+
} else {
188+
// Found dead object (which klass has potentially been unloaded). Scrub to next
189+
// marked object and continue.
190+
start = scrub_to_next_live(hr, start, limit);
191+
}
192+
193+
bool mark_aborted = yield_if_necessary();
194+
if (mark_aborted) {
195+
return true;
196+
} else if (!should_rebuild_or_scrub(hr)) {
197+
// We need to check should_rebuild_or_scrub() again because the region might
198+
// have been reclaimed during above yield/safepoint.
199+
log_trace(gc, marking)("Scan and scrub aborted for reclaimed region: %u", hr->hrm_index());
200+
return false;
201+
}
176202
}
203+
return false;
177204
}
178205

179-
// Scan and scrub the given region to tars.
180-
void scan_and_scrub_region(G1HeapRegion* hr, HeapWord* const pb) {
206+
// Scan the given region from parsable_bottom to tars. Returns whether marking has
207+
// been aborted.
208+
bool scan_from_pb_to_tars(G1HeapRegion* hr, HeapWord* start, HeapWord* const limit) {
209+
210+
while (start < limit) {
211+
start += scan_object(hr, start);
212+
// Avoid stalling safepoints and stop iteration if mark cycle has been aborted.
213+
bool mark_aborted = yield_if_necessary();
214+
if (mark_aborted) {
215+
return true;
216+
} else if (!should_rebuild_or_scrub(hr)) {
217+
// We need to check should_rebuild_or_scrub() again because the region might
218+
// have been reclaimed during above yield/safepoint.
219+
log_trace(gc, marking)("Scan aborted for reclaimed region: %u", hr->hrm_index());
220+
return false;
221+
}
222+
}
223+
return false;
224+
}
225+
226+
// Scan and scrub the given region to tars. Returns whether marking has
227+
// been aborted.
228+
bool scan_and_scrub_region(G1HeapRegion* hr, HeapWord* const pb) {
181229
assert(should_rebuild_or_scrub(hr), "must be");
182230

183231
log_trace(gc, marking)("Scrub and rebuild region: " HR_FORMAT " pb: " PTR_FORMAT " TARS: " PTR_FORMAT " TAMS: " PTR_FORMAT,
184232
HR_FORMAT_PARAMS(hr), p2i(pb), p2i(_cm->top_at_rebuild_start(hr)), p2i(_cm->top_at_mark_start(hr)));
185233

186-
{
187-
// Step 1: Scan the given region from bottom to parsable_bottom.
188-
HeapWord* start = hr->bottom();
189-
HeapWord* limit = pb;
190-
while (start < limit) {
191-
start = scan_or_scrub(hr, start, limit);
192-
193-
if (yield_if_necessary(hr)) {
194-
return;
195-
}
196-
}
234+
if (scan_and_scrub_to_pb(hr, hr->bottom(), pb)) {
235+
log_trace(gc, marking)("Scan and scrub aborted for region: %u", hr->hrm_index());
236+
return true;
197237
}
198238

239+
// Yielding during scrubbing and scanning might have reclaimed the region, so need to
240+
// re-check after above.
241+
if (!should_rebuild_or_scrub(hr)) {
242+
return false;
243+
}
199244
// Scrubbing completed for this region - notify that we are done with it, resetting
200245
// pb to bottom.
201246
hr->note_end_of_scrubbing();
202247

203-
{
204-
// Step 2: Rebuild from TAMS (= parsable_bottom) to TARS.
205-
HeapWord* start = pb;
206-
HeapWord* limit = _cm->top_at_rebuild_start(hr);
207-
while (start < limit) {
208-
start += scan_object(hr, start);
209-
210-
if (yield_if_necessary(hr)) {
211-
return;
212-
}
213-
}
248+
// Rebuild from TAMS (= parsable_bottom) to TARS.
249+
if (scan_from_pb_to_tars(hr, pb, _cm->top_at_rebuild_start(hr))) {
250+
log_trace(gc, marking)("Rebuild aborted for region: %u (%s)", hr->hrm_index(), hr->get_short_type_str());
251+
return true;
214252
}
253+
return false;
215254
}
216255

217256
// Scan a humongous region for remembered set updates. Scans in chunks to avoid
218-
// stalling safepoints.
219-
void scan_humongous_region(G1HeapRegion* hr, HeapWord* const pb) {
257+
// stalling safepoints. Returns whether the concurrent marking phase has been aborted.
258+
bool scan_humongous_region(G1HeapRegion* hr, HeapWord* const pb) {
220259
assert(should_rebuild_or_scrub(hr), "must be");
221260

222261
if (!_should_rebuild_remset) {
223262
// When not rebuilding there is nothing to do for humongous objects.
224-
return;
263+
return false;
225264
}
226265

227266
// At this point we should only have live humongous objects, that
@@ -239,7 +278,12 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
239278
HeapWord* humongous_end = hr->humongous_start_region()->bottom() + humongous->size();
240279
MemRegion mr(hr->bottom(), MIN2(hr->top(), humongous_end));
241280

242-
scan_large_object(hr, humongous, mr);
281+
bool mark_aborted = scan_large_object(hr, humongous, mr);
282+
if (mark_aborted) {
283+
log_trace(gc, marking)("Rebuild aborted for region: %u (%s)", hr->hrm_index(), hr->get_short_type_str());
284+
return true;
285+
}
286+
return false;
243287
}
244288

245289
public:
@@ -268,16 +312,17 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
268312
return false;
269313
}
270314

315+
bool mark_aborted;
271316
if (hr->needs_scrubbing()) {
272317
// This is a region with potentially unparsable (dead) objects.
273-
scan_and_scrub_region(hr, pb);
318+
mark_aborted = scan_and_scrub_region(hr, pb);
274319
} else {
275320
assert(hr->is_humongous(), "must be, but %u is %s", hr->hrm_index(), hr->get_short_type_str());
276321
// No need to scrub humongous, but we should scan it to rebuild remsets.
277-
scan_humongous_region(hr, pb);
322+
mark_aborted = scan_humongous_region(hr, pb);
278323
}
279324

280-
return _cm->has_aborted();
325+
return mark_aborted;
281326
}
282327
};
283328

0 commit comments

Comments
 (0)