From 6f6175f9700c8db2c2d7b8af3e095c240d40af92 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Fri, 17 Nov 2023 12:41:30 -0600 Subject: [PATCH] bugfix: memory limit was not respected; removed heap exports --- compiler/src/wasm_runtime.c | 6 ++- core/alloc/heap.onyx | 12 +++-- core/onyx/cbindgen.onyx | 31 +++++++---- core/onyx/cptr.onyx | 4 ++ runtime/build.sh | 11 +++- shared/include/onyx_library.h | 98 +++++++++++++++++++++-------------- 6 files changed, 104 insertions(+), 58 deletions(-) diff --git a/compiler/src/wasm_runtime.c b/compiler/src/wasm_runtime.c index 9a78ce2f..dc3f491e 100644 --- a/compiler/src/wasm_runtime.c +++ b/compiler/src/wasm_runtime.c @@ -463,7 +463,11 @@ static b32 link_wasm_imports( if (wasm_name_equals_string(module_name, "onyx")) { if (wasm_name_equals_string(import_name, "memory")) { if (wasm_memory == NULL) { - wasm_limits_t limits = { 1024, 65536 }; + const wasm_externtype_t *memory_extern_type = wasm_importtype_type(module_imports.data[i]); + const wasm_memorytype_t *expected_memory_type = wasm_externtype_as_memorytype_const(memory_extern_type); + const wasm_limits_t *memory_limits = wasm_memorytype_limits(expected_memory_type); + + wasm_limits_t limits = { memory_limits->min, memory_limits->max }; wasm_memorytype_t* memory_type = wasm_memorytype_new(&limits); wasm_memory = wasm_memory_new(wasm_store, memory_type); } diff --git a/core/alloc/heap.onyx b/core/alloc/heap.onyx index cb3615a1..1c12f67b 100644 --- a/core/alloc/heap.onyx +++ b/core/alloc/heap.onyx @@ -52,11 +52,13 @@ get_freed_size :: () => { return total; } -#if !#defined(runtime.vars.Dont_Export_Heap_Functions) { - // heap_alloc is not exported because you can use __heap_resize(NULL, size) - #export "__heap_resize" heap_resize - #export "__heap_free" heap_free -} +// See the comment in onyx_library.h as to why these don't exist anymore. +// +// #if !#defined(runtime.vars.Dont_Export_Heap_Functions) { +// // heap_alloc is not exported because you can use __heap_resize(NULL, size) +// #export "__heap_resize" heap_resize +// #export "__heap_free" heap_free +// } #local { use core.intrinsics.wasm { diff --git a/core/onyx/cbindgen.onyx b/core/onyx/cbindgen.onyx index d381ecfe..c1b9ad0e 100644 --- a/core/onyx/cbindgen.onyx +++ b/core/onyx/cbindgen.onyx @@ -51,11 +51,16 @@ customize :: struct { use core {package, *} use simd {*} -#if runtime.compiler_os == .Linux { - #if #defined (runtime.vars.CC) { - Linux_Compiler :: runtime.vars.CC - } else { - Linux_Compiler :: "/usr/bin/gcc" +#if #defined (runtime.vars.CC) { + #local Compiler :: runtime.vars.CC +} else { + #if runtime.compiler_os == .Linux { + #local Compiler :: "/usr/bin/gcc" + #local Library_Suffix :: "so" + } + #if runtime.compiler_os == .MacOS { + #local Compiler :: "clang" + #local Library_Suffix :: "dylib" } } @@ -130,14 +135,19 @@ compile_c_file :: ( includes: [] str = .[], libraries: [] str = .[], flags := "") -> bool { - #if runtime.compiler_os == .Linux { + #if runtime.compiler_os == .Linux || runtime.compiler_os == .MacOS { args: [..] str; args << "-shared"; args << "-fPIC"; args << path; - args << "-I"; - args << "/usr/share/onyx/include"; + onyx_path := os.env("ONYX_PATH"); + if !onyx_path { + logf(.Warning, "ONYX_PATH environment variable was not declared. This likely won't compile."); + } else { + args << "-I"; + args << tprintf("{}/include", onyx_path->unwrap()); + } for includes { args << "-I"; @@ -149,13 +159,13 @@ compile_c_file :: ( } args << "-o"; - args << tprintf("{}.so", dest); + args << tprintf("{}.{}", dest, Library_Suffix); for libraries { args << aprintf("-l{}", it); } - proc := os.process_spawn(Linux_Compiler, args); + proc := os.process_spawn(Compiler, args); defer os.process_destroy(&proc); proc_reader := io.reader_make(&proc); @@ -177,7 +187,6 @@ compile_c_file :: ( } #local { - write_file_introduction :: (writer: &io.Writer, preamble: [] str, name: str) { io.write_format(writer, "//\n"); io.write_format(writer, "// THIS FILE WAS AUTOMATICALLY GENERATED.\n"); diff --git a/core/onyx/cptr.onyx b/core/onyx/cptr.onyx index 49bd8866..c126a0eb 100644 --- a/core/onyx/cptr.onyx +++ b/core/onyx/cptr.onyx @@ -38,6 +38,10 @@ cptr :: struct (T: type_expr) { buf: [sizeof T] u8; __cptr_read(this.data, ~~buf, sizeof T); return *cast(&T) buf; + }, + + (this: cptr($T), buffer: [] u8) { + __cptr_read(this.data, ~~buffer.data, buffer.length); } } diff --git a/runtime/build.sh b/runtime/build.sh index 263ccffc..a5bd95c5 100755 --- a/runtime/build.sh +++ b/runtime/build.sh @@ -1,8 +1,15 @@ #!/bin/sh -echo "Compiling onyx_runtime.so" +case "$(uname)" in + Linux) suffix='so' ;; + *BSD) suffix='so' ;; + Darwin) suffix='dylib' ;; + *) suffix='dll' ;; +esac + +echo "Compiling onyx_runtime.$suffix" $ONYX_CC -shared -fpic -w -O2 \ - -o onyx_runtime.so \ + -o onyx_runtime.$suffix \ -I ../shared/include -I ../compiler/include \ ./onyx_runtime.c \ -lpthread diff --git a/shared/include/onyx_library.h b/shared/include/onyx_library.h index 41789a7a..e9064217 100644 --- a/shared/include/onyx_library.h +++ b/shared/include/onyx_library.h @@ -115,44 +115,64 @@ typedef struct WasmFuncDefinition { #define ONYX_UNPTR(p) ((int) (p != NULL ? ((char *) p - runtime->wasm_memory_data(runtime->wasm_memory)) : 0)) -#ifdef ONYX_HEAP_FUNCTIONS - -static wasm_func_t* __onyx_heap_resize_function = NULL; -static void *__onyx_heap_resize(void* ptr, int size) { - if (__onyx_heap_resize_function == NULL) { - wasm_extern_t *__extern = runtime->wasm_extern_lookup_by_name(runtime->wasm_module, runtime->wasm_instance, "__heap_resize"); - __onyx_heap_resize_function = runtime->wasm_extern_as_func(__extern); - } - - int onyx_ptr = ONYX_UNPTR(ptr); - - wasm_val_t args[] = { WASM_I32_VAL(onyx_ptr), WASM_I32_VAL(size) }; - wasm_val_t results[1]; - wasm_val_vec_t args_arr = WASM_ARRAY_VEC(args); - wasm_val_vec_t results_arr = WASM_ARRAY_VEC(results); - - runtime->wasm_func_call(__onyx_heap_resize_function, &args_arr, &results_arr); - return ONYX_PTR(results[0].of.i32); -} - -static wasm_func_t* __onyx_heap_free_function = NULL; -static void __onyx_heap_free(void *ptr) { - if (__onyx_heap_free_function == NULL) { - wasm_extern_t *__extern = runtime->wasm_extern_lookup_by_name(runtime->wasm_module, runtime->wasm_instance, "__heap_free"); - __onyx_heap_free_function = runtime->wasm_extern_as_func(__extern); - } - - if (ptr == NULL) return; - int onyx_ptr = ONYX_UNPTR(ptr); - - wasm_val_t args[] = { WASM_I32_VAL(onyx_ptr) }; - wasm_val_vec_t results = {0,0}; - wasm_val_vec_t args_arr = WASM_ARRAY_VEC(args); - - runtime->wasm_func_call(__onyx_heap_free_function, &args_arr, &results); -} - - -#endif +// +// Below are definitions that allow you to use the heap_resize and heap_free +// functions to allocate and free memory inside Onyx's memory space, but from +// a C-library. These functions were very useful, but they had some nasty +// problems that cannot be easily addressed. +// +// The largest problem was that the WASM embedder made no guarantees about how +// the underlying memory used would be positioned or when it could relocate. +// If a C-library were to invoke heap_resize, and that resize caused the +// memory_grow intrinsic to be invoked, the embedder could move the memory to +// a new address. This would mean that ALL existing pointers into Onyx's memory +// given to the C-library would be invalidated, almost always causing a segfault. +// +// There isn't a great way around this, since the idea of wrapping a C library +// isn't necessarily supported by WASM at any level. The current work around +// is to have the C library allocate using malloc(), then return the pointer +// as a cptr(T), and then have Onyx copy that to a new buffer, and immediately +// free the cptr(T), generally using a destructor of some kind from the C library. +// + +// #ifdef ONYX_HEAP_FUNCTIONS + +// static wasm_func_t* __onyx_heap_resize_function = NULL; +// static void *__onyx_heap_resize(void* ptr, int size) { +// if (__onyx_heap_resize_function == NULL) { +// wasm_extern_t *__extern = runtime->wasm_extern_lookup_by_name(runtime->wasm_module, runtime->wasm_instance, "__heap_resize"); +// __onyx_heap_resize_function = runtime->wasm_extern_as_func(__extern); +// } + +// int onyx_ptr = ONYX_UNPTR(ptr); + +// wasm_val_t args[] = { WASM_I32_VAL(onyx_ptr), WASM_I32_VAL(size) }; +// wasm_val_t results[1]; +// wasm_val_vec_t args_arr = WASM_ARRAY_VEC(args); +// wasm_val_vec_t results_arr = WASM_ARRAY_VEC(results); + +// runtime->wasm_func_call(__onyx_heap_resize_function, &args_arr, &results_arr); +// return ONYX_PTR(results[0].of.i32); +// } + +// static wasm_func_t* __onyx_heap_free_function = NULL; +// static void __onyx_heap_free(void *ptr) { +// if (__onyx_heap_free_function == NULL) { +// wasm_extern_t *__extern = runtime->wasm_extern_lookup_by_name(runtime->wasm_module, runtime->wasm_instance, "__heap_free"); +// __onyx_heap_free_function = runtime->wasm_extern_as_func(__extern); +// } + +// if (ptr == NULL) return; +// int onyx_ptr = ONYX_UNPTR(ptr); + +// wasm_val_t args[] = { WASM_I32_VAL(onyx_ptr) }; +// wasm_val_vec_t results = {0,0}; +// wasm_val_vec_t args_arr = WASM_ARRAY_VEC(args); + +// runtime->wasm_func_call(__onyx_heap_free_function, &args_arr, &results); +// } + + +// #endif #endif -- 2.25.1