@@ -13338,6 +13338,49 @@ void gc_heap::age_free_regions (const char* msg)
1333813338 }
1333913339}
1334013340
13341+ // distribute_free_regions is called during all blocking GCs and in the start of the BGC mark phase
13342+ // unless we already called it during an ephemeral GC right before the BGC.
13343+ //
13344+ // Free regions are stored on the following permanent lists:
13345+ // - global_regions_to_decommit
13346+ // - global_free_huge_regions
13347+ // - (per-heap) free_regions
13348+ // and the following lists that are local to distribute_free_regions:
13349+ // - aged_regions
13350+ // - surplus_regions
13351+ //
13352+ // For reason_induced_aggressive GCs, we decommit all regions. Therefore, the below description is
13353+ // for other GC types.
13354+ //
13355+ // distribute_free_regions steps:
13356+ //
13357+ // 1. Process region ages
13358+ // a. Move all huge regions from free_regions to global_free_huge_regions.
13359+ // (The intention is that free_regions shouldn't contain any huge regions outside of the period
13360+ // where a GC reclaims them and distribute_free_regions moves them to global_free_huge_regions,
13361+ // though perhaps BGC can leave them there. Future work could verify and assert this.)
13362+ // b. Move any basic region in global_regions_to_decommit (which means we intended to decommit them
13363+ // but haven't done so yet) to surplus_regions
13364+ // b. Move all huge regions that are past the age threshold from global_free_huge_regions to aged_regions
13365+ // c. Move all basic/large regions that are past the age threshold from free_regions to aged_regions
13366+ // 2. Move all regions from aged_regions to global_regions_to_decommit. Note that the intention is to
13367+ // combine this with move_highest_free_regions in a future change, which is why we don't just do this
13368+ // in steps 1b/1c.
13369+ // 3. Compute the required per-heap budgets for SOH (basic regions) and the balance. The budget for LOH
13370+ // (large/huge) is zero as we are using an entirely age-based approach.
13371+ // balance = (number of free regions) - budget
13372+ // 4. Decide if we are going to distribute or decommit a nonzero balance. To distribute, we adjust the
13373+ // per-heap budgets, so after this step the LOH (large/huge) budgets can be positive.
13374+ // a. A negative balance (deficit) must be distributed since decommitting a negative number of regions
13375+ // doesn't make sense. A negative balance isn't possible for LOH since the budgets start at zero.
13376+ // b. For SOH (basic), we will decommit surplus regions unless we are in a foreground GC during BGC.
13377+ // c. For LOH (large/huge), we will distribute surplus regions since we are using an entirely age-based
13378+ // approach. However, if we are in a high-memory-usage scenario, we will decommit.
13379+ // 5. Implement the distribute-or-decommit strategy. To distribute, we simply move regions across heaps,
13380+ // using surplus_regions as a holding space. To decommit, for server GC we generally leave them on the
13381+ // global_regions_to_decommit list and decommit them over time. However, in high-memory-usage scenarios,
13382+ // we will immediately decommit some or all of these regions. For workstation GC, we decommit a limited
13383+ // amount and move the rest back to the (one) heap's free_list.
1334113384void gc_heap::distribute_free_regions()
1334213385{
1334313386#ifdef MULTIPLE_HEAPS
0 commit comments