Skip to content

Commit

Permalink
Avoid trampolines in emmalloc (#20496)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kripken authored Oct 19, 2023
1 parent ebfea7a commit 054bf30
Showing 1 changed file with 13 additions and 74 deletions.
87 changes: 13 additions & 74 deletions system/lib/emmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand All @@ -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)
{
Expand All @@ -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)
{
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)
{
Expand All @@ -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)
{
Expand Down Expand Up @@ -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()!
Expand Down Expand Up @@ -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()
{
Expand Down

0 comments on commit 054bf30

Please sign in to comment.