diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 00d36794a6e834..501c93d154ad23 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -2485,7 +2485,7 @@ class gc_heap PER_HEAP_METHOD void decommit_heap_segment (heap_segment* seg); PER_HEAP_ISOLATED_METHOD bool virtual_alloc_commit_for_heap (void* addr, size_t size, int h_number); PER_HEAP_ISOLATED_METHOD bool virtual_commit (void* address, size_t size, int bucket, int h_number=-1, bool* hard_limit_exceeded_p=NULL); - PER_HEAP_ISOLATED_METHOD bool virtual_decommit (void* address, size_t size, int bucket, int h_number=-1); + PER_HEAP_ISOLATED_METHOD bool virtual_decommit (void* address, size_t size, int bucket, int h_number=-1, void* end_of_data=nullptr); PER_HEAP_ISOLATED_METHOD void reduce_committed_bytes (void* address, size_t size, int bucket, int h_number, bool decommit_succeeded_p); friend void destroy_card_table (uint32_t*); PER_HEAP_ISOLATED_METHOD void destroy_card_table_helper (uint32_t* c_table); diff --git a/src/coreclr/gc/memory.cpp b/src/coreclr/gc/memory.cpp index cd533a16e8036d..78a162e06bb34c 100644 --- a/src/coreclr/gc/memory.cpp +++ b/src/coreclr/gc/memory.cpp @@ -161,7 +161,7 @@ void gc_heap::reduce_committed_bytes (void* address, size_t size, int bucket, in } } -bool gc_heap::virtual_decommit (void* address, size_t size, int bucket, int h_number) +bool gc_heap::virtual_decommit (void* address, size_t size, int bucket, int h_number, void* end_of_data) { /** * Here are all possible cases for the decommits: @@ -173,6 +173,14 @@ bool gc_heap::virtual_decommit (void* address, size_t size, int bucket, int h_nu bool decommit_succeeded_p = ((bucket != recorded_committed_bookkeeping_bucket) && use_large_pages_p) ? true : GCToOSInterface::VirtualDecommit (address, size); + // Large pages: the decommit above is a no-op so memory retains stale data. + // Clear up to end_of_data if the caller provided it so that the heap never + // observes leftover object references after the region is reused. + if (use_large_pages_p && (end_of_data != nullptr) && (end_of_data > address)) + { + memclr ((uint8_t*)address, (uint8_t*)end_of_data - (uint8_t*)address); + } + reduce_committed_bytes (address, size, bucket, h_number, decommit_succeeded_p); return decommit_succeeded_p; diff --git a/src/coreclr/gc/regions_segments.cpp b/src/coreclr/gc/regions_segments.cpp index 1518ef8c0b8e47..ee51642d5afd8a 100644 --- a/src/coreclr/gc/regions_segments.cpp +++ b/src/coreclr/gc/regions_segments.cpp @@ -1834,7 +1834,7 @@ void gc_heap::distribute_free_regions() size_t end_space = heap_segment_committed (region) - aligned_allocated; if (end_space > 0) { - virtual_decommit (aligned_allocated, end_space, gen_to_oh (i), hn); + virtual_decommit (aligned_allocated, end_space, gen_to_oh (i), hn, heap_segment_used (region)); heap_segment_committed (region) = aligned_allocated; heap_segment_used (region) = min (heap_segment_used (region), heap_segment_committed (region)); assert (heap_segment_committed (region) > heap_segment_mem (region));