More eagerly to refresh alloc regions in attempt_allocation_slow since it is holding heap lock

This commit is contained in:
Xiaolong Peng 2026-01-13 15:42:35 -08:00
parent 475bdac7cd
commit 6cc1834b7b
2 changed files with 19 additions and 9 deletions

View File

@ -161,17 +161,20 @@ HeapWord* ShenandoahAllocator<ALLOC_PARTITION>::attempt_allocation_slow(Shenando
// if alloc regions have been refreshed by other thread while current thread waits to take heap lock.
regions_ready_for_refresh = 0u; //reset regions_ready_for_refresh to 0.
obj = attempt_allocation_in_alloc_regions<true /*holding heap lock*/>(req, in_new_region, alloc_start_index(), regions_ready_for_refresh);
if (obj != nullptr) {
if (obj != nullptr && regions_ready_for_refresh == 0) {
return obj;
}
}
ShenandoahHeapAccountingUpdater accounting_updater(_free_set, ALLOC_PARTITION);
// Eagerly refresh alloc regions if any is ready for refresh since it is already holding the heap lock.
if (regions_ready_for_refresh > 0u) {
int refreshed = refresh_alloc_regions(&req, &in_new_region, &obj);
if (refreshed > 0 || obj != nullptr) {
accounting_updater._need_update = true;
if (obj == nullptr) {
if (const int refreshed = refresh_alloc_regions(&req, &in_new_region, &obj); refreshed > 0 || obj != nullptr) {
accounting_updater._need_update = true;
}
} else {
accounting_updater._need_update = refresh_alloc_regions() > 0;
}
if (obj != nullptr) {
return obj;

View File

@ -72,13 +72,20 @@ protected:
// refresh_alloc_regions to eagerly retire and refill those alloc regions.
HeapWord* attempt_allocation(ShenandoahAllocRequest& req, bool& in_new_region);
// Slow path of allocation work. When fast path trying to allocate in shared alloc regions fails attempt_allocation_slow will
// be called to refresh shared alloc regions and allocate memory for the alloc request.
// Slow path of non-humongous allocation work.
// When the allocator fails to allocate memory with fast-path w/o holding heap lock, it calls this function
// to try the slow-path allocation. The function always acquires heap lock and then handle the slow-path allocation as:
// 1. if _epoch_id has changed by any other thread, try the fast-path again immediately since alloc regions have already been refreshed;
// 2. if any region of alloc regions is ready for refresh(retire), call refresh_alloc_regions to refresh;
// 3. if allocation is still not satisfied in above steps, call attempt_allocation_from_free_set to find a region
// in free set w/ sufficient free space and allocate in the region;
// 4. update accounting if needed;
// Call must not hold heap lock.
HeapWord* attempt_allocation_slow(ShenandoahAllocRequest& req, bool& in_new_region, uint regions_ready_for_refresh, uint32_t old_epoch_id);
// Attempt to allocate from a region in free set, rather than from any of shared alloc regions, it might be called in the conditions below:
// 1. _alloc_region_count is explicitly set to 0 to disable CAS allocator;
// 2. all the shared alloc regions are not ready to retire, nor have enough space for allocation.
// 1. All the shared alloc regions are not ready to retire, nor have enough space for allocation;
// 2. There are regions can be retired, but the new regions reserved from free set don't have enough free space to satisfy the allocation.
// Caller has to hold heap lock.
HeapWord* attempt_allocation_from_free_set(ShenandoahAllocRequest& req, bool& in_new_region);