Skip to content

Commit 1dc8fa9

Browse files
author
Thomas Schatzl
committed
8274340: [BACKOUT] JDK-8271880: Tighten condition for excluding regions from collecting cards with cross-references
Reviewed-by: kbarrett, ayang
1 parent aaa36cc commit 1dc8fa9

14 files changed

+95
-97
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3277,7 +3277,6 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, G1HeapRegionA
32773277
new_alloc_region->set_survivor();
32783278
_survivor.add(new_alloc_region);
32793279
_verifier->check_bitmaps("Survivor Region Allocation", new_alloc_region);
3280-
register_new_survivor_region_with_region_attr(new_alloc_region);
32813280
} else {
32823281
new_alloc_region->set_old();
32833282
_verifier->check_bitmaps("Old Region Allocation", new_alloc_region);

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,6 @@ class G1CollectedHeap : public CollectedHeap {
605605
void register_young_region_with_region_attr(HeapRegion* r) {
606606
_region_attr.set_in_young(r->hrm_index());
607607
}
608-
inline void register_new_survivor_region_with_region_attr(HeapRegion* r);
609608
inline void register_region_with_region_attr(HeapRegion* r);
610609
inline void register_old_region_with_region_attr(HeapRegion* r);
611610
inline void register_optional_region_with_region_attr(HeapRegion* r);

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,6 @@ void G1CollectedHeap::register_humongous_region_with_region_attr(uint index) {
184184
_region_attr.set_humongous(index, region_at(index)->rem_set()->is_tracked());
185185
}
186186

187-
void G1CollectedHeap::register_new_survivor_region_with_region_attr(HeapRegion* r) {
188-
_region_attr.set_new_survivor_region(r->hrm_index());
189-
}
190-
191187
void G1CollectedHeap::register_region_with_region_attr(HeapRegion* r) {
192188
_region_attr.set_has_remset(r->hrm_index(), r->rem_set()->is_tracked());
193189
}

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

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,73 @@
3030
#include "gc/g1/g1EvacFailureRegions.hpp"
3131
#include "gc/g1/g1HeapVerifier.hpp"
3232
#include "gc/g1/g1OopClosures.inline.hpp"
33+
#include "gc/g1/g1RedirtyCardsQueue.hpp"
3334
#include "gc/g1/heapRegion.hpp"
3435
#include "gc/g1/heapRegionRemSet.inline.hpp"
3536
#include "gc/shared/preservedMarks.inline.hpp"
3637
#include "oops/access.inline.hpp"
3738
#include "oops/compressedOops.inline.hpp"
3839
#include "oops/oop.inline.hpp"
3940

41+
class UpdateLogBuffersDeferred : public BasicOopIterateClosure {
42+
private:
43+
G1CollectedHeap* _g1h;
44+
G1RedirtyCardsLocalQueueSet* _rdc_local_qset;
45+
G1CardTable* _ct;
46+
47+
// Remember the last enqueued card to avoid enqueuing the same card over and over;
48+
// since we only ever handle a card once, this is sufficient.
49+
size_t _last_enqueued_card;
50+
51+
public:
52+
UpdateLogBuffersDeferred(G1RedirtyCardsLocalQueueSet* rdc_local_qset) :
53+
_g1h(G1CollectedHeap::heap()),
54+
_rdc_local_qset(rdc_local_qset),
55+
_ct(_g1h->card_table()),
56+
_last_enqueued_card(SIZE_MAX) {}
57+
58+
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
59+
virtual void do_oop( oop* p) { do_oop_work(p); }
60+
template <class T> void do_oop_work(T* p) {
61+
assert(_g1h->heap_region_containing(p)->is_in_reserved(p), "paranoia");
62+
assert(!_g1h->heap_region_containing(p)->is_survivor(), "Unexpected evac failure in survivor region");
63+
64+
T const o = RawAccess<>::oop_load(p);
65+
if (CompressedOops::is_null(o)) {
66+
return;
67+
}
68+
69+
if (HeapRegion::is_in_same_region(p, CompressedOops::decode(o))) {
70+
return;
71+
}
72+
size_t card_index = _ct->index_for(p);
73+
if (card_index != _last_enqueued_card) {
74+
_rdc_local_qset->enqueue(_ct->byte_for_index(card_index));
75+
_last_enqueued_card = card_index;
76+
}
77+
}
78+
};
79+
4080
class RemoveSelfForwardPtrObjClosure: public ObjectClosure {
4181
G1CollectedHeap* _g1h;
4282
G1ConcurrentMark* _cm;
4383
HeapRegion* _hr;
4484
size_t _marked_bytes;
85+
UpdateLogBuffersDeferred* _log_buffer_cl;
4586
bool _during_concurrent_start;
4687
uint _worker_id;
4788
HeapWord* _last_forwarded_object_end;
4889

4990
public:
5091
RemoveSelfForwardPtrObjClosure(HeapRegion* hr,
92+
UpdateLogBuffersDeferred* log_buffer_cl,
5193
bool during_concurrent_start,
5294
uint worker_id) :
5395
_g1h(G1CollectedHeap::heap()),
5496
_cm(_g1h->concurrent_mark()),
5597
_hr(hr),
5698
_marked_bytes(0),
99+
_log_buffer_cl(log_buffer_cl),
57100
_during_concurrent_start(during_concurrent_start),
58101
_worker_id(worker_id),
59102
_last_forwarded_object_end(hr->bottom()) { }
@@ -98,6 +141,20 @@ class RemoveSelfForwardPtrObjClosure: public ObjectClosure {
98141
_marked_bytes += (obj_size * HeapWordSize);
99142
PreservedMarks::init_forwarded_mark(obj);
100143

144+
// While we were processing RSet buffers during the collection,
145+
// we actually didn't scan any cards on the collection set,
146+
// since we didn't want to update remembered sets with entries
147+
// that point into the collection set, given that live objects
148+
// from the collection set are about to move and such entries
149+
// will be stale very soon.
150+
// This change also dealt with a reliability issue which
151+
// involved scanning a card in the collection set and coming
152+
// across an array that was being chunked and looking malformed.
153+
// The problem is that, if evacuation fails, we might have
154+
// remembered set entries missing given that we skipped cards on
155+
// the collection set. So, we'll recreate such entries now.
156+
obj->oop_iterate(_log_buffer_cl);
157+
101158
HeapWord* obj_end = obj_addr + obj_size;
102159
_last_forwarded_object_end = obj_end;
103160
_hr->alloc_block_in_bot(obj_addr, obj_end);
@@ -146,22 +203,33 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
146203
G1CollectedHeap* _g1h;
147204
uint _worker_id;
148205

206+
G1RedirtyCardsLocalQueueSet _rdc_local_qset;
207+
UpdateLogBuffersDeferred _log_buffer_cl;
208+
149209
uint volatile* _num_failed_regions;
150210
G1EvacFailureRegions* _evac_failure_regions;
151211

152212
public:
153-
RemoveSelfForwardPtrHRClosure(uint worker_id,
213+
RemoveSelfForwardPtrHRClosure(G1RedirtyCardsQueueSet* rdcqs,
214+
uint worker_id,
154215
uint volatile* num_failed_regions,
155216
G1EvacFailureRegions* evac_failure_regions) :
156217
_g1h(G1CollectedHeap::heap()),
157218
_worker_id(worker_id),
219+
_rdc_local_qset(rdcqs),
220+
_log_buffer_cl(&_rdc_local_qset),
158221
_num_failed_regions(num_failed_regions),
159222
_evac_failure_regions(evac_failure_regions) {
160223
}
161224

225+
~RemoveSelfForwardPtrHRClosure() {
226+
_rdc_local_qset.flush();
227+
}
228+
162229
size_t remove_self_forward_ptr_by_walking_hr(HeapRegion* hr,
163230
bool during_concurrent_start) {
164231
RemoveSelfForwardPtrObjClosure rspc(hr,
232+
&_log_buffer_cl,
165233
during_concurrent_start,
166234
_worker_id);
167235
hr->object_iterate(&rspc);
@@ -200,15 +268,17 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
200268
}
201269
};
202270

203-
G1ParRemoveSelfForwardPtrsTask::G1ParRemoveSelfForwardPtrsTask(G1EvacFailureRegions* evac_failure_regions) :
271+
G1ParRemoveSelfForwardPtrsTask::G1ParRemoveSelfForwardPtrsTask(G1RedirtyCardsQueueSet* rdcqs,
272+
G1EvacFailureRegions* evac_failure_regions) :
204273
AbstractGangTask("G1 Remove Self-forwarding Pointers"),
205274
_g1h(G1CollectedHeap::heap()),
275+
_rdcqs(rdcqs),
206276
_hrclaimer(_g1h->workers()->active_workers()),
207277
_evac_failure_regions(evac_failure_regions),
208278
_num_failed_regions(0) { }
209279

210280
void G1ParRemoveSelfForwardPtrsTask::work(uint worker_id) {
211-
RemoveSelfForwardPtrHRClosure rsfp_cl(worker_id, &_num_failed_regions, _evac_failure_regions);
281+
RemoveSelfForwardPtrHRClosure rsfp_cl(_rdcqs, worker_id, &_num_failed_regions, _evac_failure_regions);
212282

213283
// Iterate through all regions that failed evacuation during the entire collection.
214284
_evac_failure_regions->par_iterate(&rsfp_cl, &_hrclaimer, worker_id);

src/hotspot/share/gc/g1/g1EvacFailure.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,21 @@
3232

3333
class G1CollectedHeap;
3434
class G1EvacFailureRegions;
35+
class G1RedirtyCardsQueueSet;
3536

3637
// Task to fixup self-forwarding pointers
3738
// installed as a result of an evacuation failure.
3839
class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
3940
protected:
4041
G1CollectedHeap* _g1h;
42+
G1RedirtyCardsQueueSet* _rdcqs;
4143
HeapRegionClaimer _hrclaimer;
4244

4345
G1EvacFailureRegions* _evac_failure_regions;
4446
uint volatile _num_failed_regions;
4547

4648
public:
47-
G1ParRemoveSelfForwardPtrsTask(G1EvacFailureRegions* evac_failure_regions);
49+
G1ParRemoveSelfForwardPtrsTask(G1RedirtyCardsQueueSet* rdcqs, G1EvacFailureRegions* evac_failure_regions);
4850

4951
void work(uint worker_id);
5052

src/hotspot/share/gc/g1/g1HeapRegionAttr.hpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ struct G1HeapRegionAttr {
5757
//
5858
// The other values are used for objects in regions requiring various special handling,
5959
// eager reclamation of humongous objects or optional regions.
60-
static const region_type_t Optional = -4; // The region is optional not in the current collection set.
61-
static const region_type_t Humongous = -3; // The region is a humongous candidate not in the current collection set.
62-
static const region_type_t NewSurvivor = -2; // The region is a new (ly allocated) survivor region.
60+
static const region_type_t Optional = -3; // The region is optional not in the current collection set.
61+
static const region_type_t Humongous = -2; // The region is a humongous candidate not in the current collection set.
6362
static const region_type_t NotInCSet = -1; // The region is not in the collection set.
6463
static const region_type_t Young = 0; // The region is in the collection set and a young region.
6564
static const region_type_t Old = 1; // The region is in the collection set and an old region.
@@ -77,7 +76,6 @@ struct G1HeapRegionAttr {
7776
switch (type()) {
7877
case Optional: return "Optional";
7978
case Humongous: return "Humongous";
80-
case NewSurvivor: return "NewSurvivor";
8179
case NotInCSet: return "NotInCSet";
8280
case Young: return "Young";
8381
case Old: return "Old";
@@ -87,7 +85,6 @@ struct G1HeapRegionAttr {
8785

8886
bool needs_remset_update() const { return _needs_remset_update != 0; }
8987

90-
void set_new_survivor() { _type = NewSurvivor; }
9188
void set_old() { _type = Old; }
9289
void clear_humongous() {
9390
assert(is_humongous() || !is_in_cset(), "must be");
@@ -99,7 +96,6 @@ struct G1HeapRegionAttr {
9996
bool is_in_cset() const { return type() >= Young; }
10097

10198
bool is_humongous() const { return type() == Humongous; }
102-
bool is_new_survivor() const { return type() == NewSurvivor; }
10399
bool is_young() const { return type() == Young; }
104100
bool is_old() const { return type() == Old; }
105101
bool is_optional() const { return type() == Optional; }
@@ -132,12 +128,6 @@ class G1HeapRegionAttrBiasedMappedArray : public G1BiasedMappedArray<G1HeapRegio
132128
set_by_index(index, G1HeapRegionAttr(G1HeapRegionAttr::Optional, needs_remset_update));
133129
}
134130

135-
void set_new_survivor_region(uintptr_t index) {
136-
assert(get_by_index(index).is_default(),
137-
"Region attributes at index " INTPTR_FORMAT " should be default but is %s", index, get_by_index(index).get_type_str());
138-
get_ref_by_index(index)->set_new_survivor();
139-
}
140-
141131
void set_humongous(uintptr_t index, bool needs_remset_update) {
142132
assert(get_by_index(index).is_default(),
143133
"Region attributes at index " INTPTR_FORMAT " should be default but is %s", index, get_by_index(index).get_type_str());

src/hotspot/share/gc/g1/g1OopClosures.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ class G1SkipCardEnqueueSetter : public StackObj {
116116
G1ScanEvacuatedObjClosure* _closure;
117117

118118
public:
119-
G1SkipCardEnqueueSetter(G1ScanEvacuatedObjClosure* closure, bool skip_card_enqueue) : _closure(closure) {
119+
G1SkipCardEnqueueSetter(G1ScanEvacuatedObjClosure* closure, bool new_value) : _closure(closure) {
120120
assert(_closure->_skip_card_enqueue == G1ScanEvacuatedObjClosure::Uninitialized, "Must not be set");
121-
_closure->_skip_card_enqueue = skip_card_enqueue ? G1ScanEvacuatedObjClosure::True : G1ScanEvacuatedObjClosure::False;
121+
_closure->_skip_card_enqueue = new_value ? G1ScanEvacuatedObjClosure::True : G1ScanEvacuatedObjClosure::False;
122122
}
123123

124124
~G1SkipCardEnqueueSetter() {

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

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ void G1ParScanThreadState::do_partial_array(PartialArrayScanTask task) {
235235
push_on_queue(ScannerTask(PartialArrayScanTask(from_obj)));
236236
}
237237

238-
G1HeapRegionAttr dest_attr = _g1h->region_attr(to_array);
239-
G1SkipCardEnqueueSetter x(&_scanner, dest_attr.is_new_survivor());
238+
HeapRegion* hr = _g1h->heap_region_containing(to_array);
239+
G1SkipCardEnqueueSetter x(&_scanner, hr->is_young());
240240
// Process claimed task. The length of to_array is not correct, but
241241
// fortunately the iteration ignores the length field and just relies
242242
// on start/end.
@@ -268,11 +268,6 @@ void G1ParScanThreadState::start_partial_objarray(G1HeapRegionAttr dest_attr,
268268
push_on_queue(ScannerTask(PartialArrayScanTask(from_obj)));
269269
}
270270

271-
// Skip the card enqueue iff the object (to_array) is in survivor region.
272-
// However, HeapRegion::is_survivor() is too expensive here.
273-
// Instead, we use dest_attr.is_young() because the two values are always
274-
// equal: successfully allocated young regions must be survivor regions.
275-
assert(dest_attr.is_young() == _g1h->heap_region_containing(to_array)->is_survivor(), "must be");
276271
G1SkipCardEnqueueSetter x(&_scanner, dest_attr.is_young());
277272
// Process the initial chunk. No need to process the type in the
278273
// klass, as it will already be handled by processing the built-in
@@ -524,11 +519,6 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio
524519
_string_dedup_requests.add(old);
525520
}
526521

527-
// Skip the card enqueue iff the object (obj) is in survivor region.
528-
// However, HeapRegion::is_survivor() is too expensive here.
529-
// Instead, we use dest_attr.is_young() because the two values are always
530-
// equal: successfully allocated young regions must be survivor regions.
531-
assert(dest_attr.is_young() == _g1h->heap_region_containing(obj)->is_survivor(), "must be");
532522
G1SkipCardEnqueueSetter x(&_scanner, dest_attr.is_young());
533523
obj->oop_iterate_backwards(&_scanner, klass);
534524
return obj;
@@ -615,14 +605,7 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markWord m, siz
615605
_preserved_marks->push_if_necessary(old, m);
616606
_evacuation_failed_info.register_copy_failure(word_sz);
617607

618-
// For iterating objects that failed evacuation currently we can reuse the
619-
// existing closure to scan evacuated objects because:
620-
// - for objects referring into the collection set we do not need to gather
621-
// cards at this time. The regions they are in will be unconditionally turned
622-
// to old regions without remembered sets.
623-
// - since we are iterating from a collection set region (i.e. never a Survivor
624-
// region), we always need to gather cards for this case.
625-
G1SkipCardEnqueueSetter x(&_scanner, false /* skip_card_enqueue */);
608+
G1SkipCardEnqueueSetter x(&_scanner, r->is_young());
626609
old->oop_iterate_backwards(&_scanner);
627610

628611
return old;

src/hotspot/share/gc/g1/g1ParScanThreadState.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
134134

135135
// Apply the post barrier to the given reference field. Enqueues the card of p
136136
// if the barrier does not filter out the reference for some reason (e.g.
137-
// p and q are in the same region, p is in survivor, p is in collection set)
137+
// p and q are in the same region, p is in survivor)
138138
// To be called during GC if nothing particular about p and obj are known.
139139
template <class T> void write_ref_field_post(T* p, oop obj);
140140

src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -97,34 +97,19 @@ G1OopStarChunkedList* G1ParScanThreadState::oops_into_optional_region(const Heap
9797
}
9898

9999
template <class T> void G1ParScanThreadState::write_ref_field_post(T* p, oop obj) {
100-
assert(obj != nullptr, "Must be");
100+
assert(obj != NULL, "Must be");
101101
if (HeapRegion::is_in_same_region(p, obj)) {
102102
return;
103103
}
104-
G1HeapRegionAttr from_attr = _g1h->region_attr(p);
105-
// If this is a reference from (current) survivor regions, we do not need
106-
// to track references from it.
107-
if (from_attr.is_new_survivor()) {
108-
return;
109-
}
110-
G1HeapRegionAttr dest_attr = _g1h->region_attr(obj);
111-
// References to the current collection set are references to objects that failed
112-
// evacuation. Currently these regions are always relabelled as old without
113-
// remembered sets, so skip them.
114-
assert(dest_attr.is_in_cset() == (obj->forwardee() == obj),
115-
"Only evac-failed objects must be in the collection set here but " PTR_FORMAT " is not", p2i(obj));
116-
if (dest_attr.is_in_cset()) {
117-
return;
104+
HeapRegion* from = _g1h->heap_region_containing(p);
105+
if (!from->is_young()) {
106+
enqueue_card_if_tracked(_g1h->region_attr(obj), p, obj);
118107
}
119-
enqueue_card_if_tracked(dest_attr, p, obj);
120108
}
121109

122110
template <class T> void G1ParScanThreadState::enqueue_card_if_tracked(G1HeapRegionAttr region_attr, T* p, oop o) {
123111
assert(!HeapRegion::is_in_same_region(p, o), "Should have filtered out cross-region references already.");
124-
assert(!_g1h->heap_region_containing(p)->is_survivor(), "Should have filtered out from-newly allocated survivor references already.");
125-
// We relabel all regions that failed evacuation as old gen without remembered,
126-
// and so pre-filter them out in the caller.
127-
assert(!_g1h->heap_region_containing(o)->in_collection_set(), "Should not try to enqueue reference into collection set region");
112+
assert(!_g1h->heap_region_containing(p)->is_young(), "Should have filtered out from-young references already.");
128113

129114
#ifdef ASSERT
130115
HeapRegion* const hr_obj = _g1h->heap_region_containing(o);

0 commit comments

Comments
 (0)