Loading...
--- libmalloc/libmalloc-425.100.7/src/nanov2_malloc.c
+++ libmalloc/libmalloc-715.120.13/src/nanov2_malloc.c
@@ -60,7 +60,7 @@
nanov2_block_meta_t **block_metapp, size_t rounded_size,
nanov2_size_class_t size_class, int allocation_index,
nanov2_block_meta_t *madvise_block_metap, void *corrupt_slot,
- bool clear);
+ bool clear, bool typed, malloc_type_id_t type_id);
MALLOC_ALWAYS_INLINE MALLOC_INLINE nanov2_block_meta_t *
nanov2_free_to_block_inline(nanozonev2_t *nanozone, void *ptr,
@@ -1067,32 +1067,43 @@
return size ? size : nanozone->helper_zone->size(nanozone->helper_zone, ptr);
}
-MALLOC_NOEXPORT void *
-nanov2_malloc(nanozonev2_t *nanozone, size_t size)
-{
- size_t rounded_size = _nano_common_good_size(size);
- if (rounded_size <= NANO_MAX_SIZE) {
- nanov2_block_meta_t *madvise_block_metap = NULL;
- nanov2_size_class_t size_class = nanov2_size_class_from_size(rounded_size);
-
- // Get the index of the pointer to the block from which we are should be
- // allocating. This currently depends on the physical CPU number.
- int allocation_index = nanov2_get_allocation_block_index();
-
- // Get the current allocation block meta data pointer. If this is NULL,
- // we need to find a new allocation block.
- nanov2_block_meta_t **block_metapp =
- &nanozone->current_block[size_class][allocation_index];
- nanov2_block_meta_t *block_metap = os_atomic_load(block_metapp, relaxed);
- bool corruption = false;
- void *ptr = NULL;
- if (block_metap) {
- // Fast path: we have a block -- try to allocate from it.
- ptr = nanov2_allocate_from_block_inline(nanozone, block_metap,
- size_class, &madvise_block_metap, &corruption);
- if (ptr && !corruption) {
- // Always clear the double-free guard so that we can recognize
- // that this block is not on the free list.
+MALLOC_ALWAYS_INLINE MALLOC_INLINE
+void
+nanov2_bzero(void *ptr, size_t size)
+{
+ // TODO: inline bzero from libplatform
+ bzero(ptr, size);
+}
+
+MALLOC_ALWAYS_INLINE MALLOC_INLINE
+static void *
+_nanov2_allocate(nanozonev2_t *nanozone, size_t rounded_size, bool clear,
+ bool typed, malloc_type_id_t type_id)
+{
+ nanov2_block_meta_t *madvise_block_metap = NULL;
+ nanov2_size_class_t size_class = nanov2_size_class_from_size(rounded_size);
+
+ // Get the index of the pointer to the block from which we are should be
+ // allocating. This currently depends on the physical CPU number.
+ int allocation_index = nanov2_get_allocation_block_index();
+
+ // Get the current allocation block meta data pointer. If this is NULL, we
+ // need to find a new allocation block.
+ nanov2_block_meta_t **block_metapp =
+ &nanozone->current_block[size_class][allocation_index];
+ nanov2_block_meta_t *block_metap = os_atomic_load(block_metapp, relaxed);
+ bool corruption = false;
+ void *ptr = NULL;
+ if (block_metap) {
+ // Fast path: we have a block -- try to allocate from it.
+ ptr = nanov2_allocate_from_block_inline(nanozone, block_metap,
+ size_class, &madvise_block_metap, &corruption);
+ if (ptr && !corruption) {
+ if (clear && malloc_zero_policy != MALLOC_ZERO_ON_FREE) {
+ nanov2_bzero(ptr, rounded_size);
+ } else {
+ // Always clear the double-free guard so that we can recognize that
+ // this block is not on the free list.
nanov2_free_slot_t *slotp = (nanov2_free_slot_t *)ptr;
os_atomic_store(&slotp->double_free_guard, 0, relaxed);
@@ -1101,24 +1112,41 @@
// all cases, even if a cleared allocation is not requested, to
// prevent any leakage through the next_slot bits.
os_atomic_store(&slotp->next_slot, 0, relaxed);
- return ptr;
}
- }
-
- return nanov2_allocate_outlined(nanozone, block_metapp, rounded_size,
- size_class, allocation_index, madvise_block_metap, ptr, false);
+ return ptr;
+ }
+ }
+
+ return nanov2_allocate_outlined(nanozone, block_metapp, rounded_size,
+ size_class, allocation_index, madvise_block_metap, ptr, clear,
+ typed, type_id);
+}
+
+MALLOC_NOEXPORT void *
+nanov2_malloc(nanozonev2_t *nanozone, size_t size)
+{
+ size_t rounded_size = _nano_common_good_size(size);
+ if (rounded_size <= NANO_MAX_SIZE) {
+ return _nanov2_allocate(nanozone, rounded_size, false, false,
+ MALLOC_TYPE_ID_NONE);
}
// Too big for nano, so delegate to the helper zone.
return nanozone->helper_zone->malloc(nanozone->helper_zone, size);
}
-MALLOC_ALWAYS_INLINE MALLOC_INLINE
-void
-nanov2_bzero(void *ptr, size_t size)
-{
- // TODO: inline bzero from libplatform
- bzero(ptr, size);
+MALLOC_NOEXPORT void *
+nanov2_malloc_type(nanozonev2_t *nanozone, size_t size,
+ malloc_type_id_t type_id)
+{
+ size_t rounded_size = _nano_common_good_size(size);
+ if (rounded_size <= NANO_MAX_SIZE) {
+ return _nanov2_allocate(nanozone, rounded_size, false, true, type_id);
+ }
+
+ // Too big for nano, so delegate to the helper zone.
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ return helper_zone->malloc_type_malloc(helper_zone, size, type_id);
}
MALLOC_NOEXPORT void
@@ -1189,51 +1217,6 @@
_nanov2_free(nanozone, ptr, true);
}
-MALLOC_ALWAYS_INLINE MALLOC_INLINE
-void *
-nanov2_malloc_zero(nanozonev2_t *nanozone, size_t rounded_size)
-{
- nanov2_block_meta_t *madvise_block_metap = NULL;
- nanov2_size_class_t size_class = nanov2_size_class_from_size(rounded_size);
-
- // Get the index of the pointer to the block from which we are should be
- // allocating. This currently depends on the physical CPU number.
- int allocation_index = nanov2_get_allocation_block_index();
-
- // Get the current allocation block meta data pointer. If this is NULL,
- // we need to find a new allocation block.
- nanov2_block_meta_t **block_metapp =
- &nanozone->current_block[size_class][allocation_index];
- nanov2_block_meta_t *block_metap = os_atomic_load(block_metapp, relaxed);
- bool corruption = false;
- void *ptr = NULL;
- if (block_metap) {
- // Fast path: we have a block -- try to allocate from it.
- ptr = nanov2_allocate_from_block_inline(nanozone, block_metap,
- size_class, &madvise_block_metap, &corruption);
- if (ptr && !corruption) {
- if (malloc_zero_policy == MALLOC_ZERO_ON_FREE) {
- // Always clear the double-free guard so that we can recognize that
- // this block is not on the free list.
- nanov2_free_slot_t *slotp = (nanov2_free_slot_t *)ptr;
- os_atomic_store(&slotp->double_free_guard, 0, relaxed);
-
- // We know the body of the allocation is already clear, so we just
- // need to clean up the next_slot word to get to all-zero. Do so in
- // all cases, even if a cleared allocation is not requested, to
- // prevent any leakage through the next_slot bits.
- os_atomic_store(&slotp->next_slot, 0, relaxed);
- } else {
- nanov2_bzero(ptr, rounded_size);
- }
- return ptr;
- }
- }
-
- return nanov2_allocate_outlined(nanozone, block_metapp, rounded_size,
- size_class, allocation_index, madvise_block_metap, ptr, true);
-}
-
MALLOC_NOEXPORT void *
nanov2_calloc(nanozonev2_t *nanozone, size_t num_items, size_t size)
{
@@ -1243,7 +1226,8 @@
}
size_t rounded_size = _nano_common_good_size(total_bytes);
if (total_bytes <= NANO_MAX_SIZE) {
- return nanov2_malloc_zero(nanozone, rounded_size);
+ return _nanov2_allocate(nanozone, rounded_size, true, false,
+ MALLOC_TYPE_ID_NONE);
}
// Too big for nano, so delegate to the helper zone.
@@ -1251,15 +1235,49 @@
}
MALLOC_NOEXPORT void *
+nanov2_calloc_type(nanozonev2_t *nanozone, size_t num_items, size_t size,
+ malloc_type_id_t type_id)
+{
+ size_t total_bytes;
+ if (calloc_get_size(num_items, size, 0, &total_bytes)) {
+ return NULL;
+ }
+ size_t rounded_size = _nano_common_good_size(total_bytes);
+ if (total_bytes <= NANO_MAX_SIZE) {
+ return _nanov2_allocate(nanozone, rounded_size, true, true, type_id);
+ }
+
+ // Too big for nano, so delegate to the helper zone.
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ return helper_zone->malloc_type_calloc(helper_zone, 1, total_bytes,
+ type_id);
+}
+
+MALLOC_NOEXPORT void *
nanov2_malloc_zero_on_alloc(nanozonev2_t *nanozone, size_t size)
{
size_t rounded_size = _nano_common_good_size(size);
if (rounded_size <= NANO_MAX_SIZE) {
- return nanov2_malloc_zero(nanozone, rounded_size);
+ return _nanov2_allocate(nanozone, rounded_size, true, false,
+ MALLOC_TYPE_ID_NONE);
}
// Too big for nano, so delegate to the helper zone.
return nanozone->helper_zone->malloc(nanozone->helper_zone, size);
+}
+
+MALLOC_NOEXPORT void *
+nanov2_malloc_type_zero_on_alloc(nanozonev2_t *nanozone, size_t size,
+ malloc_type_id_t type_id)
+{
+ size_t rounded_size = _nano_common_good_size(size);
+ if (rounded_size <= NANO_MAX_SIZE) {
+ return _nanov2_allocate(nanozone, rounded_size, true, true, type_id);
+ }
+
+ // Too big for nano, so delegate to the helper zone.
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ return helper_zone->malloc_type_malloc(helper_zone, size, type_id);
}
#endif // OS_VARIANT_RESOLVED
@@ -1273,25 +1291,44 @@
#endif // OS_VARIANT_NOTRESOLVED
#if OS_VARIANT_RESOLVED
-MALLOC_NOEXPORT void *
-nanov2_realloc(nanozonev2_t *nanozone, void *ptr, size_t new_size)
+MALLOC_ALWAYS_INLINE MALLOC_INLINE
+static void *
+_nanov2_realloc(nanozonev2_t *nanozone, void *ptr, size_t new_size, bool typed,
+ malloc_type_id_t type_id)
{
// If we are given a NULL pointer, just allocate memory of the requested
// size.
if (ptr == NULL) {
- return nanov2_malloc(nanozone, new_size);
- }
+ if (typed) {
+ return nanov2_malloc_type(nanozone, new_size, type_id);
+ } else {
+ return nanov2_malloc(nanozone, new_size);
+ }
+ }
+
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
size_t old_size = nanov2_pointer_size(nanozone, ptr, FALSE);
if (!old_size) {
// Not a Nano pointer - let the helper deal with it
- return nanozone->helper_zone->realloc(nanozone->helper_zone, ptr, new_size);
+ if (typed) {
+ return helper_zone->malloc_type_realloc(helper_zone, ptr, new_size,
+ type_id);
+ } else {
+ return helper_zone->realloc(helper_zone, ptr, new_size);
+ }
}
void *new_ptr;
if (new_size > NANO_MAX_SIZE) {
// Too large for Nano. Try to allocate from the helper zone.
- new_ptr = nanozone->helper_zone->malloc(nanozone->helper_zone, new_size);
+ if (typed) {
+ new_ptr = helper_zone->malloc_type_malloc(helper_zone, new_size,
+ type_id);
+ } else {
+ new_ptr = helper_zone->malloc(helper_zone, new_size);
+ }
+
if (!new_ptr) {
// Failed to allocate - leave the existing allocation alone.
return NULL;
@@ -1303,10 +1340,15 @@
return nanov2_malloc(nanozone, 0);
} else {
size_t new_good_size = _nano_common_good_size(new_size);
- if (new_good_size > old_size || new_good_size <= old_size/2) {
+ if (new_good_size > old_size || new_good_size <= old_size / 2) {
// Growing or shrinking to less than half size - we need to
// reallocate.
- new_ptr = nanov2_malloc(nanozone, new_good_size);
+ if (typed) {
+ new_ptr = nanov2_malloc_type(nanozone, new_good_size, type_id);
+ } else {
+ new_ptr = nanov2_malloc(nanozone, new_good_size);
+ }
+
if (!new_ptr) {
// Failed to allocate - leave the existing allocation alone.
return NULL;
@@ -1334,6 +1376,19 @@
return new_ptr;
}
+
+MALLOC_NOEXPORT void *
+nanov2_realloc(nanozonev2_t *nanozone, void *ptr, size_t new_size)
+{
+ return _nanov2_realloc(nanozone, ptr, new_size, false, MALLOC_TYPE_ID_NONE);
+}
+
+MALLOC_NOEXPORT void *
+nanov2_realloc_type(nanozonev2_t *nanozone, void *ptr, size_t new_size,
+ malloc_type_id_t type_id)
+{
+ return _nanov2_realloc(nanozone, ptr, new_size, true, type_id);
+}
#endif // OS_VARIANT_RESOLVED
#if OS_VARIANT_NOTRESOLVED
@@ -1407,6 +1462,22 @@
// Otherwise delegate to the helper zone
return nanozone->helper_zone->memalign(nanozone->helper_zone, alignment,
size);
+}
+
+MALLOC_NOEXPORT void *
+nanov2_memalign_type(nanozonev2_t *nanozone, size_t alignment, size_t size,
+ malloc_type_id_t type_id)
+{
+ // Serve directly if the requested alignment is trivially satisfied by our
+ // baseline alignment (16 bytes)
+ if (alignment <= NANO_REGIME_QUANTA_SIZE) {
+ return nanov2_malloc_type(nanozone, size, type_id);
+ }
+
+ // Otherwise delegate to the helper zone
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ return helper_zone->malloc_type_memalign(helper_zone, alignment, size,
+ type_id);
}
size_t
@@ -1517,9 +1588,7 @@
kern_return_t kr;
bitarray_t slots;
- if (!reader) {
- reader = nano_common_default_reader;
- }
+ reader = reader_or_in_memory_fallback(reader, task);
kr = reader(task, zone_address, sizeof(nanozonev2_t), (void **)&nanozone);
if (kr) {
@@ -1624,7 +1693,7 @@
bitarray_zap(slots, log_size, next_slot);
void *ptr = nanov2_slot_in_block_ptr(blockp, size_class, next_slot);
nanov2_free_slot_t *slotp = NANOV2_ZONE_PTR_TO_MAPPED_PTR(nanov2_free_slot_t *, ptr, ptr_offset);
- next_slot = slotp->next_slot;
+ next_slot = (uint16_t)slotp->next_slot;
free_list_count++;
}
// Add a range for each slot that is not on the freelist,
@@ -1643,7 +1712,7 @@
ranges[range_count].size = slot_size;
range_count++;
}
- free(slots);
+ _free(slots);
}
if (range_count) {
// Notify the in-use pointers that we found.
@@ -1960,7 +2029,7 @@
malloc_statistics_t *stats)
{
printer = printer ? printer : nanov2_null_printer;
- reader = !reader && task == mach_task_self() ? _malloc_default_reader : reader;
+ reader = reader_or_in_memory_fallback(reader, task);
kern_return_t err;
@@ -2292,6 +2361,7 @@
#if OS_VARIANT_NOTRESOLVED
+#if CONFIG_NANO_RESERVE_REGIONS
// Update protection for region to DEFAULT
static bool
nanov2_unprotect_region(nanov2_region_t *region)
@@ -2319,7 +2389,7 @@
return result;
}
-
+#else
// Attempts to allocate VM space for a region at a given address and returns
// whether the allocation succeeded.
static bool
@@ -2333,6 +2403,7 @@
(uint64_t)region, result, 0, 0);
return result;
}
+#endif // CONFIG_NANO_RESERVE_REGIONS
// Allocates a new region adjacent to the current one. If the allocation fails,
// keep sliding up by the size of a region until we either succeed or run out of
@@ -2424,7 +2495,8 @@
uint64_t guard = *(uint64_t *)corrupt_slot;
malloc_zone_error(MALLOC_ABORT_ON_CORRUPTION, true,
"Heap corruption detected, free list is damaged at %p\n"
- "*** Incorrect guard value: %lu\n", corrupt_slot, guard);
+ "*** Incorrect guard value: %llu\n", corrupt_slot,
+ (unsigned long long)guard);
__builtin_unreachable();
}
@@ -2489,7 +2561,7 @@
slot = old_meta_view.meta.next_slot - 1; // meta.next_slot is 1-based.
ptr = nanov2_slot_in_block_ptr(blockp, size_class, slot);
nanov2_free_slot_t *slotp = (nanov2_free_slot_t *)ptr;
- new_meta.next_slot = slot_full ? SLOT_FULL : slotp->next_slot;
+ new_meta.next_slot = slot_full ? SLOT_FULL : (uint16_t)slotp->next_slot;
}
// Write the updated meta data; try again if we raced with another thread.
@@ -2909,7 +2981,7 @@
nanov2_allocate_outlined(nanozonev2_t *nanozone, nanov2_block_meta_t **block_metapp,
size_t rounded_size, nanov2_size_class_t size_class,
int allocation_index, nanov2_block_meta_t *madvise_block_metap,
- void *corrupt_slot, bool clear)
+ void *corrupt_slot, bool clear, bool typed, malloc_type_id_t type_id)
{
void *ptr = NULL;
@@ -2928,7 +3000,13 @@
// get a new block. Before doing so, delegate to the helper allocator if
// the size class was full and has not released enough memory yet.
if (nanozone->delegate_allocations & (1 << size_class)) {
- ptr = nanozone->helper_zone->malloc(nanozone->helper_zone, rounded_size);
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ if (typed) {
+ ptr = helper_zone->malloc_type_malloc(helper_zone, rounded_size,
+ type_id);
+ } else {
+ ptr = helper_zone->malloc(helper_zone, rounded_size);
+ }
goto done;
}
@@ -2963,7 +3041,13 @@
os_atomic_or(&nanozone->delegate_allocations,
(uint16_t)(1 << size_class), relaxed);
- ptr = nanozone->helper_zone->malloc(nanozone->helper_zone, rounded_size);
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ if (typed) {
+ ptr = helper_zone->malloc_type_malloc(helper_zone, rounded_size,
+ type_id);
+ } else {
+ ptr = helper_zone->malloc(helper_zone, rounded_size);
+ }
}
done:
@@ -2990,7 +3074,7 @@
os_atomic_store(&slotp->double_free_guard, 0, relaxed);
break;
}
- // fall through
+ MALLOC_FALLTHROUGH;
case MALLOC_ZERO_ON_ALLOC:
memset(ptr, '\0', rounded_size);
break;
@@ -3096,11 +3180,9 @@
malloc_zone_t *
nanov2_create_zone(malloc_zone_t *helper_zone, unsigned debug_flags)
{
- // Note: It is important that nanov2_create_zone resets _malloc_engaged_nano
- // if it is unable to enable the nanozone (and chooses not to abort). As
- // several functions rely on _malloc_engaged_nano to determine if they
- // should manipulate the nanozone, and these should not run if we failed
- // to create the zone.
+ // Note: It is not necessary that nanov2_create_zone resets _malloc_engaged_nano
+ // if it is unable to enable the nanozone - functions that need to determine
+ // whether the nanozone is preset should test initial_nano_zone.
MALLOC_ASSERT(_malloc_engaged_nano == NANO_V2);
// Get memory for the zone and disable Nano if we fail.
@@ -3112,13 +3194,17 @@
}
// Set up the basic_zone portion of the nanozonev2 structure
- nanozone->basic_zone.version = 13;
+ nanozone->basic_zone.version = 16;
nanozone->basic_zone.size = OS_RESOLVED_VARIANT_ADDR(nanov2_size);
if (malloc_zero_policy == MALLOC_ZERO_ON_ALLOC) {
nanozone->basic_zone.malloc =
OS_RESOLVED_VARIANT_ADDR(nanov2_malloc_zero_on_alloc);
+ nanozone->basic_zone.malloc_type_malloc =
+ OS_RESOLVED_VARIANT_ADDR(nanov2_malloc_type_zero_on_alloc);
} else {
nanozone->basic_zone.malloc = OS_RESOLVED_VARIANT_ADDR(nanov2_malloc);
+ nanozone->basic_zone.malloc_type_malloc =
+ OS_RESOLVED_VARIANT_ADDR(nanov2_malloc_type);
}
nanozone->basic_zone.calloc = OS_RESOLVED_VARIANT_ADDR(nanov2_calloc);
nanozone->basic_zone.valloc = (void *)nanov2_valloc;
@@ -3135,6 +3221,13 @@
nanozone->basic_zone.claimed_address = OS_RESOLVED_VARIANT_ADDR(nanov2_claimed_address);
nanozone->basic_zone.try_free_default = OS_RESOLVED_VARIANT_ADDR(nanov2_try_free_default);
+ // zone_type == MALLOC_ZONE_TYPE_UNKNOWN
+ // No malloc_with_options
+
+ nanozone->basic_zone.malloc_type_calloc = OS_RESOLVED_VARIANT_ADDR(nanov2_calloc_type);
+ nanozone->basic_zone.malloc_type_realloc = OS_RESOLVED_VARIANT_ADDR(nanov2_realloc_type);
+ nanozone->basic_zone.malloc_type_memalign = OS_RESOLVED_VARIANT_ADDR(nanov2_memalign_type);
+
// Set these both to zero as required by CFAllocator.
nanozone->basic_zone.reserved1 = 0;
nanozone->basic_zone.reserved2 = 0;
@@ -3231,6 +3324,15 @@
// Just hand to the helper zone.
return nanozone->helper_zone->malloc(nanozone->helper_zone, size);
}
+
+MALLOC_NOEXPORT void *
+nanov2_forked_malloc_type(nanozonev2_t *nanozone, size_t size,
+ malloc_type_id_t type_id)
+{
+ // Just hand to the helper zone.
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ return helper_zone->malloc_type_malloc(helper_zone, size, type_id);
+}
#endif // OS_VARIANT_RESOLVED
#if OS_VARIANT_NOTRESOLVED
@@ -3244,11 +3346,30 @@
}
static void *
+nanov2_forked_calloc_type(nanozonev2_t *nanozone, size_t num_items, size_t size,
+ malloc_type_id_t type_id)
+{
+ // Just hand to the helper zone.
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ return helper_zone->malloc_type_calloc(helper_zone, num_items, size, type_id);
+}
+
+static void *
nanov2_forked_memalign(nanozonev2_t *nanozone, size_t alignment, size_t size)
{
// Just hand to the helper zone.
return nanozone->helper_zone->memalign(nanozone->helper_zone, alignment,
size);
+}
+
+static void *
+nanov2_forked_memalign_type(nanozonev2_t *nanozone, size_t alignment,
+ size_t size, malloc_type_id_t type_id)
+{
+ // Just hand to the helper zone.
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ return helper_zone->malloc_type_memalign(helper_zone, alignment, size,
+ type_id);
}
#endif // OS_VARIANT_NOTRESOLVED
@@ -3283,21 +3404,31 @@
nanov2_forked_free(nanozone, ptr);
}
-MALLOC_NOEXPORT void *
-nanov2_forked_realloc(nanozonev2_t *nanozone, void *ptr, size_t new_size)
+MALLOC_ALWAYS_INLINE MALLOC_INLINE
+static void *
+_nanov2_forked_realloc(nanozonev2_t *nanozone, void *ptr, size_t new_size,
+ bool typed, malloc_type_id_t type_id)
{
// could occur through malloc_zone_realloc() path
if (!ptr) {
// If ptr is a null pointer, realloc() shall be equivalent to malloc()
// for the specified size.
- return nanov2_forked_malloc(nanozone, new_size);
+ if (typed) {
+ return nanov2_forked_malloc_type(nanozone, new_size, type_id);
+ } else {
+ return nanov2_forked_malloc(nanozone, new_size);
+ }
}
size_t old_size = nanov2_pointer_size(nanozone, ptr, FALSE);
if (!old_size) {
// not-nano pointer, hand down to helper zone
malloc_zone_t *zone = (malloc_zone_t *)(nanozone->helper_zone);
- return zone->realloc(zone, ptr, new_size);
+ if (typed) {
+ return zone->malloc_type_realloc(zone, ptr, new_size, type_id);
+ } else {
+ return zone->realloc(zone, ptr, new_size);
+ }
} else {
if (!new_size) {
// If size is 0 and ptr is not a null pointer, the object pointed to
@@ -3309,8 +3440,15 @@
return nanov2_forked_malloc(nanozone, 1);
}
- void *new_ptr = nanozone->helper_zone->malloc(nanozone->helper_zone,
+ void *new_ptr;
+ if (typed) {
+ malloc_zone_t *helper_zone = nanozone->helper_zone;
+ new_ptr = helper_zone->malloc_type_malloc(helper_zone, new_size,
+ type_id);
+ } else {
+ new_ptr = nanozone->helper_zone->malloc(nanozone->helper_zone,
new_size);
+ }
if (new_ptr) {
size_t valid_size = MIN(old_size, new_size);
memcpy(new_ptr, ptr, valid_size);
@@ -3324,6 +3462,20 @@
/* NOTREACHED */
}
/* NOTREACHED */
+}
+
+MALLOC_NOEXPORT void *
+nanov2_forked_realloc(nanozonev2_t *nanozone, void *ptr, size_t new_size)
+{
+ return _nanov2_forked_realloc(nanozone, ptr, new_size, false,
+ MALLOC_TYPE_ID_NONE);
+}
+
+MALLOC_NOEXPORT void *
+nanov2_forked_realloc_type(nanozonev2_t *nanozone, void *ptr, size_t new_size,
+ malloc_type_id_t type_id)
+{
+ return _nanov2_forked_realloc(nanozone, ptr, new_size, true, type_id);
}
#endif // OS_VARIANT_RESOLVED
@@ -3394,6 +3546,13 @@
OS_RESOLVED_VARIANT_ADDR(nanov2_forked_free_definite_size);
nanozone->basic_zone.claimed_address = nanov2_forked_claimed_address;
nanozone->basic_zone.try_free_default = NULL; // Fall back to old protocol
+ nanozone->basic_zone.malloc_type_malloc =
+ OS_RESOLVED_VARIANT_ADDR(nanov2_forked_malloc_type);
+ nanozone->basic_zone.malloc_type_calloc = (void *)nanov2_forked_calloc_type;
+ nanozone->basic_zone.malloc_type_realloc =
+ OS_RESOLVED_VARIANT_ADDR(nanov2_forked_realloc_type);
+ nanozone->basic_zone.malloc_type_memalign =
+ (void *)nanov2_forked_memalign_type;
mprotect(nanozone, sizeof(nanozone->basic_zone), PROT_READ);
}