Skip to content

Commit f4f2f32

Browse files
committedDec 21, 2021
8278917: Use Prev Bitmap for recording evac failed objects
Reviewed-by: ayang, mli, tschatzl
1 parent 29bd736 commit f4f2f32

16 files changed

+118
-308
lines changed
 

‎src/hotspot/share/gc/g1/g1CollectedHeap.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -2957,14 +2957,18 @@ void G1CollectedHeap::record_obj_copy_mem_stats() {
29572957
create_g1_evac_summary(&_old_evac_stats));
29582958
}
29592959

2960+
void G1CollectedHeap::clear_prev_bitmap_for_region(HeapRegion* hr) {
2961+
MemRegion mr(hr->bottom(), hr->end());
2962+
concurrent_mark()->clear_range_in_prev_bitmap(mr);
2963+
}
2964+
29602965
void G1CollectedHeap::free_region(HeapRegion* hr, FreeRegionList* free_list) {
29612966
assert(!hr->is_free(), "the region should not be free");
29622967
assert(!hr->is_empty(), "the region should not be empty");
29632968
assert(_hrm.is_available(hr->hrm_index()), "region should be committed");
29642969

29652970
if (G1VerifyBitmaps) {
2966-
MemRegion mr(hr->bottom(), hr->end());
2967-
concurrent_mark()->clear_range_in_prev_bitmap(mr);
2971+
clear_prev_bitmap_for_region(hr);
29682972
}
29692973

29702974
// Clear the card counts for this region.

‎src/hotspot/share/gc/g1/g1CollectedHeap.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,8 @@ class G1CollectedHeap : public CollectedHeap {
622622
// for all regions.
623623
void verify_region_attr_remset_is_tracked() PRODUCT_RETURN;
624624

625+
void clear_prev_bitmap_for_region(HeapRegion* hr);
626+
625627
bool is_user_requested_concurrent_full_gc(GCCause::Cause cause);
626628

627629
// This is called at the start of either a concurrent cycle or a Full
@@ -1252,6 +1254,9 @@ class G1CollectedHeap : public CollectedHeap {
12521254
inline bool is_obj_dead_full(const oop obj, const HeapRegion* hr) const;
12531255
inline bool is_obj_dead_full(const oop obj) const;
12541256

1257+
// Mark the live object that failed evacuation in the prev bitmap.
1258+
inline void mark_evac_failure_object(const oop obj, uint worker_id) const;
1259+
12551260
G1ConcurrentMark* concurrent_mark() const { return _cm; }
12561261

12571262
// Refinement

‎src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#include "gc/g1/g1BarrierSet.hpp"
3131
#include "gc/g1/g1CollectorState.hpp"
32+
#include "gc/g1/g1ConcurrentMark.inline.hpp"
3233
#include "gc/g1/g1EvacFailureRegions.hpp"
3334
#include "gc/g1/g1Policy.hpp"
3435
#include "gc/g1/g1RemSet.hpp"
@@ -247,6 +248,13 @@ inline bool G1CollectedHeap::is_obj_dead_full(const oop obj) const {
247248
return is_obj_dead_full(obj, heap_region_containing(obj));
248249
}
249250

251+
inline void G1CollectedHeap::mark_evac_failure_object(const oop obj, uint worker_id) const {
252+
// All objects failing evacuation are live. What we'll do is
253+
// that we'll update the prev marking info so that they are
254+
// all under PTAMS and explicitly marked.
255+
_cm->par_mark_in_prev_bitmap(obj);
256+
}
257+
250258
inline void G1CollectedHeap::set_humongous_reclaim_candidate(uint region, bool value) {
251259
assert(_hrm.at(region)->is_starts_humongous(), "Must start a humongous object");
252260
_humongous_reclaim_candidates.set_candidate(region, value);

‎src/hotspot/share/gc/g1/g1ConcurrentMark.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
563563
void cleanup();
564564
// Mark in the previous bitmap. Caution: the prev bitmap is usually read-only, so use
565565
// this carefully.
566-
inline void mark_in_prev_bitmap(oop p);
566+
inline void par_mark_in_prev_bitmap(oop p);
567567

568568
// Clears marks for all objects in the given range, for the prev or
569569
// next bitmaps. Caution: the previous bitmap is usually

‎src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,8 @@ inline bool G1CMTask::deal_with_reference(T* p) {
268268
return make_reference_grey(obj);
269269
}
270270

271-
inline void G1ConcurrentMark::mark_in_prev_bitmap(oop p) {
272-
assert(!_prev_mark_bitmap->is_marked(p), "sanity");
273-
_prev_mark_bitmap->mark(p);
271+
inline void G1ConcurrentMark::par_mark_in_prev_bitmap(oop p) {
272+
_prev_mark_bitmap->par_mark(p);
274273
}
275274

276275
bool G1ConcurrentMark::is_marked_in_prev_bitmap(oop p) const {

‎src/hotspot/share/gc/g1/g1EvacFailure.cpp

+26-25
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
#include "oops/compressedOops.inline.hpp"
3838
#include "oops/oop.inline.hpp"
3939

40-
class RemoveSelfForwardPtrObjClosure: public ObjectClosure {
40+
class RemoveSelfForwardPtrObjClosure {
4141
G1CollectedHeap* _g1h;
4242
G1ConcurrentMark* _cm;
4343
HeapRegion* _hr;
@@ -60,13 +60,13 @@ class RemoveSelfForwardPtrObjClosure: public ObjectClosure {
6060

6161
size_t marked_bytes() { return _marked_words * HeapWordSize; }
6262

63-
// Iterate over the live objects in the region to find self-forwarded objects
63+
// Handle the marked objects in the region. These are self-forwarded objects
6464
// that need to be kept live. We need to update the remembered sets of these
6565
// objects. Further update the BOT and marks.
6666
// We can coalesce and overwrite the remaining heap contents with dummy objects
6767
// as they have either been dead or evacuated (which are unreferenced now, i.e.
6868
// dead too) already.
69-
void do_object(oop obj) {
69+
size_t apply(oop obj) {
7070
HeapWord* obj_addr = cast_from_oop<HeapWord*>(obj);
7171
assert(_last_forwarded_object_end <= obj_addr, "should iterate in ascending address order");
7272
assert(_hr->is_in(obj_addr), "sanity");
@@ -75,12 +75,9 @@ class RemoveSelfForwardPtrObjClosure: public ObjectClosure {
7575
assert(obj->is_forwarded() && obj->forwardee() == obj, "sanity");
7676

7777
zap_dead_objects(_last_forwarded_object_end, obj_addr);
78-
// We consider all objects that we find self-forwarded to be
79-
// live. What we'll do is that we'll update the prev marking
80-
// info so that they are all under PTAMS and explicitly marked.
81-
if (!_cm->is_marked_in_prev_bitmap(obj)) {
82-
_cm->mark_in_prev_bitmap(obj);
83-
}
78+
79+
// Zapping clears the bitmap, make sure it didn't clear too much.
80+
assert(_cm->is_marked_in_prev_bitmap(obj), "should be correctly marked");
8481
if (_during_concurrent_start) {
8582
// For the next marking info we'll only mark the
8683
// self-forwarded objects explicitly if we are during
@@ -92,7 +89,7 @@ class RemoveSelfForwardPtrObjClosure: public ObjectClosure {
9289
// explicitly and all objects in the CSet are considered
9390
// (implicitly) live. So, we won't mark them explicitly and
9491
// we'll leave them over NTAMS.
95-
_cm->mark_in_next_bitmap(_worker_id, _hr, obj);
92+
_cm->mark_in_next_bitmap(_worker_id, obj);
9693
}
9794
size_t obj_size = obj->size();
9895

@@ -102,6 +99,7 @@ class RemoveSelfForwardPtrObjClosure: public ObjectClosure {
10299
HeapWord* obj_end = obj_addr + obj_size;
103100
_last_forwarded_object_end = obj_end;
104101
_hr->alloc_block_in_bot(obj_addr, obj_end);
102+
return obj_size;
105103
}
106104

107105
// Fill the memory area from start to end with filler objects, and update the BOT
@@ -161,8 +159,11 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
161159
RemoveSelfForwardPtrObjClosure rspc(hr,
162160
during_concurrent_start,
163161
_worker_id);
164-
// Iterates evac failure objs which are recorded during evacuation.
165-
hr->process_and_drop_evac_failure_objs(&rspc);
162+
163+
// All objects that failed evacuation has been marked in the prev bitmap.
164+
// Use the bitmap to apply the above closure to all failing objects.
165+
G1CMBitMap* bitmap = const_cast<G1CMBitMap*>(_g1h->concurrent_mark()->prev_mark_bitmap());
166+
hr->apply_to_marked_objects(bitmap, &rspc);
166167
// Need to zap the remainder area of the processed region.
167168
rspc.zap_remainder();
168169

@@ -172,26 +173,26 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
172173
bool do_heap_region(HeapRegion *hr) {
173174
assert(!hr->is_pinned(), "Unexpected pinned region at index %u", hr->hrm_index());
174175
assert(hr->in_collection_set(), "bad CS");
176+
assert(_evac_failure_regions->contains(hr->hrm_index()), "precondition");
175177

176-
if (_evac_failure_regions->contains(hr->hrm_index())) {
177-
hr->clear_index_in_opt_cset();
178+
hr->clear_index_in_opt_cset();
178179

179-
bool during_concurrent_start = _g1h->collector_state()->in_concurrent_start_gc();
180-
bool during_concurrent_mark = _g1h->collector_state()->mark_or_rebuild_in_progress();
180+
bool during_concurrent_start = _g1h->collector_state()->in_concurrent_start_gc();
181+
bool during_concurrent_mark = _g1h->collector_state()->mark_or_rebuild_in_progress();
181182

182-
hr->note_self_forwarding_removal_start(during_concurrent_start,
183-
during_concurrent_mark);
184-
_g1h->verifier()->check_bitmaps("Self-Forwarding Ptr Removal", hr);
183+
hr->note_self_forwarding_removal_start(during_concurrent_start,
184+
during_concurrent_mark);
185185

186-
hr->reset_bot();
186+
hr->reset_bot();
187187

188-
size_t live_bytes = remove_self_forward_ptr_by_walking_hr(hr, during_concurrent_start);
188+
size_t live_bytes = remove_self_forward_ptr_by_walking_hr(hr, during_concurrent_start);
189189

190-
hr->rem_set()->clean_strong_code_roots(hr);
191-
hr->rem_set()->clear_locked(true);
190+
hr->rem_set()->clean_strong_code_roots(hr);
191+
hr->rem_set()->clear_locked(true);
192+
193+
hr->note_self_forwarding_removal_end(live_bytes);
194+
_g1h->verifier()->check_bitmaps("Self-Forwarding Ptr Removal", hr);
192195

193-
hr->note_self_forwarding_removal_end(live_bytes);
194-
}
195196
return false;
196197
}
197198
};

‎src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.cpp

-123
This file was deleted.

‎src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.hpp

-82
This file was deleted.

‎src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.inline.hpp

-40
This file was deleted.

‎src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp

+17-6
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,16 @@ class G1ResetSkipCompactingClosure : public HeapRegionClosure {
5858
}
5959
};
6060

61+
void G1FullGCCompactTask::G1CompactRegionClosure::clear_in_prev_bitmap(oop obj) {
62+
assert(_bitmap->is_marked(obj), "Should only compact marked objects");
63+
_bitmap->clear(obj);
64+
}
65+
6166
size_t G1FullGCCompactTask::G1CompactRegionClosure::apply(oop obj) {
6267
size_t size = obj->size();
6368
if (!obj->is_forwarded()) {
64-
// Object not moving
69+
// Object not moving, but clear the mark to allow reuse of the bitmap.
70+
clear_in_prev_bitmap(obj);
6571
return size;
6672
}
6773

@@ -74,6 +80,9 @@ size_t G1FullGCCompactTask::G1CompactRegionClosure::apply(oop obj) {
7480
cast_to_oop(destination)->init_mark();
7581
assert(cast_to_oop(destination)->klass() != NULL, "should have a class");
7682

83+
// Clear the mark for the compacted object to allow reuse of the
84+
// bitmap without an additional clearing step.
85+
clear_in_prev_bitmap(obj);
7786
return size;
7887
}
7988

@@ -82,13 +91,15 @@ void G1FullGCCompactTask::compact_region(HeapRegion* hr) {
8291
assert(!hr->is_humongous(), "Should be no humongous regions in compaction queue");
8392

8493
if (!collector()->is_free(hr->hrm_index())) {
94+
// The compaction closure not only copies the object to the new
95+
// location, but also clears the bitmap for it. This is needed
96+
// for bitmap verification and to be able to use the prev_bitmap
97+
// for evacuation failures in the next young collection. Testing
98+
// showed that it was better overall to clear bit by bit, compared
99+
// to clearing the whole region at the end. This difference was
100+
// clearly seen for regions with few marks.
85101
G1CompactRegionClosure compact(collector()->mark_bitmap());
86102
hr->apply_to_marked_objects(collector()->mark_bitmap(), &compact);
87-
// Clear the liveness information for this region if necessary i.e. if we actually look at it
88-
// for bitmap verification. Otherwise it is sufficient that we move the TAMS to bottom().
89-
if (G1VerifyBitmaps) {
90-
collector()->mark_bitmap()->clear_region(hr);
91-
}
92103
}
93104

94105
hr->reset_compacted_after_full_gc();

‎src/hotspot/share/gc/g1/g1FullGCCompactTask.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class G1FullGCCompactTask : public G1FullGCTask {
5050

5151
class G1CompactRegionClosure : public StackObj {
5252
G1CMBitMap* _bitmap;
53-
53+
void clear_in_prev_bitmap(oop object);
5454
public:
5555
G1CompactRegionClosure(G1CMBitMap* bitmap) : _bitmap(bitmap) { }
5656
size_t apply(oop object);

‎src/hotspot/share/gc/g1/g1ParScanThreadState.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -616,9 +616,11 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markWord m, siz
616616
if (forward_ptr == NULL) {
617617
// Forward-to-self succeeded. We are the "owner" of the object.
618618
HeapRegion* r = _g1h->heap_region_containing(old);
619-
// Records evac failure objs, this will help speed up iteration
620-
// of these objs later in *remove self forward* phase of post evacuation.
621-
r->record_evac_failure_obj(old);
619+
620+
// Objects failing evacuation will turn into old objects since the regions
621+
// are relabeled as such. We mark the failing objects in the prev bitmap and
622+
// later use it to handle all failed objects.
623+
_g1h->mark_evac_failure_object(old, _worker_id);
622624

623625
if (_evac_failure_regions->record(r->hrm_index())) {
624626
_g1h->hr_printer()->evac_failure(r);

‎src/hotspot/share/gc/g1/g1RemSet.cpp

+46-3
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,46 @@ class G1MergeHeapRootsTask : public WorkerTask {
12591259
G1MergeCardSetStats stats() const { return _stats; }
12601260
};
12611261

1262+
// Closure to clear the prev bitmap for any old region in the collection set.
1263+
// This is needed to be able to use the bitmap for evacuation failure handling.
1264+
class G1ClearBitmapClosure : public HeapRegionClosure {
1265+
G1CollectedHeap* _g1h;
1266+
void assert_bitmap_clear(HeapRegion* hr, const G1CMBitMap* bitmap) {
1267+
assert(bitmap->get_next_marked_addr(hr->bottom(), hr->end()) == hr->end(),
1268+
"Bitmap should have no mark for young regions");
1269+
}
1270+
public:
1271+
G1ClearBitmapClosure(G1CollectedHeap* g1h) : _g1h(g1h) { }
1272+
1273+
bool do_heap_region(HeapRegion* hr) {
1274+
assert(_g1h->is_in_cset(hr), "Should only be used iterating the collection set");
1275+
// Young regions should always have cleared bitmaps, so only clear old.
1276+
if (hr->is_old()) {
1277+
_g1h->clear_prev_bitmap_for_region(hr);
1278+
} else {
1279+
assert(hr->is_young(), "Should only be young and old regions in collection set");
1280+
assert_bitmap_clear(hr, _g1h->concurrent_mark()->prev_mark_bitmap());
1281+
}
1282+
return false;
1283+
}
1284+
};
1285+
1286+
// Helper to allow two closure to be applied when
1287+
// iterating through the collection set.
1288+
class G1CombinedClosure : public HeapRegionClosure {
1289+
HeapRegionClosure* _closure1;
1290+
HeapRegionClosure* _closure2;
1291+
public:
1292+
G1CombinedClosure(HeapRegionClosure* cl1, HeapRegionClosure* cl2) :
1293+
_closure1(cl1),
1294+
_closure2(cl2) { }
1295+
1296+
bool do_heap_region(HeapRegion* hr) {
1297+
return _closure1->do_heap_region(hr) ||
1298+
_closure2->do_heap_region(hr);
1299+
}
1300+
};
1301+
12621302
// Visitor for the remembered sets of humongous candidate regions to merge their
12631303
// remembered set into the card table.
12641304
class G1FlushHumongousCandidateRemSets : public HeapRegionClosure {
@@ -1426,9 +1466,12 @@ class G1MergeHeapRootsTask : public WorkerTask {
14261466
G1GCParPhaseTimesTracker x(p, merge_remset_phase, worker_id, !_initial_evacuation /* allow_multiple_record */);
14271467
G1MergeCardSetStats stats;
14281468
{
1429-
G1MergeCardSetClosure cl(_scan_state);
1430-
g1h->collection_set_iterate_increment_from(&cl, &_hr_claimer, worker_id);
1431-
stats = cl.stats();
1469+
G1MergeCardSetClosure merge(_scan_state);
1470+
G1ClearBitmapClosure clear(g1h);
1471+
G1CombinedClosure combined(&merge, &clear);
1472+
1473+
g1h->collection_set_iterate_increment_from(&combined, &_hr_claimer, worker_id);
1474+
stats = merge.stats();
14321475
}
14331476

14341477
for (uint i = 0; i < G1GCPhaseTimes::MergeRSContainersSentinel; i++) {

‎src/hotspot/share/gc/g1/heapRegion.cpp

+1-6
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,6 @@ void HeapRegion::handle_evacuation_failure() {
107107
_next_marked_bytes = 0;
108108
}
109109

110-
void HeapRegion::process_and_drop_evac_failure_objs(ObjectClosure* closure) {
111-
_evac_failure_objs.process_and_drop(closure);
112-
}
113-
114110
void HeapRegion::unlink_from_list() {
115111
set_next(NULL);
116112
set_prev(NULL);
@@ -246,8 +242,7 @@ HeapRegion::HeapRegion(uint hrm_index,
246242
_prev_marked_bytes(0), _next_marked_bytes(0),
247243
_young_index_in_cset(-1),
248244
_surv_rate_group(NULL), _age_index(G1SurvRateGroup::InvalidAgeIndex), _gc_efficiency(-1.0),
249-
_node_index(G1NUMA::UnknownNodeIndex),
250-
_evac_failure_objs(hrm_index, _bottom)
245+
_node_index(G1NUMA::UnknownNodeIndex)
251246
{
252247
assert(Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end()),
253248
"invalid space boundaries");

‎src/hotspot/share/gc/g1/heapRegion.hpp

-8
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#define SHARE_GC_G1_HEAPREGION_HPP
2727

2828
#include "gc/g1/g1BlockOffsetTable.hpp"
29-
#include "gc/g1/g1EvacFailureObjectsSet.hpp"
3029
#include "gc/g1/g1HeapRegionTraceType.hpp"
3130
#include "gc/g1/g1SurvRateGroup.hpp"
3231
#include "gc/g1/heapRegionTracer.hpp"
@@ -268,8 +267,6 @@ class HeapRegion : public CHeapObj<mtGC> {
268267

269268
uint _node_index;
270269

271-
G1EvacFailureObjectsSet _evac_failure_objs;
272-
273270
void report_region_type_change(G1HeapRegionTraceType::Type to);
274271

275272
// Returns whether the given object address refers to a dead object, and either the
@@ -566,11 +563,6 @@ class HeapRegion : public CHeapObj<mtGC> {
566563

567564
// Update the region state after a failed evacuation.
568565
void handle_evacuation_failure();
569-
// Record an object that failed evacuation within this region.
570-
void record_evac_failure_obj(oop obj);
571-
// Applies the given closure to all previously recorded objects
572-
// that failed evacuation in ascending address order.
573-
void process_and_drop_evac_failure_objs(ObjectClosure* closure);
574566

575567
// Iterate over the objects overlapping the given memory region, applying cl
576568
// to all references in the region. This is a helper for

‎src/hotspot/share/gc/g1/heapRegion.inline.hpp

-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
3131
#include "gc/g1/g1CollectedHeap.inline.hpp"
3232
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
33-
#include "gc/g1/g1EvacFailureObjectsSet.inline.hpp"
3433
#include "gc/g1/g1Predictions.hpp"
3534
#include "gc/g1/g1SegmentedArray.inline.hpp"
3635
#include "oops/oop.inline.hpp"
@@ -439,8 +438,4 @@ inline void HeapRegion::record_surv_words_in_group(size_t words_survived) {
439438
_surv_rate_group->record_surviving_words(age_in_group, words_survived);
440439
}
441440

442-
inline void HeapRegion::record_evac_failure_obj(oop obj) {
443-
_evac_failure_objs.record(obj);
444-
}
445-
446441
#endif // SHARE_GC_G1_HEAPREGION_INLINE_HPP

0 commit comments

Comments
 (0)
Please sign in to comment.