Skip to content

Commit f1c69cc

Browse files
author
Thomas Schatzl
committed
8289822: G1: Make concurrent mark code owner of TAMSes
Reviewed-by: ayang, iwalulya
1 parent 5b6b514 commit f1c69cc

14 files changed

+133
-117
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,7 @@ G1CollectedHeap::G1CollectedHeap() :
11741174
_is_alive_closure_stw(this),
11751175
_is_subject_to_discovery_stw(this),
11761176
_ref_processor_cm(nullptr),
1177-
_is_alive_closure_cm(this),
1177+
_is_alive_closure_cm(),
11781178
_is_subject_to_discovery_cm(this),
11791179
_region_attr() {
11801180

@@ -1505,6 +1505,7 @@ void G1CollectedHeap::ref_processing_init() {
15051505
// * Discovery is atomic - i.e. not concurrent.
15061506
// * Reference discovery will not need a barrier.
15071507

1508+
_is_alive_closure_cm.initialize(concurrent_mark());
15081509
// Concurrent Mark ref processor
15091510
_ref_processor_cm =
15101511
new ReferenceProcessor(&_is_subject_to_discovery_cm,

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,10 @@ class G1PrintCollectionSetDetailClosure : public HeapRegionClosure {
253253

254254
virtual bool do_heap_region(HeapRegion* r) {
255255
assert(r->in_collection_set(), "Region %u should be in collection set", r->hrm_index());
256+
G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark();
256257
_st->print_cr(" " HR_FORMAT ", TAMS: " PTR_FORMAT " PB: " PTR_FORMAT ", age: %4d",
257258
HR_FORMAT_PARAMS(r),
258-
p2i(r->top_at_mark_start()),
259+
p2i(cm->top_at_mark_start(r)),
259260
p2i(r->parsable_bottom()),
260261
r->has_surv_rate_group() ? checked_cast<int>(r->age_in_surv_rate_group()) : -1);
261262
return false;

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

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@
7878
#include "utilities/growableArray.hpp"
7979
#include "utilities/powerOfTwo.hpp"
8080

81+
G1CMIsAliveClosure::G1CMIsAliveClosure() : _cm(nullptr) { }
82+
83+
G1CMIsAliveClosure::G1CMIsAliveClosure(G1ConcurrentMark* cm) : _cm(cm) {
84+
assert(cm != nullptr, "must be");
85+
}
86+
87+
void G1CMIsAliveClosure::initialize(G1ConcurrentMark* cm) {
88+
assert(cm != nullptr, "must be");
89+
assert(_cm == nullptr, "double initialize");
90+
_cm = cm;
91+
}
92+
8193
bool G1CMBitMapClosure::do_addr(HeapWord* const addr) {
8294
assert(addr < _cm->finger(), "invariant");
8395
assert(addr >= _task->finger(), "invariant");
@@ -502,6 +514,7 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h,
502514
_max_concurrent_workers(0),
503515

504516
_region_mark_stats(NEW_C_HEAP_ARRAY(G1RegionMarkStats, _g1h->max_reserved_regions(), mtGC)),
517+
_top_at_mark_starts(NEW_C_HEAP_ARRAY(HeapWord*, _g1h->max_reserved_regions(), mtGC)),
505518
_top_at_rebuild_starts(NEW_C_HEAP_ARRAY(HeapWord*, _g1h->max_reserved_regions(), mtGC)),
506519
_needs_remembered_set_rebuild(false)
507520
{
@@ -648,6 +661,7 @@ void G1ConcurrentMark::reset_at_marking_complete() {
648661
}
649662

650663
G1ConcurrentMark::~G1ConcurrentMark() {
664+
FREE_C_HEAP_ARRAY(HeapWord*, _top_at_mark_starts);
651665
FREE_C_HEAP_ARRAY(HeapWord*, _top_at_rebuild_starts);
652666
FREE_C_HEAP_ARRAY(G1RegionMarkStats, _region_mark_stats);
653667
// The G1ConcurrentMark instance is never freed.
@@ -693,7 +707,7 @@ class G1ClearBitMapTask : public WorkerTask {
693707
assert(_bitmap->get_next_marked_addr(r->bottom(), r->end()) == r->end(), "Should not have marked bits");
694708
return r->bottom();
695709
}
696-
assert(_bitmap->get_next_marked_addr(r->top_at_mark_start(), r->end()) == r->end(), "Should not have marked bits above tams");
710+
assert(_bitmap->get_next_marked_addr(_cm->top_at_mark_start(r), r->end()) == r->end(), "Should not have marked bits above tams");
697711
}
698712
return r->end();
699713
}
@@ -737,7 +751,7 @@ class G1ClearBitMapTask : public WorkerTask {
737751
}
738752
assert(cur >= end, "Must have completed iteration over the bitmap for region %u.", r->hrm_index());
739753

740-
r->reset_top_at_mark_start();
754+
_cm->reset_top_at_mark_start(r);
741755

742756
return false;
743757
}
@@ -849,9 +863,15 @@ void G1PreConcurrentStartTask::ResetMarkingStateTask::do_work(uint worker_id) {
849863
}
850864

851865
class NoteStartOfMarkHRClosure : public HeapRegionClosure {
866+
G1ConcurrentMark* _cm;
867+
852868
public:
869+
NoteStartOfMarkHRClosure() : HeapRegionClosure(), _cm(G1CollectedHeap::heap()->concurrent_mark()) { }
870+
853871
bool do_heap_region(HeapRegion* r) override {
854-
r->note_start_of_marking();
872+
if (r->is_old_or_humongous() && !r->is_collection_set_candidate()) {
873+
_cm->update_top_at_mark_start(r);
874+
}
855875
return false;
856876
}
857877
};
@@ -1015,9 +1035,9 @@ void G1ConcurrentMark::scan_root_region(const MemRegion* region, uint worker_id)
10151035
#ifdef ASSERT
10161036
HeapWord* last = region->last();
10171037
HeapRegion* hr = _g1h->heap_region_containing(last);
1018-
assert(hr->is_old() || hr->top_at_mark_start() == hr->bottom(),
1038+
assert(hr->is_old() || top_at_mark_start(hr) == hr->bottom(),
10191039
"Root regions must be old or survivor/eden but region %u is %s", hr->hrm_index(), hr->get_type_str());
1020-
assert(hr->top_at_mark_start() == region->start(),
1040+
assert(top_at_mark_start(hr) == region->start(),
10211041
"MemRegion start should be equal to TAMS");
10221042
#endif
10231043

@@ -1079,11 +1099,11 @@ bool G1ConcurrentMark::wait_until_root_region_scan_finished() {
10791099
}
10801100

10811101
void G1ConcurrentMark::add_root_region(HeapRegion* r) {
1082-
root_regions()->add(r->top_at_mark_start(), r->top());
1102+
root_regions()->add(top_at_mark_start(r), r->top());
10831103
}
10841104

10851105
bool G1ConcurrentMark::is_root_region(HeapRegion* r) {
1086-
return root_regions()->contains(MemRegion(r->top_at_mark_start(), r->top()));
1106+
return root_regions()->contains(MemRegion(top_at_mark_start(r), r->top()));
10871107
}
10881108

10891109
void G1ConcurrentMark::root_region_scan_abort_and_wait() {
@@ -1250,7 +1270,7 @@ class G1UpdateRegionLivenessAndSelectForRebuildTask : public WorkerTask {
12501270
if (hr->is_starts_humongous()) {
12511271
// The liveness of this humongous obj decided by either its allocation
12521272
// time (allocated after conc-mark-start, i.e. live) or conc-marking.
1253-
const bool is_live = hr->top_at_mark_start() == hr->bottom()
1273+
const bool is_live = _cm->top_at_mark_start(hr) == hr->bottom()
12541274
|| _cm->contains_live_object(hr->hrm_index());
12551275
if (is_live) {
12561276
const bool selected_for_rebuild = tracker->update_humongous_before_rebuild(hr);
@@ -1266,7 +1286,7 @@ class G1UpdateRegionLivenessAndSelectForRebuildTask : public WorkerTask {
12661286
reclaim_empty_humongous_region(hr);
12671287
}
12681288
} else if (hr->is_old()) {
1269-
hr->note_end_of_marking(_cm->live_bytes(hr->hrm_index()));
1289+
hr->note_end_of_marking(_cm->top_at_mark_start(hr), _cm->live_bytes(hr->hrm_index()));
12701290

12711291
if (hr->live_bytes() != 0) {
12721292
if (tracker->update_old_before_rebuild(hr)) {
@@ -1386,7 +1406,7 @@ void G1ConcurrentMark::remark() {
13861406

13871407
// Unload Klasses, String, Code Cache, etc.
13881408
if (ClassUnloadingWithConcurrentMark) {
1389-
G1CMIsAliveClosure is_alive(_g1h);
1409+
G1CMIsAliveClosure is_alive(this);
13901410
_g1h->unload_classes_and_code("Class Unloading", &is_alive, _gc_timer_cm);
13911411
}
13921412

@@ -1640,7 +1660,7 @@ class G1CMRefProcProxyTask : public RefProcProxyTask {
16401660

16411661
void work(uint worker_id) override {
16421662
assert(worker_id < _max_workers, "sanity");
1643-
G1CMIsAliveClosure is_alive(&_g1h);
1663+
G1CMIsAliveClosure is_alive(&_cm);
16441664
uint index = (_tm == RefProcThreadModel::Single) ? 0 : worker_id;
16451665
G1CMKeepAliveAndDrainClosure keep_alive(&_cm, _cm.task(index), _tm == RefProcThreadModel::Single);
16461666
BarrierEnqueueDiscoveredFieldClosure enqueue;
@@ -1719,7 +1739,7 @@ void G1ConcurrentMark::weak_refs_work() {
17191739

17201740
{
17211741
GCTraceTime(Debug, gc, phases) debug("Weak Processing", _gc_timer_cm);
1722-
G1CMIsAliveClosure is_alive(_g1h);
1742+
G1CMIsAliveClosure is_alive(this);
17231743
WeakProcessor::weak_oops_do(_g1h->workers(), &is_alive, &do_nothing_cl, 1);
17241744
}
17251745
}
@@ -1898,9 +1918,9 @@ HeapRegion* G1ConcurrentMark::claim_region(uint worker_id) {
18981918
if (res == finger && curr_region != nullptr) {
18991919
// we succeeded
19001920
HeapWord* bottom = curr_region->bottom();
1901-
HeapWord* limit = curr_region->top_at_mark_start();
1921+
HeapWord* limit = top_at_mark_start(curr_region);
19021922

1903-
log_trace(gc, marking)("Claim region %u bottom " PTR_FORMAT " tams " PTR_FORMAT, curr_region->hrm_index(), p2i(curr_region->bottom()), p2i(curr_region->top_at_mark_start()));
1923+
log_trace(gc, marking)("Claim region %u bottom " PTR_FORMAT " tams " PTR_FORMAT, curr_region->hrm_index(), p2i(curr_region->bottom()), p2i(top_at_mark_start(curr_region)));
19041924
// notice that _finger == end cannot be guaranteed here since,
19051925
// someone else might have moved the finger even further
19061926
assert(_finger >= end, "the finger should have moved forward");
@@ -2123,7 +2143,7 @@ void G1CMTask::setup_for_region(HeapRegion* hr) {
21232143
void G1CMTask::update_region_limit() {
21242144
HeapRegion* hr = _curr_region;
21252145
HeapWord* bottom = hr->bottom();
2126-
HeapWord* limit = hr->top_at_mark_start();
2146+
HeapWord* limit = _cm->top_at_mark_start(hr);
21272147

21282148
if (limit == bottom) {
21292149
// The region was collected underneath our feet.

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@
4141
#include "utilities/numberSeq.hpp"
4242

4343
class ConcurrentGCTimer;
44-
class G1ConcurrentMarkThread;
4544
class G1CollectedHeap;
45+
class G1ConcurrentMark;
46+
class G1ConcurrentMarkThread;
4647
class G1CMOopClosure;
4748
class G1CMTask;
48-
class G1ConcurrentMark;
4949
class G1OldTracer;
5050
class G1RegionToSpaceMapper;
5151
class G1SurvivorRegions;
@@ -96,9 +96,13 @@ typedef GenericTaskQueueSet<G1CMTaskQueue, mtGC> G1CMTaskQueueSet;
9696
// are alive. An instance is also embedded into the
9797
// reference processor as the _is_alive_non_header field
9898
class G1CMIsAliveClosure : public BoolObjectClosure {
99-
G1CollectedHeap* _g1h;
99+
G1ConcurrentMark* _cm;
100+
100101
public:
101-
G1CMIsAliveClosure(G1CollectedHeap* g1h) : _g1h(g1h) { }
102+
G1CMIsAliveClosure();
103+
G1CMIsAliveClosure(G1ConcurrentMark* cm);
104+
void initialize(G1ConcurrentMark* cm);
105+
102106
bool do_object_b(oop obj);
103107
};
104108

@@ -537,6 +541,9 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
537541

538542
// Region statistics gathered during marking.
539543
G1RegionMarkStats* _region_mark_stats;
544+
// Top pointer for each region at the start of marking. Must be valid for all committed
545+
// regions.
546+
HeapWord* volatile* _top_at_mark_starts;
540547
// Top pointer for each region at the start of the rebuild remembered set process
541548
// for regions which remembered sets need to be rebuilt. A null for a given region
542549
// means that this region does not be scanned during the rebuilding remembered
@@ -556,6 +563,16 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
556563
// Set live bytes for concurrent marking.
557564
void set_live_bytes(uint region, size_t live_bytes) { _region_mark_stats[region]._live_words = live_bytes / HeapWordSize; }
558565

566+
// Update the TAMS for the given region to the current top.
567+
inline void update_top_at_mark_start(HeapRegion* r);
568+
// Reset the TAMS for the given region to bottom of that region.
569+
inline void reset_top_at_mark_start(HeapRegion* r);
570+
571+
inline HeapWord* top_at_mark_start(const HeapRegion* r) const;
572+
inline HeapWord* top_at_mark_start(uint region) const;
573+
// Returns whether the given object been allocated since marking start (i.e. >= TAMS in that region).
574+
inline bool obj_allocated_since_mark_start(oop obj) const;
575+
559576
// Sets the internal top_at_region_start for the given region to current top of the region.
560577
inline void update_top_at_rebuild_start(HeapRegion* r);
561578
// TARS for the given region during remembered set rebuilding.

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

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,13 @@ inline bool G1CMIsAliveClosure::do_object_b(oop obj) {
4848
return true;
4949
}
5050

51-
HeapRegion* hr = _g1h->heap_region_containing(obj);
5251
// All objects allocated since the start of marking are considered live.
53-
if (hr->obj_allocated_since_marking_start(obj)) {
52+
if (_cm->obj_allocated_since_mark_start(obj)) {
5453
return true;
5554
}
5655

5756
// All objects that are marked are live.
58-
return _g1h->is_marked(obj);
57+
return _cm->is_marked_in_bitmap(obj);
5958
}
6059

6160
inline bool G1CMSubjectToDiscoveryClosure::do_object_b(oop obj) {
@@ -66,15 +65,16 @@ inline bool G1CMSubjectToDiscoveryClosure::do_object_b(oop obj) {
6665
}
6766

6867
inline bool G1ConcurrentMark::mark_in_bitmap(uint const worker_id, oop const obj) {
69-
HeapRegion* const hr = _g1h->heap_region_containing(obj);
70-
71-
if (hr->obj_allocated_since_marking_start(obj)) {
68+
if (obj_allocated_since_mark_start(obj)) {
7269
return false;
7370
}
7471

7572
// Some callers may have stale objects to mark above TAMS after humongous reclaim.
7673
// Can't assert that this is a valid object at this point, since it might be in the process of being copied by another thread.
77-
assert(!hr->is_continues_humongous(), "Should not try to mark object " PTR_FORMAT " in Humongous continues region %u above TAMS " PTR_FORMAT, p2i(obj), hr->hrm_index(), p2i(hr->top_at_mark_start()));
74+
DEBUG_ONLY(HeapRegion* const hr = _g1h->heap_region_containing(obj);)
75+
assert(!hr->is_continues_humongous(),
76+
"Should not try to mark object " PTR_FORMAT " in Humongous continues region %u above TAMS " PTR_FORMAT,
77+
p2i(obj), hr->hrm_index(), p2i(top_at_mark_start(hr)));
7878

7979
bool success = _mark_bitmap.par_mark(obj);
8080
if (success) {
@@ -184,6 +184,31 @@ inline size_t G1CMTask::scan_objArray(objArrayOop obj, MemRegion mr) {
184184
return mr.word_size();
185185
}
186186

187+
inline void G1ConcurrentMark::update_top_at_mark_start(HeapRegion* r) {
188+
uint const region = r->hrm_index();
189+
assert(region < _g1h->max_reserved_regions(), "Tried to access TAMS for region %u out of bounds", region);
190+
_top_at_mark_starts[region] = r->top();
191+
}
192+
193+
inline void G1ConcurrentMark::reset_top_at_mark_start(HeapRegion* r) {
194+
_top_at_mark_starts[r->hrm_index()] = r->bottom();
195+
}
196+
197+
inline HeapWord* G1ConcurrentMark::top_at_mark_start(const HeapRegion* r) const {
198+
return top_at_mark_start(r->hrm_index());
199+
}
200+
201+
inline HeapWord* G1ConcurrentMark::top_at_mark_start(uint region) const {
202+
assert(region < _g1h->max_reserved_regions(), "Tried to access TARS for region %u out of bounds", region);
203+
return _top_at_mark_starts[region];
204+
}
205+
206+
inline bool G1ConcurrentMark::obj_allocated_since_mark_start(oop obj) const {
207+
uint const region = _g1h->addr_to_region(obj);
208+
assert(region < _g1h->max_reserved_regions(), "obj " PTR_FORMAT " outside heap %u", p2i(obj), region);
209+
return cast_from_oop<HeapWord*>(obj) >= top_at_mark_start(region);
210+
}
211+
187212
inline HeapWord* G1ConcurrentMark::top_at_rebuild_start(HeapRegion* r) const {
188213
return _top_at_rebuild_starts[r->hrm_index()];
189214
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
229229
assert(should_rebuild_or_scrub(hr), "must be");
230230

231231
log_trace(gc, marking)("Scrub and rebuild region: " HR_FORMAT " pb: " PTR_FORMAT " TARS: " PTR_FORMAT " TAMS: " PTR_FORMAT,
232-
HR_FORMAT_PARAMS(hr), p2i(pb), p2i(_cm->top_at_rebuild_start(hr)), p2i(hr->top_at_mark_start()));
232+
HR_FORMAT_PARAMS(hr), p2i(pb), p2i(_cm->top_at_rebuild_start(hr)), p2i(_cm->top_at_mark_start(hr)));
233233

234234
if (scan_and_scrub_to_pb(hr, hr->bottom(), pb)) {
235235
log_trace(gc, marking)("Scan and scrub aborted for region: %u", hr->hrm_index());

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,11 @@ void HeapRegion::hr_clear(bool clear_space) {
124124

125125
rem_set()->clear();
126126

127-
init_top_at_mark_start();
127+
G1CollectedHeap::heap()->concurrent_mark()->reset_top_at_mark_start(this);
128+
129+
_parsable_bottom = bottom();
130+
_garbage_bytes = 0;
131+
128132
if (clear_space) clear(SpaceDecorator::Mangle);
129133
}
130134

@@ -226,7 +230,6 @@ HeapRegion::HeapRegion(uint hrm_index,
226230
#ifdef ASSERT
227231
_containing_set(nullptr),
228232
#endif
229-
_top_at_mark_start(nullptr),
230233
_parsable_bottom(nullptr),
231234
_garbage_bytes(0),
232235
_young_index_in_cset(-1),
@@ -414,8 +417,9 @@ void HeapRegion::print_on(outputStream* st) const {
414417
} else {
415418
st->print("| ");
416419
}
420+
G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark();
417421
st->print("|TAMS " PTR_FORMAT "| PB " PTR_FORMAT "| %s ",
418-
p2i(top_at_mark_start()), p2i(parsable_bottom_acquire()), rem_set()->get_state_str());
422+
p2i(cm->top_at_mark_start(this)), p2i(parsable_bottom_acquire()), rem_set()->get_state_str());
419423
if (UseNUMA) {
420424
G1NUMA* numa = G1NUMA::numa();
421425
if (node_index() < numa->num_active_nodes()) {

0 commit comments

Comments
 (0)