From 054bf307ee8391ffea9037761e3c9e2bc54dcbbe Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 19 Oct 2023 15:01:21 -0700 Subject: [PATCH] Avoid trampolines in emmalloc (#20496) Rather than define malloc as a small function that calls emmalloc_malloc, just make it an alias, etc. In an optimized build the small functions get inlined away, but we can save that work, and also it can have downsides (e.g. they have different function pointers, which aliases do not, see discussion in #20487). For that to work, we need to make the aliases weak, to match the fact that the trampolines were weak. --- system/lib/emmalloc.c | 87 +++++++------------------------------------ 1 file changed, 13 insertions(+), 74 deletions(-) diff --git a/system/lib/emmalloc.c b/system/lib/emmalloc.c index 61a71710fd86d..52d5a9d9349a7 100644 --- a/system/lib/emmalloc.c +++ b/system/lib/emmalloc.c @@ -71,11 +71,10 @@ static_assert((((int32_t)0x80000000U) >> 31) == -1, "This malloc implementation static_assert(alignof(max_align_t) == 8, "max_align_t must be correct"); #ifdef EMMALLOC_NO_STD_EXPORTS -#define EMMALLOC_EXPORT #define EMMALLOC_ALIAS(ALIAS, ORIGINAL) #else #define EMMALLOC_EXPORT __attribute__((weak, __visibility__("default"))) -#define EMMALLOC_ALIAS(ALIAS, ORIGINAL) extern __typeof(ORIGINAL) ALIAS __attribute__((alias(#ORIGINAL))); +#define EMMALLOC_ALIAS(ALIAS, ORIGINAL) extern __typeof(ORIGINAL) ALIAS __attribute__((weak, alias(#ORIGINAL))); #endif #define MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -826,13 +825,7 @@ void *emmalloc_memalign(size_t alignment, size_t size) return ptr; } EMMALLOC_ALIAS(emscripten_builtin_memalign, emmalloc_memalign); - -#ifndef EMMALLOC_NO_STD_EXPORTS -void * EMMALLOC_EXPORT memalign(size_t alignment, size_t size) -{ - return emmalloc_memalign(alignment, size); -} -#endif +EMMALLOC_ALIAS(memalign, emmalloc_memalign); #ifndef EMMALLOC_NO_STD_EXPORTS void * EMMALLOC_EXPORT aligned_alloc(size_t alignment, size_t size) @@ -848,14 +841,8 @@ void *emmalloc_malloc(size_t size) return emmalloc_memalign(MALLOC_ALIGNMENT, size); } EMMALLOC_ALIAS(emscripten_builtin_malloc, emmalloc_malloc); -EMMALLOC_ALIAS(__libc_malloc, emmalloc_malloc); - -#ifndef EMMALLOC_NO_STD_EXPORTS -void * EMMALLOC_EXPORT malloc(size_t size) -{ - return emmalloc_malloc(size); -} -#endif +EMMALLOC_ALIAS(__libc_malloc, emmalloc_malloc); +EMMALLOC_ALIAS(malloc, emmalloc_malloc); size_t emmalloc_usable_size(void *ptr) { @@ -876,13 +863,7 @@ size_t emmalloc_usable_size(void *ptr) return size - REGION_HEADER_SIZE; } - -#ifndef EMMALLOC_NO_STD_EXPORTS -size_t EMMALLOC_EXPORT malloc_usable_size(void *ptr) -{ - return emmalloc_usable_size(ptr); -} -#endif +EMMALLOC_ALIAS(malloc_usable_size, emmalloc_usable_size); void emmalloc_free(void *ptr) { @@ -954,14 +935,8 @@ void emmalloc_free(void *ptr) #endif } EMMALLOC_ALIAS(emscripten_builtin_free, emmalloc_free); -EMMALLOC_ALIAS(__libc_free, emmalloc_free); - -#ifndef EMMALLOC_NO_STD_EXPORTS -void EMMALLOC_EXPORT free(void *ptr) -{ - return emmalloc_free(ptr); -} -#endif +EMMALLOC_ALIAS(__libc_free, emmalloc_free); +EMMALLOC_ALIAS(free, emmalloc_free); // Can be called to attempt to increase or decrease the size of the given region // to a new size (in-place). Returns 1 if resize succeeds, and 0 on failure. @@ -1089,13 +1064,7 @@ void *emmalloc_aligned_realloc(void *ptr, size_t alignment, size_t size) // null pointer is returned. return newptr; } - -#ifndef EMMALLOC_NO_STD_EXPORTS -void * EMMALLOC_EXPORT aligned_realloc(void *ptr, size_t alignment, size_t size) -{ - return emmalloc_aligned_realloc(ptr, alignment, size); -} -#endif +EMMALLOC_ALIAS(aligned_realloc, emmalloc_aligned_realloc); // realloc_try() is like realloc(), but only attempts to try to resize the existing memory // area. If resizing the existing memory area fails, then realloc_try() will return 0 @@ -1180,13 +1149,7 @@ void *emmalloc_realloc(void *ptr, size_t size) return emmalloc_aligned_realloc(ptr, MALLOC_ALIGNMENT, size); } EMMALLOC_ALIAS(__libc_realloc, emmalloc_realloc); - -#ifndef EMMALLOC_NO_STD_EXPORTS -void * EMMALLOC_EXPORT realloc(void *ptr, size_t size) -{ - return emmalloc_realloc(ptr, size); -} -#endif +EMMALLOC_ALIAS(realloc, emmalloc_realloc); // realloc_uninitialized() is like realloc(), but old memory contents // will be undefined after reallocation. (old memory is not preserved in any case) @@ -1203,13 +1166,7 @@ int emmalloc_posix_memalign(void **memptr, size_t alignment, size_t size) *memptr = emmalloc_memalign(alignment, size); return *memptr ? 0 : 12/*ENOMEM*/; } - -#ifndef EMMALLOC_NO_STD_EXPORTS -int EMMALLOC_EXPORT posix_memalign(void **memptr, size_t alignment, size_t size) -{ - return emmalloc_posix_memalign(memptr, alignment, size); -} -#endif +EMMALLOC_ALIAS(posix_memalign, emmalloc_posix_memalign); void *emmalloc_calloc(size_t num, size_t size) { @@ -1220,13 +1177,7 @@ void *emmalloc_calloc(size_t num, size_t size) return ptr; } EMMALLOC_ALIAS(__libc_calloc, emmalloc_calloc); - -#ifndef EMMALLOC_NO_STD_EXPORTS -void * EMMALLOC_EXPORT calloc(size_t num, size_t size) -{ - return emmalloc_calloc(num, size); -} -#endif +EMMALLOC_ALIAS(calloc, emmalloc_calloc); static int count_linked_list_size(Region *list) { @@ -1316,13 +1267,7 @@ struct mallinfo emmalloc_mallinfo() MALLOC_RELEASE(); return info; } - -#ifndef EMMALLOC_NO_STD_EXPORTS -struct mallinfo EMMALLOC_EXPORT mallinfo() -{ - return emmalloc_mallinfo(); -} -#endif +EMMALLOC_ALIAS(mallinfo, emmalloc_mallinfo); // Note! This function is not fully multithreading safe: while this function is running, other threads should not be // allowed to call sbrk()! @@ -1384,13 +1329,7 @@ int emmalloc_trim(size_t pad) MALLOC_RELEASE(); return success; } - -#ifndef EMMALLOC_NO_STD_EXPORTS -int EMMALLOC_EXPORT malloc_trim(size_t pad) -{ - return emmalloc_trim(pad); -} -#endif +EMMALLOC_ALIAS(malloc_trim, emmalloc_trim) size_t emmalloc_dynamic_heap_size() {