Skip to content

Commit 6da8e2a

Browse files
authored
Decommit memory as needed (#79912)
1 parent 3f5210d commit 6da8e2a

File tree

2 files changed

+80
-40
lines changed

2 files changed

+80
-40
lines changed

src/coreclr/gc/gc.cpp

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3988,6 +3988,8 @@ bool region_allocator::allocate_large_region (int gen_num, uint8_t** start, uint
39883988
return allocate_region (gen_num, size, start, end, direction, fn);
39893989
}
39903990

3991+
// Whenever a region is deleted, it is expected that the memory and the mark array
3992+
// of the region is decommitted already.
39913993
void region_allocator::delete_region (uint8_t* region_start)
39923994
{
39933995
enter_spin_lock();
@@ -20325,22 +20327,22 @@ bool gc_heap::try_get_new_free_region()
2032520327
bool gc_heap::init_table_for_region (int gen_number, heap_segment* region)
2032620328
{
2032720329
#ifdef BACKGROUND_GC
20328-
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
20329-
heap_segment_mem (region), mark_array));
20330-
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
20331-
!commit_mark_array_new_seg (__this, region))
20332-
{
20333-
dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix",
20334-
get_region_start (region), heap_segment_reserved (region)));
20330+
dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
20331+
heap_segment_mem (region), mark_array));
20332+
if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
20333+
!commit_mark_array_new_seg (__this, region))
20334+
{
20335+
dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix",
20336+
get_region_start (region), heap_segment_reserved (region)));
2033520337

20336-
// We don't have memory to commit the mark array so we cannot use the new region.
20337-
global_region_allocator.delete_region (get_region_start (region));
20338-
return false;
20339-
}
20340-
if ((region->flags & heap_segment_flags_ma_committed) != 0)
20341-
{
20342-
bgc_verify_mark_array_cleared (region, true);
20343-
}
20338+
// We don't have memory to commit the mark array so we cannot use the new region.
20339+
decommit_region (region, gen_to_oh (gen_number), heap_number);
20340+
return false;
20341+
}
20342+
if ((region->flags & heap_segment_flags_ma_committed) != 0)
20343+
{
20344+
bgc_verify_mark_array_cleared (region, true);
20345+
}
2034420346
#endif //BACKGROUND_GC
2034520347

2034620348
if (gen_number <= max_generation)
@@ -41064,31 +41066,7 @@ bool gc_heap::decommit_step (uint64_t step_milliseconds)
4106441066
while (global_regions_to_decommit[kind].get_num_free_regions() > 0)
4106541067
{
4106641068
heap_segment* region = global_regions_to_decommit[kind].unlink_region_front();
41067-
41068-
uint8_t* page_start = align_lower_page(get_region_start(region));
41069-
uint8_t* end = use_large_pages_p ? heap_segment_used(region) : heap_segment_committed(region);
41070-
size_t size = end - page_start;
41071-
bool decommit_succeeded_p = false;
41072-
if (!use_large_pages_p)
41073-
{
41074-
decommit_succeeded_p = virtual_decommit(page_start, size, recorded_committed_free_bucket);
41075-
dprintf(REGIONS_LOG, ("decommitted region %p(%p-%p) (%zu bytes) - success: %d",
41076-
region,
41077-
page_start,
41078-
end,
41079-
size,
41080-
decommit_succeeded_p));
41081-
}
41082-
if (!decommit_succeeded_p)
41083-
{
41084-
memclr(page_start, size);
41085-
dprintf(REGIONS_LOG, ("cleared region %p(%p-%p) (%zu bytes)",
41086-
region,
41087-
page_start,
41088-
end,
41089-
size));
41090-
}
41091-
global_region_allocator.delete_region(get_region_start(region));
41069+
size_t size = decommit_region (region, recorded_committed_free_bucket, -1);
4109241070
decommit_size += size;
4109341071
if (decommit_size >= max_decommit_step_size)
4109441072
{
@@ -41115,6 +41093,64 @@ bool gc_heap::decommit_step (uint64_t step_milliseconds)
4111541093
return (decommit_size != 0);
4111641094
}
4111741095

41096+
#ifdef USE_REGIONS
41097+
size_t gc_heap::decommit_region (heap_segment* region, int bucket, int h_number)
41098+
{
41099+
uint8_t* page_start = align_lower_page (get_region_start (region));
41100+
uint8_t* end = use_large_pages_p ? heap_segment_used (region) : heap_segment_committed (region);
41101+
size_t size = end - page_start;
41102+
bool decommit_succeeded_p = false;
41103+
if (!use_large_pages_p)
41104+
{
41105+
decommit_succeeded_p = virtual_decommit (page_start, size, bucket, h_number);
41106+
}
41107+
dprintf (REGIONS_LOG, ("decommitted region %p(%p-%p) (%zu bytes) - success: %d",
41108+
region,
41109+
page_start,
41110+
end,
41111+
size,
41112+
decommit_succeeded_p));
41113+
if (decommit_succeeded_p)
41114+
{
41115+
heap_segment_committed (region) = heap_segment_mem (region);
41116+
}
41117+
else
41118+
{
41119+
memclr (page_start, size);
41120+
heap_segment_used (region) = heap_segment_mem (region);
41121+
dprintf(REGIONS_LOG, ("cleared region %p(%p-%p) (%zu bytes)",
41122+
region,
41123+
page_start,
41124+
end,
41125+
size));
41126+
}
41127+
41128+
if ((region->flags & heap_segment_flags_ma_committed) != 0)
41129+
{
41130+
#ifdef MULTIPLE_HEAPS
41131+
gc_heap* hp = heap_segment_heap (region);
41132+
#else
41133+
gc_heap* hp = pGenGCHeap;
41134+
#endif
41135+
hp->decommit_mark_array_by_seg (region);
41136+
region->flags &= ~(heap_segment_flags_ma_committed);
41137+
}
41138+
41139+
if (use_large_pages_p)
41140+
{
41141+
assert (heap_segment_used (region) == heap_segment_mem (region));
41142+
}
41143+
else
41144+
{
41145+
assert (heap_segment_committed (region) == heap_segment_mem (region));
41146+
}
41147+
assert ((region->flags & heap_segment_flags_ma_committed) == 0);
41148+
global_region_allocator.delete_region (get_region_start (region));
41149+
41150+
return size;
41151+
}
41152+
#endif //USE_REGIONS
41153+
4111841154
#ifdef MULTIPLE_HEAPS
4111941155
// return the decommitted size
4112041156
size_t gc_heap::decommit_ephemeral_segment_pages_step ()

src/coreclr/gc/gcpriv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,6 +2079,10 @@ class gc_heap
20792079
size_t decommit_heap_segment_pages_worker (heap_segment* seg, uint8_t *new_committed);
20802080
PER_HEAP_ISOLATED
20812081
bool decommit_step (uint64_t step_milliseconds);
2082+
#ifdef USE_REGIONS
2083+
PER_HEAP_ISOLATED
2084+
size_t decommit_region (heap_segment* region, int bucket, int h_number);
2085+
#endif //USE_REGIONS
20822086
PER_HEAP
20832087
void decommit_heap_segment (heap_segment* seg);
20842088
PER_HEAP_ISOLATED

0 commit comments

Comments
 (0)