@@ -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