Skip to content

Commit 68a3551

Browse files
committed
8364212: Shenandoah: Rework archived objects loading
Reviewed-by: wkemper, kdnilsen
1 parent d906e45 commit 68a3551

File tree

6 files changed

+76
-73
lines changed

6 files changed

+76
-73
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class ShenandoahAllocRequest : StackObj {
3434
enum Type {
3535
_alloc_shared, // Allocate common, outside of TLAB
3636
_alloc_shared_gc, // Allocate common, outside of GCLAB/PLAB
37+
_alloc_cds, // Allocate for CDS
3738
_alloc_tlab, // Allocate TLAB
3839
_alloc_gclab, // Allocate GCLAB
3940
_alloc_plab, // Allocate PLAB
@@ -46,6 +47,8 @@ class ShenandoahAllocRequest : StackObj {
4647
return "Shared";
4748
case _alloc_shared_gc:
4849
return "Shared GC";
50+
case _alloc_cds:
51+
return "CDS";
4952
case _alloc_tlab:
5053
return "TLAB";
5154
case _alloc_gclab:
@@ -121,6 +124,10 @@ class ShenandoahAllocRequest : StackObj {
121124
return ShenandoahAllocRequest(0, requested_size, _alloc_shared, ShenandoahAffiliation::YOUNG_GENERATION);
122125
}
123126

127+
static inline ShenandoahAllocRequest for_cds(size_t requested_size) {
128+
return ShenandoahAllocRequest(0, requested_size, _alloc_cds, ShenandoahAffiliation::YOUNG_GENERATION);
129+
}
130+
124131
inline size_t size() const {
125132
return _requested_size;
126133
}
@@ -163,6 +170,7 @@ class ShenandoahAllocRequest : StackObj {
163170
switch (_alloc_type) {
164171
case _alloc_tlab:
165172
case _alloc_shared:
173+
case _alloc_cds:
166174
return true;
167175
case _alloc_gclab:
168176
case _alloc_plab:
@@ -178,6 +186,7 @@ class ShenandoahAllocRequest : StackObj {
178186
switch (_alloc_type) {
179187
case _alloc_tlab:
180188
case _alloc_shared:
189+
case _alloc_cds:
181190
return false;
182191
case _alloc_gclab:
183192
case _alloc_plab:
@@ -197,6 +206,7 @@ class ShenandoahAllocRequest : StackObj {
197206
return true;
198207
case _alloc_shared:
199208
case _alloc_shared_gc:
209+
case _alloc_cds:
200210
return false;
201211
default:
202212
ShouldNotReachHere();

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

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ HeapWord* ShenandoahFreeSet::allocate_single(ShenandoahAllocRequest& req, bool&
816816
switch (req.type()) {
817817
case ShenandoahAllocRequest::_alloc_tlab:
818818
case ShenandoahAllocRequest::_alloc_shared:
819+
case ShenandoahAllocRequest::_alloc_cds:
819820
return allocate_for_mutator(req, in_new_region);
820821
case ShenandoahAllocRequest::_alloc_gclab:
821822
case ShenandoahAllocRequest::_alloc_plab:
@@ -1169,8 +1170,8 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah
11691170
return result;
11701171
}
11711172

1172-
HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) {
1173-
assert(req.is_mutator_alloc(), "All humongous allocations are performed by mutator");
1173+
HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req, bool is_humongous) {
1174+
assert(req.is_mutator_alloc(), "All contiguous allocations are performed by mutator");
11741175
shenandoah_assert_heaplocked();
11751176

11761177
size_t words_size = req.size();
@@ -1244,10 +1245,16 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) {
12441245
assert(i == beg || _heap->get_region(i - 1)->index() + 1 == r->index(), "Should be contiguous");
12451246
assert(r->is_empty(), "Should be empty");
12461247

1247-
if (i == beg) {
1248-
r->make_humongous_start();
1248+
r->set_affiliation(req.affiliation());
1249+
1250+
if (is_humongous) {
1251+
if (i == beg) {
1252+
r->make_humongous_start();
1253+
} else {
1254+
r->make_humongous_cont();
1255+
}
12491256
} else {
1250-
r->make_humongous_cont();
1257+
r->make_regular_allocation(req.affiliation());
12511258
}
12521259

12531260
// Trailing region may be non-full, record the remainder there
@@ -1257,21 +1264,31 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) {
12571264
} else {
12581265
used_words = ShenandoahHeapRegion::region_size_words();
12591266
}
1260-
1261-
r->set_affiliation(req.affiliation());
12621267
r->set_update_watermark(r->bottom());
12631268
r->set_top(r->bottom() + used_words);
12641269
}
12651270
generation->increase_affiliated_region_count(num);
12661271

1267-
// retire_range_from_partition() will adjust bounds on Mutator free set if appropriate
1268-
_partitions.retire_range_from_partition(ShenandoahFreeSetPartitionId::Mutator, beg, end);
1269-
1270-
size_t total_humongous_size = ShenandoahHeapRegion::region_size_bytes() * num;
1271-
_partitions.increase_used(ShenandoahFreeSetPartitionId::Mutator, total_humongous_size);
1272+
size_t total_used = 0;
1273+
if (is_humongous) {
1274+
// Humongous allocation retires all regions at once: no allocation is possible anymore.
1275+
_partitions.retire_range_from_partition(ShenandoahFreeSetPartitionId::Mutator, beg, end);
1276+
total_used = ShenandoahHeapRegion::region_size_bytes() * num;
1277+
} else {
1278+
// Non-humongous allocation retires only the regions that cannot be used for allocation anymore.
1279+
for (idx_t i = beg; i <= end; i++) {
1280+
ShenandoahHeapRegion* r = _heap->get_region(i);
1281+
if (r->free() < PLAB::min_size() * HeapWordSize) {
1282+
_partitions.retire_from_partition(ShenandoahFreeSetPartitionId::Mutator, i, r->used());
1283+
}
1284+
total_used += r->used();
1285+
}
1286+
}
1287+
_partitions.increase_used(ShenandoahFreeSetPartitionId::Mutator, total_used);
12721288
_partitions.assert_bounds();
1289+
12731290
req.set_actual_size(words_size);
1274-
if (remainder != 0) {
1291+
if (remainder != 0 && is_humongous) {
12751292
req.set_waste(ShenandoahHeapRegion::region_size_words() - remainder);
12761293
}
12771294
return _heap->get_region(beg)->bottom();
@@ -2060,7 +2077,10 @@ HeapWord* ShenandoahFreeSet::allocate(ShenandoahAllocRequest& req, bool& in_new_
20602077
case ShenandoahAllocRequest::_alloc_shared:
20612078
case ShenandoahAllocRequest::_alloc_shared_gc:
20622079
in_new_region = true;
2063-
return allocate_contiguous(req);
2080+
return allocate_contiguous(req, /* is_humongous = */ true);
2081+
case ShenandoahAllocRequest::_alloc_cds:
2082+
in_new_region = true;
2083+
return allocate_contiguous(req, /* is_humongous = */ false);
20642084
case ShenandoahAllocRequest::_alloc_plab:
20652085
case ShenandoahAllocRequest::_alloc_gclab:
20662086
case ShenandoahAllocRequest::_alloc_tlab:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ class ShenandoahFreeSet : public CHeapObj<mtGC> {
345345
// object. No other objects are packed into these regions.
346346
//
347347
// Precondition: ShenandoahHeapRegion::requires_humongous(req.size())
348-
HeapWord* allocate_contiguous(ShenandoahAllocRequest& req);
348+
HeapWord* allocate_contiguous(ShenandoahAllocRequest& req, bool is_humongous);
349349

350350
// Change region r from the Mutator partition to the GC's Collector or OldCollector partition. This requires that the
351351
// region is entirely empty.

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

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,41 +2773,15 @@ bool ShenandoahHeap::requires_barriers(stackChunkOop obj) const {
27732773

27742774
HeapWord* ShenandoahHeap::allocate_loaded_archive_space(size_t size) {
27752775
#if INCLUDE_CDS_JAVA_HEAP
2776-
// CDS wants a continuous memory range to load a bunch of objects.
2777-
// This effectively bypasses normal allocation paths, and requires
2778-
// a bit of massaging to unbreak GC invariants.
2779-
2780-
ShenandoahAllocRequest req = ShenandoahAllocRequest::for_shared(size);
2781-
2782-
// Easy case: a single regular region, no further adjustments needed.
2783-
if (!ShenandoahHeapRegion::requires_humongous(size)) {
2784-
return allocate_memory(req);
2785-
}
2786-
2787-
// Hard case: the requested size would cause a humongous allocation.
2788-
// We need to make sure it looks like regular allocation to the rest of GC.
2789-
2790-
// CDS code would guarantee no objects straddle multiple regions, as long as
2791-
// regions are as large as MIN_GC_REGION_ALIGNMENT. It is impractical at this
2792-
// point to deal with case when Shenandoah runs with smaller regions.
2793-
// TODO: This check can be dropped once MIN_GC_REGION_ALIGNMENT agrees more with Shenandoah.
2794-
if (ShenandoahHeapRegion::region_size_bytes() < ArchiveHeapWriter::MIN_GC_REGION_ALIGNMENT) {
2795-
return nullptr;
2796-
}
2797-
2798-
HeapWord* mem = allocate_memory(req);
2799-
size_t start_idx = heap_region_index_containing(mem);
2800-
size_t num_regions = ShenandoahHeapRegion::required_regions(size * HeapWordSize);
2801-
2802-
// Flip humongous -> regular.
2803-
{
2804-
ShenandoahHeapLocker locker(lock(), false);
2805-
for (size_t c = start_idx; c < start_idx + num_regions; c++) {
2806-
get_region(c)->make_regular_bypass();
2807-
}
2808-
}
2776+
// CDS wants a raw continuous memory range to load a bunch of objects itself.
2777+
// This is an unusual request, since all requested regions should be regular, not humongous.
2778+
//
2779+
// CDS would guarantee no objects straddle multiple regions, as long as regions are as large
2780+
// as MIN_GC_REGION_ALIGNMENT.
2781+
guarantee(ShenandoahHeapRegion::region_size_bytes() >= ArchiveHeapWriter::MIN_GC_REGION_ALIGNMENT, "Must be");
28092782

2810-
return mem;
2783+
ShenandoahAllocRequest req = ShenandoahAllocRequest::for_cds(size);
2784+
return allocate_memory(req);
28112785
#else
28122786
assert(false, "Archive heap loader should not be available, should not be here");
28132787
return nullptr;
@@ -2834,17 +2808,25 @@ void ShenandoahHeap::complete_loaded_archive_space(MemRegion archive_space) {
28342808
"Archive space should be fully used: " PTR_FORMAT " " PTR_FORMAT,
28352809
p2i(cur), p2i(end));
28362810

2837-
// Region bounds are good.
2838-
ShenandoahHeapRegion* begin_reg = heap_region_containing(start);
2839-
ShenandoahHeapRegion* end_reg = heap_region_containing(end);
2840-
assert(begin_reg->is_regular(), "Must be");
2841-
assert(end_reg->is_regular(), "Must be");
2842-
assert(begin_reg->bottom() == start,
2843-
"Must agree: archive-space-start: " PTR_FORMAT ", begin-region-bottom: " PTR_FORMAT,
2844-
p2i(start), p2i(begin_reg->bottom()));
2845-
assert(end_reg->top() == end,
2846-
"Must agree: archive-space-end: " PTR_FORMAT ", end-region-top: " PTR_FORMAT,
2847-
p2i(end), p2i(end_reg->top()));
2811+
// All regions in contiguous space have good state.
2812+
size_t begin_reg_idx = heap_region_index_containing(start);
2813+
size_t end_reg_idx = heap_region_index_containing(end);
2814+
2815+
for (size_t idx = begin_reg_idx; idx <= end_reg_idx; idx++) {
2816+
ShenandoahHeapRegion* r = get_region(idx);
2817+
assert(r->is_regular(), "Must be regular");
2818+
assert(r->is_young(), "Must be young");
2819+
assert(idx == end_reg_idx || r->top() == r->end(),
2820+
"All regions except the last one should be full: " PTR_FORMAT " " PTR_FORMAT,
2821+
p2i(r->top()), p2i(r->end()));
2822+
assert(idx != begin_reg_idx || r->bottom() == start,
2823+
"Archive space start should be at the bottom of first region: " PTR_FORMAT " " PTR_FORMAT,
2824+
p2i(r->bottom()), p2i(start));
2825+
assert(idx != end_reg_idx || r->top() == end,
2826+
"Archive space end should be at the top of last region: " PTR_FORMAT " " PTR_FORMAT,
2827+
p2i(r->top()), p2i(end));
2828+
}
2829+
28482830
#endif
28492831
}
28502832

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

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -142,27 +142,17 @@ void ShenandoahHeapRegion::make_affiliated_maybe() {
142142

143143
void ShenandoahHeapRegion::make_regular_bypass() {
144144
shenandoah_assert_heaplocked();
145-
assert (!Universe::is_fully_initialized() ||
146-
ShenandoahHeap::heap()->is_full_gc_in_progress() ||
145+
assert (ShenandoahHeap::heap()->is_full_gc_in_progress() ||
147146
ShenandoahHeap::heap()->is_degenerated_gc_in_progress(),
148-
"Only for STW GC or when Universe is initializing (CDS)");
147+
"Only for STW GC");
149148
reset_age();
150-
auto cur_state = state();
151-
switch (cur_state) {
149+
switch (state()) {
152150
case _empty_uncommitted:
153151
do_commit();
154152
case _empty_committed:
155153
case _cset:
156154
case _humongous_start:
157155
case _humongous_cont:
158-
if (cur_state == _humongous_start || cur_state == _humongous_cont) {
159-
// CDS allocates chunks of the heap to fill with regular objects. The allocator
160-
// will dutifully track any waste in the unused portion of the last region. Once
161-
// CDS has finished initializing the objects, it will convert these regions to
162-
// regular regions. The 'waste' in the last region is no longer wasted at this point,
163-
// so we must stop treating it as such.
164-
decrement_humongous_waste();
165-
}
166156
set_state(_regular);
167157
return;
168158
case _pinned_cset:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ inline void ShenandoahHeapRegion::adjust_alloc_metadata(ShenandoahAllocRequest::
112112
switch (type) {
113113
case ShenandoahAllocRequest::_alloc_shared:
114114
case ShenandoahAllocRequest::_alloc_shared_gc:
115+
case ShenandoahAllocRequest::_alloc_cds:
115116
// Counted implicitly by tlab/gclab allocs
116117
break;
117118
case ShenandoahAllocRequest::_alloc_tlab:

0 commit comments

Comments
 (0)