bugfix: memory limit was not respected; removed heap exports
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 17 Nov 2023 18:41:30 +0000 (12:41 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 17 Nov 2023 18:41:30 +0000 (12:41 -0600)
compiler/src/wasm_runtime.c
core/alloc/heap.onyx
core/onyx/cbindgen.onyx
core/onyx/cptr.onyx
runtime/build.sh
shared/include/onyx_library.h

index 9a78ce2f954affa2f526dcd0ff12d6740777815b..dc3f491ecf6b13e5fb1584e31c8aaddc93485434 100644 (file)
@@ -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);
                 }
index cb3615a18348adb055126d1c6dedb897f0428051..1c12f67b604abb268ca71cbe931bf6059aac03a4 100644 (file)
@@ -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 {
index d381ecfeca405a28115097a60f19df1f53f67e61..c1b9ad0e5734fb130cd578d2620c0eb00a7a39a8 100644 (file)
@@ -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");
index 49bd8866b13f52270083d4806170fafd561ce0af..c126a0eb38674e49a2d8f45701ae3e5733423e21 100644 (file)
@@ -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);
         }
     }
 
index 263ccffc2cbf4b4c567c79e92f6edd0459823448..a5bd95c5358b9feec2f3ea4c158d7c6b48f945c9 100755 (executable)
@@ -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
index 41789a7a08ee395c5dd243b0957225fbb4a93d60..e90642170fafef99041985ea46141571815472cf 100644 (file)
@@ -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