Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.
/ lanai Public archive

Commit fe2a820

Browse files
committedApr 3, 2020
8242101: Shenandoah: coalesce and parallelise heap region walks during the pauses
Reviewed-by: rkennke
1 parent 746d28d commit fe2a820

File tree

3 files changed

+76
-40
lines changed

3 files changed

+76
-40
lines changed
 

‎src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp

+70-30
Original file line numberDiff line numberDiff line change
@@ -1351,11 +1351,11 @@ void ShenandoahHeap::parallel_heap_region_iterate(ShenandoahHeapRegionClosure* b
13511351
}
13521352
}
13531353

1354-
class ShenandoahClearLivenessClosure : public ShenandoahHeapRegionClosure {
1354+
class ShenandoahInitMarkUpdateRegionStateClosure : public ShenandoahHeapRegionClosure {
13551355
private:
13561356
ShenandoahMarkingContext* const _ctx;
13571357
public:
1358-
ShenandoahClearLivenessClosure() : _ctx(ShenandoahHeap::heap()->marking_context()) {}
1358+
ShenandoahInitMarkUpdateRegionStateClosure() : _ctx(ShenandoahHeap::heap()->marking_context()) {}
13591359

13601360
void heap_region_do(ShenandoahHeapRegion* r) {
13611361
if (r->is_active()) {
@@ -1395,9 +1395,9 @@ void ShenandoahHeap::op_init_mark() {
13951395
}
13961396

13971397
{
1398-
ShenandoahGCPhase phase(ShenandoahPhaseTimings::clear_liveness);
1399-
ShenandoahClearLivenessClosure clc;
1400-
parallel_heap_region_iterate(&clc);
1398+
ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_region_states);
1399+
ShenandoahInitMarkUpdateRegionStateClosure cl;
1400+
parallel_heap_region_iterate(&cl);
14011401
}
14021402

14031403
// Make above changes visible to worker threads
@@ -1426,19 +1426,43 @@ void ShenandoahHeap::op_mark() {
14261426
concurrent_mark()->mark_from_roots();
14271427
}
14281428

1429-
class ShenandoahCompleteLivenessClosure : public ShenandoahHeapRegionClosure {
1429+
class ShenandoahFinalMarkUpdateRegionStateClosure : public ShenandoahHeapRegionClosure {
14301430
private:
14311431
ShenandoahMarkingContext* const _ctx;
1432+
ShenandoahHeapLock* const _lock;
1433+
14321434
public:
1433-
ShenandoahCompleteLivenessClosure() : _ctx(ShenandoahHeap::heap()->complete_marking_context()) {}
1435+
ShenandoahFinalMarkUpdateRegionStateClosure() :
1436+
_ctx(ShenandoahHeap::heap()->complete_marking_context()), _lock(ShenandoahHeap::heap()->lock()) {}
14341437

14351438
void heap_region_do(ShenandoahHeapRegion* r) {
14361439
if (r->is_active()) {
1440+
// All allocations past TAMS are implicitly live, adjust the region data.
1441+
// Bitmaps/TAMS are swapped at this point, so we need to poll complete bitmap.
14371442
HeapWord *tams = _ctx->top_at_mark_start(r);
14381443
HeapWord *top = r->top();
14391444
if (top > tams) {
14401445
r->increase_live_data_alloc_words(pointer_delta(top, tams));
14411446
}
1447+
1448+
// We are about to select the collection set, make sure it knows about
1449+
// current pinning status. Also, this allows trashing more regions that
1450+
// now have their pinning status dropped.
1451+
if (r->is_pinned()) {
1452+
if (r->pin_count() == 0) {
1453+
ShenandoahHeapLocker locker(_lock);
1454+
r->make_unpinned();
1455+
}
1456+
} else {
1457+
if (r->pin_count() > 0) {
1458+
ShenandoahHeapLocker locker(_lock);
1459+
r->make_pinned();
1460+
}
1461+
}
1462+
1463+
// Remember limit for updating refs. It's guaranteed that we get no
1464+
// from-space-refs written from here on.
1465+
r->set_update_watermark(r->top());
14421466
} else {
14431467
assert(!r->has_live(), "Region " SIZE_FORMAT " should have no live data", r->index());
14441468
assert(_ctx->top_at_mark_start(r) == r->top(),
@@ -1469,12 +1493,13 @@ void ShenandoahHeap::op_final_mark() {
14691493
if (ShenandoahVerify) {
14701494
verifier()->verify_roots_no_forwarded();
14711495
}
1472-
// All allocations past TAMS are implicitly live, adjust the region data.
1473-
// Bitmaps/TAMS are swapped at this point, so we need to poll complete bitmap.
1496+
14741497
{
1475-
ShenandoahGCPhase phase(ShenandoahPhaseTimings::complete_liveness);
1476-
ShenandoahCompleteLivenessClosure cl;
1498+
ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_region_states);
1499+
ShenandoahFinalMarkUpdateRegionStateClosure cl;
14771500
parallel_heap_region_iterate(&cl);
1501+
1502+
assert_pinned_region_status();
14781503
}
14791504

14801505
// Force the threads to reacquire their TLABs outside the collection set.
@@ -1483,14 +1508,6 @@ void ShenandoahHeap::op_final_mark() {
14831508
make_parsable(true);
14841509
}
14851510

1486-
// We are about to select the collection set, make sure it knows about
1487-
// current pinning status. Also, this allows trashing more regions that
1488-
// now have their pinning status dropped.
1489-
{
1490-
ShenandoahGCPhase phase(ShenandoahPhaseTimings::sync_pinned);
1491-
sync_pinned_region_status();
1492-
}
1493-
14941511
{
14951512
ShenandoahGCPhase phase(ShenandoahPhaseTimings::choose_cset);
14961513
ShenandoahHeapLocker locker(lock());
@@ -1518,13 +1535,6 @@ void ShenandoahHeap::op_final_mark() {
15181535
verifier()->verify_before_evacuation();
15191536
}
15201537

1521-
// Remember limit for updating refs. It's guaranteed that we get no from-space-refs written
1522-
// from here on.
1523-
for (uint i = 0; i < num_regions(); i++) {
1524-
ShenandoahHeapRegion* r = get_region(i);
1525-
r->set_update_watermark(r->top());
1526-
}
1527-
15281538
set_evacuation_in_progress(true);
15291539
// From here on, we need to update references.
15301540
set_has_forwarded_objects(true);
@@ -2397,6 +2407,35 @@ void ShenandoahHeap::op_init_updaterefs() {
23972407
}
23982408
}
23992409

2410+
class ShenandoahFinalUpdateRefsUpdateRegionStateClosure : public ShenandoahHeapRegionClosure {
2411+
private:
2412+
ShenandoahHeapLock* const _lock;
2413+
2414+
public:
2415+
ShenandoahFinalUpdateRefsUpdateRegionStateClosure() : _lock(ShenandoahHeap::heap()->lock()) {}
2416+
2417+
void heap_region_do(ShenandoahHeapRegion* r) {
2418+
// Drop unnecessary "pinned" state from regions that does not have CP marks
2419+
// anymore, as this would allow trashing them.
2420+
2421+
if (r->is_active()) {
2422+
if (r->is_pinned()) {
2423+
if (r->pin_count() == 0) {
2424+
ShenandoahHeapLocker locker(_lock);
2425+
r->make_unpinned();
2426+
}
2427+
} else {
2428+
if (r->pin_count() > 0) {
2429+
ShenandoahHeapLocker locker(_lock);
2430+
r->make_pinned();
2431+
}
2432+
}
2433+
}
2434+
}
2435+
2436+
bool is_thread_safe() { return true; }
2437+
};
2438+
24002439
void ShenandoahHeap::op_final_updaterefs() {
24012440
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at safepoint");
24022441

@@ -2433,11 +2472,12 @@ void ShenandoahHeap::op_final_updaterefs() {
24332472
verifier()->verify_roots_in_to_space();
24342473
}
24352474

2436-
// Drop unnecessary "pinned" state from regions that does not have CP marks
2437-
// anymore, as this would allow trashing them below.
24382475
{
2439-
ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_sync_pinned);
2440-
sync_pinned_region_status();
2476+
ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_update_region_states);
2477+
ShenandoahFinalUpdateRefsUpdateRegionStateClosure cl;
2478+
parallel_heap_region_iterate(&cl);
2479+
2480+
assert_pinned_region_status();
24412481
}
24422482

24432483
{

‎src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp

+3-6
Original file line numberDiff line numberDiff line change
@@ -384,18 +384,15 @@ class ShenandoahHeapRegion {
384384
size_t get_gclab_allocs() const;
385385

386386
HeapWord* get_update_watermark() const {
387-
// Updates to the update-watermark only happen at safepoints or, when pushing
388-
// back the watermark for evacuation regions, under the Shenandoah heap-lock.
389-
// Consequently, we should access the field under the same lock. However, since
390-
// those updates are only monotonically increasing, possibly reading a stale value
391-
// is only conservative - we would not miss to update any fields.
387+
// Updates to the update-watermark only happen at safepoints.
388+
// Since those updates are only monotonically increasing, possibly reading
389+
// a stale value is only conservative - we would not miss to update any fields.
392390
HeapWord* watermark = _update_watermark;
393391
assert(bottom() <= watermark && watermark <= top(), "within bounds");
394392
return watermark;
395393
}
396394

397395
void set_update_watermark(HeapWord* w) {
398-
shenandoah_assert_heaplocked_or_safepoint();
399396
assert(bottom() <= w && w <= top(), "within bounds");
400397
_update_watermark = w;
401398
}

‎src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class outputStream;
6363
f(init_mark_gross, "Pause Init Mark (G)") \
6464
f(init_mark, "Pause Init Mark (N)") \
6565
f(make_parsable, " Make Parsable") \
66-
f(clear_liveness, " Clear Liveness") \
66+
f(init_update_region_states, " Update Region States") \
6767
f(scan_roots, " Scan Roots") \
6868
SHENANDOAH_GC_PAR_PHASE_DO(scan_, " S: ", f) \
6969
f(resize_tlabs, " Resize TLABs") \
@@ -80,9 +80,8 @@ class outputStream;
8080
f(purge_par, " Parallel Cleanup") \
8181
SHENANDOAH_GC_PAR_PHASE_DO(purge_par_roots, " PC: ", f) \
8282
f(purge_cldg, " CLDG") \
83-
f(complete_liveness, " Complete Liveness") \
83+
f(final_update_region_states, " Update Region States") \
8484
f(retire_tlabs, " Retire TLABs") \
85-
f(sync_pinned, " Sync Pinned") \
8685
f(choose_cset, " Choose Collection Set") \
8786
f(final_rebuild_freeset, " Rebuild Free Set") \
8887
f(init_evac, " Initial Evacuation") \
@@ -98,7 +97,7 @@ class outputStream;
9897
f(final_update_refs_finish_work, " Finish Work") \
9998
f(final_update_refs_roots, " Update Roots") \
10099
SHENANDOAH_GC_PAR_PHASE_DO(final_update_, " UR: ", f) \
101-
f(final_update_refs_sync_pinned, " Sync Pinned") \
100+
f(final_update_refs_update_region_states, " Update Region States") \
102101
f(final_update_refs_trash_cset, " Trash Collection Set") \
103102
f(final_update_refs_rebuild_freeset, " Rebuild Free Set") \
104103
\

0 commit comments

Comments
 (0)
This repository has been archived.