From c85c8538d3001b002ba4564bb8cb6b5170194874 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 5 Dec 2024 13:52:38 -0800 Subject: [PATCH] Add emscripten_builtin_realloc Also improve testing for allocator wrapping. Fixes: #23080 --- system/include/emscripten/heap.h | 1 + system/lib/dlmalloc.c | 1 + system/lib/emmalloc.c | 1 + system/lib/mimalloc/src/alloc-override.c | 1 + test/core/test_wrap_malloc.c | 15 ++++++++++++++- test/test_core.py | 10 ++++++++-- tools/system_libs.py | 2 +- 7 files changed, 27 insertions(+), 4 deletions(-) diff --git a/system/include/emscripten/heap.h b/system/include/emscripten/heap.h index 0bd56cdbb32db..26041d6be2be2 100644 --- a/system/include/emscripten/heap.h +++ b/system/include/emscripten/heap.h @@ -46,6 +46,7 @@ size_t emscripten_get_heap_max(void); // dlmalloc and emmalloc. void *emscripten_builtin_memalign(size_t alignment, size_t size); void *emscripten_builtin_malloc(size_t size); +void *emscripten_builtin_realloc(void *ptr, size_t size); void *emscripten_builtin_calloc(size_t nmemb, size_t size); void emscripten_builtin_free(void *ptr); diff --git a/system/lib/dlmalloc.c b/system/lib/dlmalloc.c index f55ff649cfefb..5c4de3fe03c89 100644 --- a/system/lib/dlmalloc.c +++ b/system/lib/dlmalloc.c @@ -6082,6 +6082,7 @@ int mspace_mallopt(int param_number, int value) { // This allows an easy mechanism for hooking into memory allocation. #if defined(__EMSCRIPTEN__) && !ONLY_MSPACES extern __typeof(malloc) emscripten_builtin_malloc __attribute__((alias("dlmalloc"))); +extern __typeof(realloc) emscripten_builtin_realloc __attribute__((alias("dlrealloc"))); extern __typeof(calloc) emscripten_builtin_calloc __attribute__((alias("dlcalloc"))); extern __typeof(free) emscripten_builtin_free __attribute__((alias("dlfree"))); extern __typeof(memalign) emscripten_builtin_memalign __attribute__((alias("dlmemalign"))); diff --git a/system/lib/emmalloc.c b/system/lib/emmalloc.c index 940335c37cf5e..6c794b3f3e880 100644 --- a/system/lib/emmalloc.c +++ b/system/lib/emmalloc.c @@ -1113,6 +1113,7 @@ void *emmalloc_aligned_realloc_uninitialized(void *ptr, size_t alignment, size_t void *emmalloc_realloc(void *ptr, size_t size) { return emmalloc_aligned_realloc(ptr, MALLOC_ALIGNMENT, size); } +EMMALLOC_ALIAS(emscripten_builtin_realloc, emmalloc_realloc); EMMALLOC_ALIAS(__libc_realloc, emmalloc_realloc); EMMALLOC_ALIAS(realloc, emmalloc_realloc); diff --git a/system/lib/mimalloc/src/alloc-override.c b/system/lib/mimalloc/src/alloc-override.c index e326ea7b4b051..ded7a101de9f2 100644 --- a/system/lib/mimalloc/src/alloc-override.c +++ b/system/lib/mimalloc/src/alloc-override.c @@ -298,6 +298,7 @@ mi_decl_weak int reallocarr(void* p, size_t count, size_t size) { return mi_r #ifdef __EMSCRIPTEN__ // emscripten adds some more on top of WASI void* emscripten_builtin_malloc(size_t size) MI_FORWARD1(mi_malloc, size) + void* emscripten_builtin_realloc(void* p, size_t size) MI_FORWARD2(mi_realloc, p, size) void* emscripten_builtin_free(void* p) MI_FORWARD0(mi_free, p) void* emscripten_builtin_memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); } void* emscripten_builtin_calloc(size_t nmemb, size_t size) MI_FORWARD2(mi_calloc, nmemb, size) diff --git a/test/core/test_wrap_malloc.c b/test/core/test_wrap_malloc.c index 97d3fd2ec1fe9..be58ffa2ae917 100644 --- a/test/core/test_wrap_malloc.c +++ b/test/core/test_wrap_malloc.c @@ -11,6 +11,7 @@ static int totalAllocs; static int totalFrees; +static int totalReallocs; void *malloc(size_t size) { ++totalAllocs; @@ -19,6 +20,13 @@ void *malloc(size_t size) { return ptr; } +void *realloc(void* ptr, size_t size) { + ++totalReallocs; + ptr = emscripten_builtin_realloc(ptr, size); + emscripten_console_logf("Reallocated %zu bytes, got %p. %d pointers re-allocated total.", size, ptr, totalReallocs); + return ptr; +} + void free(void *ptr) { ++totalFrees; emscripten_builtin_free(ptr); @@ -39,9 +47,14 @@ int main() { free(ptr); } + void* ptr = malloc(50); + ptr = realloc(ptr, 50); + emscripten_console_logf("totalAllocs: %d", totalAllocs); emscripten_console_logf("totalFrees: %d", totalFrees); - assert(totalAllocs == 20); + emscripten_console_logf("totalReallocs: %d", totalReallocs); + assert(totalAllocs == 21); + assert(totalReallocs == 1); assert(totalFrees == 20); emscripten_console_logf("OK."); return 0; diff --git a/test/test_core.py b/test/test_core.py index 2163d969cffc1..1695fce9ff840 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -8594,8 +8594,14 @@ def test_mallinfo(self): @no_asan('cannot replace malloc/free with ASan') @no_lsan('cannot replace malloc/free with LSan') - def test_wrap_malloc(self): - self.do_runf('core/test_wrap_malloc.c', 'OK.') + @parameterized({ + '': ([],), + 'emmalloc': (['-sMALLOC=emmalloc'],), + # FIXME(https://github.com/emscripten-core/emscripten/issues/23090) + # 'mimalloc': (['-sMALLOC=mimalloc'],), + }) + def test_wrap_malloc(self, args): + self.do_runf('core/test_wrap_malloc.c', 'OK.', emcc_args=args) def test_environment(self): self.set_setting('ASSERTIONS') diff --git a/tools/system_libs.py b/tools/system_libs.py index 582d19ba21148..e6bbf1c3435b1 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -1721,7 +1721,7 @@ class libmalloc(MTLibrary): def __init__(self, **kwargs): self.malloc = kwargs.pop('malloc') if self.malloc not in ('dlmalloc', 'emmalloc', 'emmalloc-debug', 'emmalloc-memvalidate', 'emmalloc-verbose', 'emmalloc-memvalidate-verbose', 'mimalloc', 'none'): - raise Exception('malloc must be one of "emmalloc[-debug|-memvalidate][-verbose]", "dlmalloc" or "none", see settings.js') + raise Exception('malloc must be one of "emmalloc[-debug|-memvalidate][-verbose]", "mimalloc", "dlmalloc" or "none", see settings.js') self.is_tracing = kwargs.pop('is_tracing') self.memvalidate = kwargs.pop('memvalidate')