Skip to content

Commit 533a8a8

Browse files
author
William Kemper
committed
8376839: GenShen: Improve performance of evacuations into the old generation
Reviewed-by: kdnilsen
1 parent f2289d8 commit 533a8a8

18 files changed

Lines changed: 248 additions & 91 deletions

src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,24 @@ void ShenandoahConcurrentGC::entry_concurrent_update_refs_prepare(ShenandoahHeap
112112
heap->concurrent_prepare_for_update_refs();
113113
}
114114

115+
void ShenandoahConcurrentGC::entry_update_card_table() {
116+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
117+
TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
118+
119+
static const char* msg = "Concurrent update cards";
120+
ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_update_card_table);
121+
EventMark em("%s", msg);
122+
123+
ShenandoahWorkerScope scope(heap->workers(),
124+
ShenandoahWorkerPolicy::calc_workers_for_conc_evac(),
125+
"concurrent update cards");
126+
127+
// Heap needs to be parsable here.
128+
// Also, parallel heap region iterate must have a phase set.
129+
assert(ShenandoahTimingsTracker::is_current_phase_valid(), "Current phase must be set");
130+
ShenandoahGenerationalHeap::heap()->old_generation()->update_card_table();
131+
}
132+
115133
bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) {
116134
ShenandoahHeap* const heap = ShenandoahHeap::heap();
117135
_generation->ref_processor()->set_soft_reference_policy(
@@ -206,6 +224,11 @@ bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) {
206224

207225
// Perform update-refs phase.
208226
entry_concurrent_update_refs_prepare(heap);
227+
228+
if (ShenandoahHeap::heap()->mode()->is_generational()) {
229+
entry_update_card_table();
230+
}
231+
209232
if (ShenandoahVerify) {
210233
vmop_entry_init_update_refs();
211234
}

src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ class ShenandoahConcurrentGC : public ShenandoahGC {
5959
bool collect(GCCause::Cause cause) override;
6060
ShenandoahDegenPoint degen_point() const;
6161

62-
void entry_concurrent_update_refs_prepare(ShenandoahHeap* heap);
63-
6462
// Return true if this cycle found enough immediate garbage to skip evacuation
6563
bool abbreviated() const { return _abbreviated; }
6664

@@ -95,6 +93,8 @@ class ShenandoahConcurrentGC : public ShenandoahGC {
9593
void entry_cleanup_early();
9694
void entry_evacuate();
9795
void entry_update_thread_roots();
96+
void entry_update_card_table();
97+
void entry_concurrent_update_refs_prepare(ShenandoahHeap* heap);
9898
void entry_update_refs();
9999
void entry_cleanup_complete();
100100

src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,11 @@ void ShenandoahDegenGC::op_degenerated() {
277277
_abbreviated = true;
278278
}
279279

280+
// labs are retired, walk the old regions and update remembered set
281+
if (ShenandoahHeap::heap()->mode()->is_generational()) {
282+
ShenandoahGenerationalHeap::heap()->old_generation()->update_card_table();
283+
}
284+
280285
case _degenerated_update_refs:
281286
if (heap->has_forwarded_objects()) {
282287
op_update_refs();

src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,7 +1569,7 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah
15691569
// We must call try_recycle_under_lock() even if !r->is_trash(). The reason is that if r is being recycled at this
15701570
// moment by a GC worker thread, it may appear to be not trash even though it has not yet been fully recycled. If
15711571
// we proceed without waiting for the worker to finish recycling the region, the worker thread may overwrite the
1572-
// region's affiliation with FREE after we set the region's affiliation to req.afiliation() below
1572+
// region's affiliation with FREE after we set the region's affiliation to req.affiliation() below
15731573
r->try_recycle_under_lock();
15741574
in_new_region = r->is_empty();
15751575
if (in_new_region) {
@@ -1585,7 +1585,6 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah
15851585
// concurrent preparations for mixed evacuations are completed), we mark this region as not requiring any
15861586
// coalesce-and-fill processing.
15871587
r->end_preemptible_coalesce_and_fill();
1588-
_heap->old_generation()->clear_cards_for(r);
15891588
}
15901589
#ifdef ASSERT
15911590
ShenandoahMarkingContext* const ctx = _heap->marking_context();

src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@ void ShenandoahGenerationalEvacuationTask::evacuate_and_promote_regions() {
133133
}
134134
}
135135
}
136+

src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,10 +363,6 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, uint
363363
// Record that the evacuation succeeded
364364
evac_tracker()->end_evacuation(thread, size * HeapWordSize, FROM_GENERATION, TO_GENERATION);
365365
}
366-
367-
if (TO_GENERATION == OLD_GENERATION) {
368-
old_generation()->handle_evacuation(copy, size);
369-
}
370366
} else {
371367
// Failed to evacuate. We need to deal with the object that is left behind. Since this
372368
// new allocation is certainly after TAMS, it will be considered live in the next cycle.

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,6 +1955,26 @@ void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk) const
19551955
}
19561956
}
19571957

1958+
class ShenandoahHeapRegionIteratorTask : public WorkerTask {
1959+
private:
1960+
ShenandoahRegionIterator _regions;
1961+
ShenandoahHeapRegionClosure* _closure;
1962+
1963+
public:
1964+
ShenandoahHeapRegionIteratorTask(ShenandoahHeapRegionClosure* closure)
1965+
: WorkerTask("Shenandoah Heap Region Iterator")
1966+
, _closure(closure) {}
1967+
1968+
void work(uint worker_id) override {
1969+
ShenandoahParallelWorkerSession worker_session(worker_id);
1970+
ShenandoahHeapRegion* region = _regions.next();
1971+
while (region != nullptr) {
1972+
_closure->heap_region_do(region);
1973+
region = _regions.next();
1974+
}
1975+
}
1976+
};
1977+
19581978
class ShenandoahParallelHeapRegionTask : public WorkerTask {
19591979
private:
19601980
ShenandoahHeap* const _heap;
@@ -2011,6 +2031,11 @@ void ShenandoahHeap::parallel_heap_region_iterate(ShenandoahHeapRegionClosure* b
20112031
}
20122032
}
20132033

2034+
void ShenandoahHeap::heap_region_iterator(ShenandoahHeapRegionClosure* closure) const {
2035+
ShenandoahHeapRegionIteratorTask task(closure);
2036+
workers()->run_task(&task);
2037+
}
2038+
20142039
class ShenandoahRendezvousHandshakeClosure : public HandshakeClosure {
20152040
public:
20162041
inline ShenandoahRendezvousHandshakeClosure(const char* name) : HandshakeClosure(name) {}

src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ class ShenandoahHeap : public CollectedHeap {
298298

299299
void heap_region_iterate(ShenandoahHeapRegionClosure* blk) const;
300300
void parallel_heap_region_iterate(ShenandoahHeapRegionClosure* blk) const;
301+
void heap_region_iterator(ShenandoahHeapRegionClosure* blk) const;
301302

302303
inline ShenandoahMmuTracker* mmu_tracker() { return &_mmu_tracker; };
303304

src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ ShenandoahHeapRegion::ShenandoahHeapRegion(HeapWord* start, size_t index, bool c
6767
_new_top(nullptr),
6868
_empty_time(os::elapsedTime()),
6969
_top_before_promoted(nullptr),
70+
_top_at_evac_start(start),
7071
_state(committed ? _empty_committed : _empty_uncommitted),
7172
_top(start),
7273
_tlab_allocs(0),
@@ -565,12 +566,17 @@ void ShenandoahHeapRegion::recycle_internal() {
565566
assert(_recycling.is_set() && is_trash(), "Wrong state");
566567
ShenandoahHeap* heap = ShenandoahHeap::heap();
567568

569+
_top_at_evac_start = _bottom;
568570
_mixed_candidate_garbage_words = 0;
569571
set_top(bottom());
570572
clear_live_data();
571573
reset_alloc_metadata();
572574
heap->marking_context()->reset_top_at_mark_start(this);
573575
set_update_watermark(bottom());
576+
if (is_old()) {
577+
heap->old_generation()->clear_cards_for(this);
578+
}
579+
574580
if (ZapUnusedHeapArea) {
575581
SpaceMangler::mangle_region(MemRegion(bottom(), end()));
576582
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ class ShenandoahHeapRegion {
246246
double _empty_time;
247247

248248
HeapWord* _top_before_promoted;
249+
HeapWord* _top_at_evac_start;
249250

250251
// Seldom updated fields
251252
Atomic<RegionState> _state;
@@ -365,12 +366,15 @@ class ShenandoahHeapRegion {
365366
}
366367

367368
// Returns true iff this region was promoted in place subsequent to the most recent start of concurrent old marking.
368-
inline bool was_promoted_in_place() {
369+
bool was_promoted_in_place() const {
369370
return _promoted_in_place;
370371
}
371372
inline void restore_top_before_promote();
372373
inline size_t garbage_before_padded_for_promote() const;
373374

375+
HeapWord* get_top_at_evac_start() const { return _top_at_evac_start; }
376+
void record_top_at_evac_start() { _top_at_evac_start = _top; }
377+
374378
// If next available memory is not aligned on address that is multiple of alignment, fill the empty space
375379
// so that returned object is aligned on an address that is a multiple of alignment_in_bytes. Requested
376380
// size is in words. It is assumed that this->is_old(). A pad object is allocated, filled, and registered

0 commit comments

Comments
 (0)