update wasm support with emscripten compilation; now using sbrk instead of wasm_memory_grow

This commit is contained in:
Daan Leijen 2021-10-01 15:05:01 -07:00
parent 076f815cec
commit 679aad0659
4 changed files with 56 additions and 9 deletions

View file

@ -32,6 +32,10 @@ terms of the MIT license. A copy of the license can be found in the file
#define mi_decl_cache_align
#endif
#if defined(__EMSCRIPTEN__) && !defined(__wasi__)
#define __wasi__
#endif
// "options.c"
void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message);
void _mi_fprintf(mi_output_fun* out, void* arg, const char* fmt, ...);
@ -242,10 +246,10 @@ static inline bool mi_malloc_satisfies_alignment(size_t alignment, size_t size)
#undef _CLOCK_T
#endif
static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) {
#if (SIZE_MAX == UINT_MAX)
return __builtin_umul_overflow(count, size, total);
#elif (SIZE_MAX == ULONG_MAX)
#if (SIZE_MAX == ULONG_MAX)
return __builtin_umull_overflow(count, size, total);
#elif (SIZE_MAX == UINT_MAX)
return __builtin_umul_overflow(count, size, total);
#else
return __builtin_umulll_overflow(count, size, total);
#endif

View file

@ -26,11 +26,14 @@ terms of the MIT license. A copy of the license can be found in the file
#pragma warning(disable:4996) // strerror
#endif
#if defined(__wasi__)
#define MI_USE_SBRK
#endif
#if defined(_WIN32)
#include <windows.h>
#elif defined(__wasi__)
// stdlib.h is all we need, and has already been included in mimalloc.h
#include <unistd.h> // sbrk
#else
#include <sys/mman.h> // mmap
#include <unistd.h> // sysconf
@ -99,11 +102,13 @@ size_t _mi_os_large_page_size() {
return (large_os_page_size != 0 ? large_os_page_size : _mi_os_page_size());
}
#if !defined(MI_USE_SBRK) && !defined(__wasi__)
static bool use_large_os_page(size_t size, size_t alignment) {
// if we have access, check the size and alignment requirements
if (large_os_page_size == 0 || !mi_option_is_enabled(mi_option_large_os_pages)) return false;
return ((size % large_os_page_size) == 0 && (alignment % large_os_page_size) == 0);
}
#endif
// round to a good OS allocation size (bounded by max 12.5% waste)
size_t _mi_os_good_alloc_size(size_t size) {
@ -236,8 +241,8 @@ static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats
bool err = false;
#if defined(_WIN32)
err = (VirtualFree(addr, 0, MEM_RELEASE) == 0);
#elif defined(__wasi__)
err = 0; // WebAssembly's heap cannot be shrunk
#elif defined(MI_USE_SBRK)
err = 0; // sbrk heap cannot be shrunk
#else
err = (munmap(addr, size) == -1);
#endif
@ -252,7 +257,9 @@ static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats
}
}
#if !defined(MI_USE_SBRK) && !defined(__wasi__)
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size);
#endif
#ifdef _WIN32
static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment, DWORD flags) {
@ -318,7 +325,32 @@ static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment,
return p;
}
#elif defined(__wasi__)
#elif defined(MI_USE_SBRK)
#define MI_SBRK_FAIL ((void*)(-1))
static void* mi_sbrk_heap_grow(size_t size, size_t try_alignment) {
void* pbase0 = sbrk(0);
if (pbase0 == MI_SBRK_FAIL) {
_mi_warning_message("unable to allocate sbrk() OS memory (%zu bytes)\n", size);
errno = ENOMEM;
return NULL;
}
uintptr_t base = (uintptr_t)pbase0;
uintptr_t aligned_base = _mi_align_up(base, (uintptr_t) try_alignment);
size_t alloc_size = _mi_align_up( aligned_base - base + size, _mi_os_page_size());
mi_assert(alloc_size >= size && (alloc_size % _mi_os_page_size()) == 0);
if (alloc_size < size) return NULL;
void* pbase1 = sbrk(alloc_size);
if (pbase1 == MI_SBRK_FAIL) {
_mi_warning_message("unable to allocate sbrk() OS memory (%zu bytes, %zu requested)\n", size, alloc_size);
errno = ENOMEM;
return NULL;
}
mi_assert(pbase0 == pbase1);
return (void*)aligned_base;
}
#elif defined(__wasi__)
// currently unused as we use sbrk() on wasm
static void* mi_wasm_heap_grow(size_t size, size_t try_alignment) {
uintptr_t base = __builtin_wasm_memory_size(0) * _mi_os_page_size();
uintptr_t aligned_base = _mi_align_up(base, (uintptr_t) try_alignment);
@ -326,11 +358,13 @@ static void* mi_wasm_heap_grow(size_t size, size_t try_alignment) {
mi_assert(alloc_size >= size && (alloc_size % _mi_os_page_size()) == 0);
if (alloc_size < size) return NULL;
if (__builtin_wasm_memory_grow(0, alloc_size / _mi_os_page_size()) == SIZE_MAX) {
_mi_warning_message("unable to allocate wasm_memory_grow() OS memory (%zu bytes, %zu requested)\n", size, alloc_size);
errno = ENOMEM;
return NULL;
}
return (void*)aligned_base;
}
#else
#define MI_OS_USE_MMAP
static void* mi_unix_mmapx(void* addr, size_t size, size_t try_alignment, int protect_flags, int flags, int fd) {
@ -506,6 +540,8 @@ static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size)
if (hint%try_alignment != 0) return NULL;
return (void*)hint;
}
#elif defined(__wasi__) || defined(MI_USE_SBRK)
// no need for mi_os_get_aligned_hint
#else
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
UNUSED(try_alignment); UNUSED(size);
@ -536,7 +572,12 @@ static void* mi_os_mem_alloc(size_t size, size_t try_alignment, bool commit, boo
int flags = MEM_RESERVE;
if (commit) flags |= MEM_COMMIT;
p = mi_win_virtual_alloc(NULL, size, try_alignment, flags, false, allow_large, is_large);
#elif defined(MI_USE_SBRK)
KK_UNUSED(allow_large);
*is_large = false;
p = mi_sbrk_heap_grow(size, try_alignment);
#elif defined(__wasi__)
KK_UNUSED(allow_large);
*is_large = false;
p = mi_wasm_heap_grow(size, try_alignment);
#else

View file

@ -188,7 +188,7 @@ static bool os_random_buf(void* buf, size_t buf_len) {
#elif defined(ANDROID) || defined(XP_DARWIN) || defined(__APPLE__) || defined(__DragonFly__) || \
defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
defined(__sun) || defined(__wasi__)
defined(__sun) // todo: what to use with __wasi__?
#include <stdlib.h>
static bool os_random_buf(void* buf, size_t buf_len) {
arc4random_buf(buf, buf_len);
@ -280,7 +280,9 @@ void _mi_random_init(mi_random_ctx_t* ctx) {
if (!os_random_buf(key, sizeof(key))) {
// if we fail to get random data from the OS, we fall back to a
// weak random source based on the current time
#if !defined(__wasi__)
_mi_warning_message("unable to use secure randomness\n");
#endif
uintptr_t x = _os_random_weak(0);
for (size_t i = 0; i < 8; i++) { // key is eight 32-bit words.
x = _mi_random_shuffle(x);

View file

@ -479,7 +479,7 @@ static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msec
*page_faults = (size_t)info.PageFaultCount;
}
#elif defined(__unix__) || defined(__unix) || defined(unix) || defined(__APPLE__) || defined(__HAIKU__)
#elif !defined(__wasi__) && (defined(__unix__) || defined(__unix) || defined(unix) || defined(__APPLE__) || defined(__HAIKU__))
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>