This commit is contained in:
Daan Leijen 2024-03-25 16:02:20 -07:00
parent 0022802177
commit 460278f110
2 changed files with 8 additions and 35 deletions

View file

@ -71,7 +71,7 @@ mi_block_t* _mi_page_ptr_unalign(const mi_page_t* page, const void* p) {
static void mi_decl_noinline mi_free_generic_local(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept { static void mi_decl_noinline mi_free_generic_local(mi_page_t* page, mi_segment_t* segment, void* p) mi_attr_noexcept {
MI_UNUSED(segment); MI_UNUSED(segment);
mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(page, p) : (mi_block_t*)p); mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(page, p) : (mi_block_t*)p);
mi_free_block_local(page, block, true, true); mi_free_block_local(page, block, true /* track stats */, true /* check for a full page */);
} }
// free a pointer owned by another thread (page parameter comes first for better codegen) // free a pointer owned by another thread (page parameter comes first for better codegen)
@ -136,7 +136,7 @@ void mi_free(void* p) mi_attr_noexcept
if mi_likely(page->flags.full_aligned == 0) { // and it is not a full page (full pages need to move from the full bin), nor has aligned blocks (aligned blocks need to be unaligned) if mi_likely(page->flags.full_aligned == 0) { // and it is not a full page (full pages need to move from the full bin), nor has aligned blocks (aligned blocks need to be unaligned)
// thread-local, aligned, and not a full page // thread-local, aligned, and not a full page
mi_block_t* const block = (mi_block_t*)p; mi_block_t* const block = (mi_block_t*)p;
mi_free_block_local(page, block, true, false /* no need to check if the page is full */); mi_free_block_local(page, block, true /* track stats */, false /* no need to check if the page is full */);
} }
else { else {
// page is full or contains (inner) aligned blocks; use generic path // page is full or contains (inner) aligned blocks; use generic path
@ -167,11 +167,11 @@ bool _mi_free_delayed_block(mi_block_t* block) {
return false; return false;
} }
// collect all other non-local frees to ensure up-to-date `used` count // collect all other non-local frees (move from `thread_free` to `free`) to ensure up-to-date `used` count
_mi_page_free_collect(page, false); _mi_page_free_collect(page, false);
// and free the block (possibly freeing the page as well since used is updated) // and free the block (possibly freeing the page as well since `used` is updated)
mi_free_block_local(page, block, false /* stats have already been adjusted */, true); mi_free_block_local(page, block, false /* stats have already been adjusted */, true /* check for a full page */);
return true; return true;
} }
@ -225,10 +225,6 @@ static void mi_decl_noinline mi_free_block_delayed_mt( mi_page_t* page, mi_block
} }
} }
#if MI_HUGE_PAGE_ABANDON
static void mi_stat_huge_free(const mi_page_t* page);
#endif
// Multi-threaded free (`_mt`) (or free in huge block if compiled with MI_HUGE_PAGE_ABANDON) // Multi-threaded free (`_mt`) (or free in huge block if compiled with MI_HUGE_PAGE_ABANDON)
static void mi_decl_noinline mi_free_block_mt(mi_page_t* page, mi_segment_t* segment, mi_block_t* block) static void mi_decl_noinline mi_free_block_mt(mi_page_t* page, mi_segment_t* segment, mi_block_t* block)
{ {
@ -251,7 +247,7 @@ static void mi_decl_noinline mi_free_block_mt(mi_page_t* page, mi_segment_t* seg
// that is safe as these are constant and the page won't be freed (as the block is not freed yet). // that is safe as these are constant and the page won't be freed (as the block is not freed yet).
mi_check_padding(page, block); mi_check_padding(page, block);
// adjust stats (after padding check and potential recursive `mi_free` above) // adjust stats (after padding check and potentially recursive `mi_free` above)
mi_stat_free(page, block); // stat_free may access the padding mi_stat_free(page, block); // stat_free may access the padding
mi_track_free_size(block, mi_page_usable_size_of(page,block)); mi_track_free_size(block, mi_page_usable_size_of(page,block));
@ -261,7 +257,6 @@ static void mi_decl_noinline mi_free_block_mt(mi_page_t* page, mi_segment_t* seg
if (segment->page_kind == MI_PAGE_HUGE) { if (segment->page_kind == MI_PAGE_HUGE) {
#if MI_HUGE_PAGE_ABANDON #if MI_HUGE_PAGE_ABANDON
// huge page segments are always abandoned and can be freed immediately // huge page segments are always abandoned and can be freed immediately
mi_stat_huge_free(page);
_mi_segment_huge_page_free(segment, page, block); _mi_segment_huge_page_free(segment, page, block);
return; return;
#else #else
@ -510,35 +505,13 @@ static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) {
mi_heap_stat_decrease(heap, normal_bins[_mi_bin(bsize)], 1); mi_heap_stat_decrease(heap, normal_bins[_mi_bin(bsize)], 1);
#endif #endif
} }
#if !MI_HUGE_PAGE_ABANDON
else { else {
const size_t bpsize = mi_page_block_size(page); const size_t bpsize = mi_page_block_size(page); // match stat in page.c:mi_huge_page_alloc
mi_heap_stat_decrease(heap, huge, bpsize); mi_heap_stat_decrease(heap, huge, bpsize);
} }
#endif
} }
#else #else
static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) { static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) {
MI_UNUSED(page); MI_UNUSED(block); MI_UNUSED(page); MI_UNUSED(block);
} }
#endif #endif
#if MI_HUGE_PAGE_ABANDON
#if (MI_STAT>0)
// maintain stats for huge objects
static void mi_stat_huge_free(const mi_page_t* page) {
mi_heap_t* const heap = mi_heap_get_default();
const size_t bsize = mi_page_block_size(page); // to match stats in `page.c:mi_page_huge_alloc`
if (bsize <= MI_HUGE_OBJ_SIZE_MAX) {
mi_heap_stat_decrease(heap, huge, bsize);
}
else {
mi_heap_stat_decrease(heap, giant, bsize);
}
}
#else
static void mi_stat_huge_free(const mi_page_t* page) {
MI_UNUSED(page);
}
#endif
#endif

View file

@ -1167,7 +1167,7 @@ void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block
mi_block_set_next(page, block, page->free); mi_block_set_next(page, block, page->free);
page->free = block; page->free = block;
page->used--; page->used--;
page->is_zero = false; page->is_zero_init = false;
mi_assert(page->used == 0); mi_assert(page->used == 0);
mi_tld_t* tld = heap->tld; mi_tld_t* tld = heap->tld;
mi_segments_track_size((long)segment->segment_size, &tld->segments); mi_segments_track_size((long)segment->segment_size, &tld->segments);