return allocate_region (gen_num, size, start, end, direction, fn);
}
+// Whenever a region is deleted, it is expected that the memory and the mark array
+// of the region is decommitted already.
void region_allocator::delete_region (uint8_t* region_start)
{
enter_spin_lock();
bool gc_heap::init_table_for_region (int gen_number, heap_segment* region)
{
#ifdef BACKGROUND_GC
- dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
- heap_segment_mem (region), mark_array));
- if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
- !commit_mark_array_new_seg (__this, region))
- {
- dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix",
- get_region_start (region), heap_segment_reserved (region)));
+ dprintf (GC_TABLE_LOG, ("new seg %Ix, mark_array is %Ix",
+ heap_segment_mem (region), mark_array));
+ if (((region->flags & heap_segment_flags_ma_committed) == 0) &&
+ !commit_mark_array_new_seg (__this, region))
+ {
+ dprintf (GC_TABLE_LOG, ("failed to commit mark array for the new region %Ix-%Ix",
+ get_region_start (region), heap_segment_reserved (region)));
- // We don't have memory to commit the mark array so we cannot use the new region.
- global_region_allocator.delete_region (get_region_start (region));
- return false;
- }
- if ((region->flags & heap_segment_flags_ma_committed) != 0)
- {
- bgc_verify_mark_array_cleared (region, true);
- }
+ // We don't have memory to commit the mark array so we cannot use the new region.
+ decommit_region (region, gen_to_oh (gen_number), heap_number);
+ return false;
+ }
+ if ((region->flags & heap_segment_flags_ma_committed) != 0)
+ {
+ bgc_verify_mark_array_cleared (region, true);
+ }
#endif //BACKGROUND_GC
if (gen_number <= max_generation)
while (global_regions_to_decommit[kind].get_num_free_regions() > 0)
{
heap_segment* region = global_regions_to_decommit[kind].unlink_region_front();
-
- uint8_t* page_start = align_lower_page(get_region_start(region));
- uint8_t* end = use_large_pages_p ? heap_segment_used(region) : heap_segment_committed(region);
- size_t size = end - page_start;
- bool decommit_succeeded_p = false;
- if (!use_large_pages_p)
- {
- decommit_succeeded_p = virtual_decommit(page_start, size, recorded_committed_free_bucket);
- dprintf(REGIONS_LOG, ("decommitted region %p(%p-%p) (%zu bytes) - success: %d",
- region,
- page_start,
- end,
- size,
- decommit_succeeded_p));
- }
- if (!decommit_succeeded_p)
- {
- memclr(page_start, size);
- dprintf(REGIONS_LOG, ("cleared region %p(%p-%p) (%zu bytes)",
- region,
- page_start,
- end,
- size));
- }
- global_region_allocator.delete_region(get_region_start(region));
+ size_t size = decommit_region (region, recorded_committed_free_bucket, -1);
decommit_size += size;
if (decommit_size >= max_decommit_step_size)
{
return (decommit_size != 0);
}
+#ifdef USE_REGIONS
+size_t gc_heap::decommit_region (heap_segment* region, int bucket, int h_number)
+{
+ uint8_t* page_start = align_lower_page (get_region_start (region));
+ uint8_t* end = use_large_pages_p ? heap_segment_used (region) : heap_segment_committed (region);
+ size_t size = end - page_start;
+ bool decommit_succeeded_p = false;
+ if (!use_large_pages_p)
+ {
+ decommit_succeeded_p = virtual_decommit (page_start, size, bucket, h_number);
+ }
+ dprintf (REGIONS_LOG, ("decommitted region %p(%p-%p) (%zu bytes) - success: %d",
+ region,
+ page_start,
+ end,
+ size,
+ decommit_succeeded_p));
+ if (decommit_succeeded_p)
+ {
+ heap_segment_committed (region) = heap_segment_mem (region);
+ }
+ else
+ {
+ memclr (page_start, size);
+ heap_segment_used (region) = heap_segment_mem (region);
+ dprintf(REGIONS_LOG, ("cleared region %p(%p-%p) (%zu bytes)",
+ region,
+ page_start,
+ end,
+ size));
+ }
+
+ // Under USE_REGIONS, mark array is never partially committed. So we are only checking for this
+ // flag here.
+ if ((region->flags & heap_segment_flags_ma_committed) != 0)
+ {
+#ifdef MULTIPLE_HEAPS
+ // In return_free_region, we set heap_segment_heap (region) to nullptr so we cannot use it here.
+ // but since all heaps share the same mark array we simply pick the 0th heap to use.
+ gc_heap* hp = g_heaps [0];
+#else
+ gc_heap* hp = pGenGCHeap;
+#endif
+ hp->decommit_mark_array_by_seg (region);
+ region->flags &= ~(heap_segment_flags_ma_committed);
+ }
+
+ if (use_large_pages_p)
+ {
+ assert (heap_segment_used (region) == heap_segment_mem (region));
+ }
+ else
+ {
+ assert (heap_segment_committed (region) == heap_segment_mem (region));
+ }
+ assert ((region->flags & heap_segment_flags_ma_committed) == 0);
+ global_region_allocator.delete_region (get_region_start (region));
+
+ return size;
+}
+#endif //USE_REGIONS
+
#ifdef MULTIPLE_HEAPS
// return the decommitted size
size_t gc_heap::decommit_ephemeral_segment_pages_step ()