Skip to content

Commit 5672a93

Browse files
author
William Kemper
committed
8348400: GenShen: assert(ShenandoahHeap::heap()->is_full_gc_in_progress() || (used_regions_size() <= _max_capacity)) failed: Cannot use more than capacity #
Reviewed-by: ysr
1 parent c2a4fed commit 5672a93

File tree

2 files changed

+60
-15
lines changed

2 files changed

+60
-15
lines changed

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

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,9 @@ HeapWord* ShenandoahFreeSet::try_allocate_from_mutator(ShenandoahAllocRequest& r
931931
ShenandoahHeapRegion* r = _heap->get_region(idx);
932932
if (can_allocate_from(r)) {
933933
if (req.is_old()) {
934-
flip_to_old_gc(r);
934+
if (!flip_to_old_gc(r)) {
935+
continue;
936+
}
935937
} else {
936938
flip_to_gc(r);
937939
}
@@ -1284,25 +1286,65 @@ void ShenandoahFreeSet::recycle_trash() {
12841286
heap->parallel_heap_region_iterate(&closure);
12851287
}
12861288

1287-
void ShenandoahFreeSet::flip_to_old_gc(ShenandoahHeapRegion* r) {
1288-
size_t idx = r->index();
1289+
bool ShenandoahFreeSet::flip_to_old_gc(ShenandoahHeapRegion* r) {
1290+
const size_t idx = r->index();
12891291

12901292
assert(_partitions.partition_id_matches(idx, ShenandoahFreeSetPartitionId::Mutator), "Should be in mutator view");
12911293
assert(can_allocate_from(r), "Should not be allocated");
12921294

12931295
ShenandoahGenerationalHeap* gen_heap = ShenandoahGenerationalHeap::heap();
1294-
size_t region_capacity = alloc_capacity(r);
1295-
_partitions.move_from_partition_to_partition(idx, ShenandoahFreeSetPartitionId::Mutator,
1296-
ShenandoahFreeSetPartitionId::OldCollector, region_capacity);
1297-
_partitions.assert_bounds();
1298-
_heap->old_generation()->augment_evacuation_reserve(region_capacity);
1296+
const size_t region_capacity = alloc_capacity(r);
1297+
12991298
bool transferred = gen_heap->generation_sizer()->transfer_to_old(1);
1300-
if (!transferred) {
1301-
log_warning(gc, free)("Forcing transfer of %zu to old reserve.", idx);
1302-
gen_heap->generation_sizer()->force_transfer_to_old(1);
1299+
if (transferred) {
1300+
_partitions.move_from_partition_to_partition(idx, ShenandoahFreeSetPartitionId::Mutator,
1301+
ShenandoahFreeSetPartitionId::OldCollector, region_capacity);
1302+
_partitions.assert_bounds();
1303+
_heap->old_generation()->augment_evacuation_reserve(region_capacity);
1304+
return true;
13031305
}
1304-
// We do not ensure that the region is no longer trash, relying on try_allocate_in(), which always comes next,
1305-
// to recycle trash before attempting to allocate anything in the region.
1306+
1307+
if (_heap->young_generation()->free_unaffiliated_regions() == 0 && _heap->old_generation()->free_unaffiliated_regions() > 0) {
1308+
// Old has free unaffiliated regions, but it couldn't use them for allocation (likely because they
1309+
// are trash and weak roots are in process). In this scenario, we aren't really stealing from the
1310+
// mutator (they have nothing to steal), but they do have a usable region in their partition. What
1311+
// we want to do here is swap that region from the mutator partition with one from the old collector
1312+
// partition.
1313+
// 1. Find a temporarily unusable trash region in the old collector partition
1314+
ShenandoahRightLeftIterator iterator(&_partitions, ShenandoahFreeSetPartitionId::OldCollector, true);
1315+
idx_t unusable_trash = -1;
1316+
for (unusable_trash = iterator.current(); iterator.has_next(); unusable_trash = iterator.next()) {
1317+
const ShenandoahHeapRegion* region = _heap->get_region(unusable_trash);
1318+
if (region->is_trash() && _heap->is_concurrent_weak_root_in_progress()) {
1319+
break;
1320+
}
1321+
}
1322+
1323+
if (unusable_trash != -1) {
1324+
const size_t unusable_capacity = alloc_capacity(unusable_trash);
1325+
// 2. Move the (temporarily) unusable trash region we found to the mutator partition
1326+
_partitions.move_from_partition_to_partition(unusable_trash,
1327+
ShenandoahFreeSetPartitionId::OldCollector,
1328+
ShenandoahFreeSetPartitionId::Mutator, unusable_capacity);
1329+
1330+
// 3. Move this usable region from the mutator partition to the old collector partition
1331+
_partitions.move_from_partition_to_partition(idx,
1332+
ShenandoahFreeSetPartitionId::Mutator,
1333+
ShenandoahFreeSetPartitionId::OldCollector, region_capacity);
1334+
1335+
_partitions.assert_bounds();
1336+
1337+
// 4. Do not adjust capacities for generations, we just swapped the regions that have already
1338+
// been accounted for. However, we should adjust the evacuation reserves as those may have changed.
1339+
shenandoah_assert_heaplocked();
1340+
const size_t reserve = _heap->old_generation()->get_evacuation_reserve();
1341+
_heap->old_generation()->set_evacuation_reserve(reserve - unusable_capacity + region_capacity);
1342+
return true;
1343+
}
1344+
}
1345+
1346+
// We can't take this region young because it has no free unaffiliated regions (transfer failed).
1347+
return false;
13061348
}
13071349

13081350
void ShenandoahFreeSet::flip_to_gc(ShenandoahHeapRegion* r) {

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,12 @@ class ShenandoahFreeSet : public CHeapObj<mtGC> {
323323
//
324324
// Typical usage: During evacuation, the GC may find it needs more memory than had been reserved at the start of evacuation to
325325
// hold evacuated objects. If this occurs and memory is still available in the Mutator's free set, we will flip a region from
326-
// the Mutator free set into the Collector or OldCollector free set.
326+
// the Mutator free set into the Collector or OldCollector free set. The conditions to move this region are checked by
327+
// the caller, so the given region is always moved.
327328
void flip_to_gc(ShenandoahHeapRegion* r);
328-
void flip_to_old_gc(ShenandoahHeapRegion* r);
329+
330+
// Return true if and only if the given region is successfully flipped to the old partition
331+
bool flip_to_old_gc(ShenandoahHeapRegion* r);
329332

330333
// Handle allocation for mutator.
331334
HeapWord* allocate_for_mutator(ShenandoahAllocRequest &req, bool &in_new_region);

0 commit comments

Comments
 (0)