Просмотр исходного кода

Allow executing malloc/free from native in memory64 mode (#3315)

Marcin Kolny 1 год назад
Родитель
Сommit
fd7f738451

+ 28 - 15
core/iwasm/interpreter/wasm_loader.c

@@ -36,6 +36,21 @@
 #define TEMPLATE_READ_VALUE(Type, p) \
 #define TEMPLATE_READ_VALUE(Type, p) \
     (p += sizeof(Type), *(Type *)(p - sizeof(Type)))
     (p += sizeof(Type), *(Type *)(p - sizeof(Type)))
 
 
+#if WASM_ENABLE_MEMORY64 != 0
+static bool
+has_module_memory64(WASMModule *module)
+{
+    /* TODO: multi-memories for now assuming the memory idx type is consistent
+     * across multi-memories */
+    if (module->import_memory_count > 0)
+        return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG);
+    else if (module->memory_count > 0)
+        return !!(module->memories[0].flags & MEMORY64_FLAG);
+
+    return false;
+}
+#endif
+
 static void
 static void
 set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
 set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
 {
 {
@@ -5659,6 +5674,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
     uint32 aux_data_end_global_index = (uint32)-1;
     uint32 aux_data_end_global_index = (uint32)-1;
     uint32 aux_heap_base_global_index = (uint32)-1;
     uint32 aux_heap_base_global_index = (uint32)-1;
     WASMFuncType *func_type;
     WASMFuncType *func_type;
+    uint8 malloc_free_io_type = VALUE_TYPE_I32;
 
 
     /* Find code and function sections if have */
     /* Find code and function sections if have */
     while (section) {
     while (section) {
@@ -5887,6 +5903,10 @@ load_from_sections(WASMModule *module, WASMSection *sections,
     module->retain_function = (uint32)-1;
     module->retain_function = (uint32)-1;
 
 
     /* Resolve malloc/free function exported by wasm module */
     /* Resolve malloc/free function exported by wasm module */
+#if WASM_ENABLE_MEMORY64 != 0
+    if (has_module_memory64(module))
+        malloc_free_io_type = VALUE_TYPE_I64;
+#endif
     export = module->exports;
     export = module->exports;
     for (i = 0; i < module->export_count; i++, export ++) {
     for (i = 0; i < module->export_count; i++, export ++) {
         if (export->kind == EXPORT_KIND_FUNC) {
         if (export->kind == EXPORT_KIND_FUNC) {
@@ -5895,8 +5915,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 func_index = export->index - module->import_function_count;
                 func_index = export->index - module->import_function_count;
                 func_type = module->functions[func_index]->func_type;
                 func_type = module->functions[func_index]->func_type;
                 if (func_type->param_count == 1 && func_type->result_count == 1
                 if (func_type->param_count == 1 && func_type->result_count == 1
-                    && func_type->types[0] == VALUE_TYPE_I32
-                    && func_type->types[1] == VALUE_TYPE_I32) {
+                    && func_type->types[0] == malloc_free_io_type
+                    && func_type->types[1] == malloc_free_io_type) {
                     bh_assert(module->malloc_function == (uint32)-1);
                     bh_assert(module->malloc_function == (uint32)-1);
                     module->malloc_function = export->index;
                     module->malloc_function = export->index;
                     LOG_VERBOSE("Found malloc function, name: %s, index: %u",
                     LOG_VERBOSE("Found malloc function, name: %s, index: %u",
@@ -5909,9 +5929,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 func_index = export->index - module->import_function_count;
                 func_index = export->index - module->import_function_count;
                 func_type = module->functions[func_index]->func_type;
                 func_type = module->functions[func_index]->func_type;
                 if (func_type->param_count == 2 && func_type->result_count == 1
                 if (func_type->param_count == 2 && func_type->result_count == 1
-                    && func_type->types[0] == VALUE_TYPE_I32
+                    && func_type->types[0] == malloc_free_io_type
                     && func_type->types[1] == VALUE_TYPE_I32
                     && func_type->types[1] == VALUE_TYPE_I32
-                    && func_type->types[2] == VALUE_TYPE_I32) {
+                    && func_type->types[2] == malloc_free_io_type) {
                     uint32 j;
                     uint32 j;
                     WASMExport *export_tmp;
                     WASMExport *export_tmp;
 
 
@@ -5935,8 +5955,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                                 module->functions[func_index]->func_type;
                                 module->functions[func_index]->func_type;
                             if (func_type->param_count == 1
                             if (func_type->param_count == 1
                                 && func_type->result_count == 1
                                 && func_type->result_count == 1
-                                && func_type->types[0] == VALUE_TYPE_I32
-                                && func_type->types[1] == VALUE_TYPE_I32) {
+                                && func_type->types[0] == malloc_free_io_type
+                                && func_type->types[1] == malloc_free_io_type) {
                                 bh_assert(module->retain_function
                                 bh_assert(module->retain_function
                                           == (uint32)-1);
                                           == (uint32)-1);
                                 module->retain_function = export_tmp->index;
                                 module->retain_function = export_tmp->index;
@@ -5962,7 +5982,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 func_index = export->index - module->import_function_count;
                 func_index = export->index - module->import_function_count;
                 func_type = module->functions[func_index]->func_type;
                 func_type = module->functions[func_index]->func_type;
                 if (func_type->param_count == 1 && func_type->result_count == 0
                 if (func_type->param_count == 1 && func_type->result_count == 0
-                    && func_type->types[0] == VALUE_TYPE_I32) {
+                    && func_type->types[0] == malloc_free_io_type) {
                     bh_assert(module->free_function == (uint32)-1);
                     bh_assert(module->free_function == (uint32)-1);
                     module->free_function = export->index;
                     module->free_function = export->index;
                     LOG_VERBOSE("Found free function, name: %s, index: %u",
                     LOG_VERBOSE("Found free function, name: %s, index: %u",
@@ -10737,14 +10757,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
            func->param_cell_num, func->local_cell_num, func->ret_cell_num);
            func->param_cell_num, func->local_cell_num, func->ret_cell_num);
 #endif
 #endif
 #if WASM_ENABLE_MEMORY64 != 0
 #if WASM_ENABLE_MEMORY64 != 0
-    bool is_memory64 = false;
-    /* TODO: multi-memories for now assuming the memory idx type is consistent
-     * across multi-memories */
-    if (module->import_memory_count > 0)
-        is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG;
-    else if (module->memory_count > 0)
-        is_memory64 = module->memories[0].flags & MEMORY64_FLAG;
-
+    bool is_memory64 = has_module_memory64(module);
     mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
     mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
 #else
 #else
     mem_offset_type = VALUE_TYPE_I32;
     mem_offset_type = VALUE_TYPE_I32;

+ 28 - 15
core/iwasm/interpreter/wasm_mini_loader.c

@@ -25,6 +25,21 @@
 #define TEMPLATE_READ_VALUE(Type, p) \
 #define TEMPLATE_READ_VALUE(Type, p) \
     (p += sizeof(Type), *(Type *)(p - sizeof(Type)))
     (p += sizeof(Type), *(Type *)(p - sizeof(Type)))
 
 
+#if WASM_ENABLE_MEMORY64 != 0
+static bool
+has_module_memory64(WASMModule *module)
+{
+    /* TODO: multi-memories for now assuming the memory idx type is consistent
+     * across multi-memories */
+    if (module->import_memory_count > 0)
+        return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG);
+    else if (module->memory_count > 0)
+        return !!(module->memories[0].flags & MEMORY64_FLAG);
+
+    return false;
+}
+#endif
+
 static void
 static void
 set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
 set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
 {
 {
@@ -2573,6 +2588,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
     uint32 aux_data_end_global_index = (uint32)-1;
     uint32 aux_data_end_global_index = (uint32)-1;
     uint32 aux_heap_base_global_index = (uint32)-1;
     uint32 aux_heap_base_global_index = (uint32)-1;
     WASMFuncType *func_type;
     WASMFuncType *func_type;
+    uint8 malloc_free_io_type = VALUE_TYPE_I32;
 
 
     /* Find code and function sections if have */
     /* Find code and function sections if have */
     while (section) {
     while (section) {
@@ -2781,6 +2797,10 @@ load_from_sections(WASMModule *module, WASMSection *sections,
     module->retain_function = (uint32)-1;
     module->retain_function = (uint32)-1;
 
 
     /* Resolve malloc/free function exported by wasm module */
     /* Resolve malloc/free function exported by wasm module */
+#if WASM_ENABLE_MEMORY64 != 0
+    if (has_module_memory64(module))
+        malloc_free_io_type = VALUE_TYPE_I64;
+#endif
     export = module->exports;
     export = module->exports;
     for (i = 0; i < module->export_count; i++, export ++) {
     for (i = 0; i < module->export_count; i++, export ++) {
         if (export->kind == EXPORT_KIND_FUNC) {
         if (export->kind == EXPORT_KIND_FUNC) {
@@ -2789,8 +2809,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 func_index = export->index - module->import_function_count;
                 func_index = export->index - module->import_function_count;
                 func_type = module->functions[func_index]->func_type;
                 func_type = module->functions[func_index]->func_type;
                 if (func_type->param_count == 1 && func_type->result_count == 1
                 if (func_type->param_count == 1 && func_type->result_count == 1
-                    && func_type->types[0] == VALUE_TYPE_I32
-                    && func_type->types[1] == VALUE_TYPE_I32) {
+                    && func_type->types[0] == malloc_free_io_type
+                    && func_type->types[1] == malloc_free_io_type) {
                     bh_assert(module->malloc_function == (uint32)-1);
                     bh_assert(module->malloc_function == (uint32)-1);
                     module->malloc_function = export->index;
                     module->malloc_function = export->index;
                     LOG_VERBOSE("Found malloc function, name: %s, index: %u",
                     LOG_VERBOSE("Found malloc function, name: %s, index: %u",
@@ -2803,9 +2823,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 func_index = export->index - module->import_function_count;
                 func_index = export->index - module->import_function_count;
                 func_type = module->functions[func_index]->func_type;
                 func_type = module->functions[func_index]->func_type;
                 if (func_type->param_count == 2 && func_type->result_count == 1
                 if (func_type->param_count == 2 && func_type->result_count == 1
-                    && func_type->types[0] == VALUE_TYPE_I32
+                    && func_type->types[0] == malloc_free_io_type
                     && func_type->types[1] == VALUE_TYPE_I32
                     && func_type->types[1] == VALUE_TYPE_I32
-                    && func_type->types[2] == VALUE_TYPE_I32) {
+                    && func_type->types[2] == malloc_free_io_type) {
                     uint32 j;
                     uint32 j;
                     WASMExport *export_tmp;
                     WASMExport *export_tmp;
 
 
@@ -2829,8 +2849,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                                 module->functions[func_index]->func_type;
                                 module->functions[func_index]->func_type;
                             if (func_type->param_count == 1
                             if (func_type->param_count == 1
                                 && func_type->result_count == 1
                                 && func_type->result_count == 1
-                                && func_type->types[0] == VALUE_TYPE_I32
-                                && func_type->types[1] == VALUE_TYPE_I32) {
+                                && func_type->types[0] == malloc_free_io_type
+                                && func_type->types[1] == malloc_free_io_type) {
                                 bh_assert(module->retain_function
                                 bh_assert(module->retain_function
                                           == (uint32)-1);
                                           == (uint32)-1);
                                 module->retain_function = export_tmp->index;
                                 module->retain_function = export_tmp->index;
@@ -2856,7 +2876,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 func_index = export->index - module->import_function_count;
                 func_index = export->index - module->import_function_count;
                 func_type = module->functions[func_index]->func_type;
                 func_type = module->functions[func_index]->func_type;
                 if (func_type->param_count == 1 && func_type->result_count == 0
                 if (func_type->param_count == 1 && func_type->result_count == 0
-                    && func_type->types[0] == VALUE_TYPE_I32) {
+                    && func_type->types[0] == malloc_free_io_type) {
                     bh_assert(module->free_function == (uint32)-1);
                     bh_assert(module->free_function == (uint32)-1);
                     module->free_function = export->index;
                     module->free_function = export->index;
                     LOG_VERBOSE("Found free function, name: %s, index: %u",
                     LOG_VERBOSE("Found free function, name: %s, index: %u",
@@ -5906,14 +5926,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
            func->param_cell_num, func->local_cell_num, func->ret_cell_num);
            func->param_cell_num, func->local_cell_num, func->ret_cell_num);
 #endif
 #endif
 #if WASM_ENABLE_MEMORY64 != 0
 #if WASM_ENABLE_MEMORY64 != 0
-    bool is_memory64 = false;
-    /* TODO: multi-memories for now assuming the memory idx type is consistent
-     * across multi-memories */
-    if (module->import_memory_count > 0)
-        is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG;
-    else if (module->memory_count > 0)
-        is_memory64 = module->memories[0].flags & MEMORY64_FLAG;
-
+    bool is_memory64 = has_module_memory64(module);
     mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
     mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
 #else
 #else
     mem_offset_type = VALUE_TYPE_I32;
     mem_offset_type = VALUE_TYPE_I32;

+ 45 - 18
core/iwasm/interpreter/wasm_runtime.c

@@ -1400,30 +1400,39 @@ fail:
 static bool
 static bool
 execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
 execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
                         WASMFunctionInstance *malloc_func,
                         WASMFunctionInstance *malloc_func,
-                        WASMFunctionInstance *retain_func, uint32 size,
-                        uint32 *p_result)
+                        WASMFunctionInstance *retain_func, uint64 size,
+                        uint64 *p_result)
 {
 {
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
     WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
     WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
 #endif
 #endif
     WASMExecEnv *exec_env_created = NULL;
     WASMExecEnv *exec_env_created = NULL;
     WASMModuleInstanceCommon *module_inst_old = NULL;
     WASMModuleInstanceCommon *module_inst_old = NULL;
-    uint32 argv[2], argc;
+    uint32 argv[3], argc;
     bool ret;
     bool ret;
-
-    argv[0] = size;
-    argc = 1;
+#if WASM_ENABLE_MEMORY64 != 0
+    bool is_memory64 = module_inst->memories[0]->is_memory64;
+    if (is_memory64) {
+        argc = 2;
+        PUT_I64_TO_ADDR(&argv[0], size);
+    }
+    else
+#endif
+    {
+        argc = 1;
+        argv[0] = size;
+    }
 
 
     /* if __retain is exported, then this module is compiled by
     /* if __retain is exported, then this module is compiled by
         assemblyscript, the memory should be managed by as's runtime,
         assemblyscript, the memory should be managed by as's runtime,
         in this case we need to call the retain function after malloc
         in this case we need to call the retain function after malloc
         the memory */
         the memory */
     if (retain_func) {
     if (retain_func) {
-        /* the malloc functino from assemblyscript is:
+        /* the malloc function from assemblyscript is:
             function __new(size: usize, id: u32)
             function __new(size: usize, id: u32)
             id = 0 means this is an ArrayBuffer object */
             id = 0 means this is an ArrayBuffer object */
-        argv[1] = 0;
-        argc = 2;
+        argv[argc] = 0;
+        argc++;
     }
     }
 
 
     if (exec_env) {
     if (exec_env) {
@@ -1475,24 +1484,42 @@ execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     if (exec_env_created)
     if (exec_env_created)
         wasm_exec_env_destroy(exec_env_created);
         wasm_exec_env_destroy(exec_env_created);
 
 
-    if (ret)
-        *p_result = argv[0];
+    if (ret) {
+#if WASM_ENABLE_MEMORY64 != 0
+        if (is_memory64)
+            *p_result = GET_I64_FROM_ADDR(&argv[0]);
+        else
+#endif
+        {
+            *p_result = argv[0];
+        }
+    }
     return ret;
     return ret;
 }
 }
 
 
 static bool
 static bool
 execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
 execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
-                      WASMFunctionInstance *free_func, uint32 offset)
+                      WASMFunctionInstance *free_func, uint64 offset)
 {
 {
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
     WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
     WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
 #endif
 #endif
     WASMExecEnv *exec_env_created = NULL;
     WASMExecEnv *exec_env_created = NULL;
     WASMModuleInstanceCommon *module_inst_old = NULL;
     WASMModuleInstanceCommon *module_inst_old = NULL;
-    uint32 argv[2];
+    uint32 argv[2], argc;
     bool ret;
     bool ret;
 
 
-    argv[0] = offset;
+#if WASM_ENABLE_MEMORY64 != 0
+    if (module_inst->memories[0]->is_memory64) {
+        PUT_I64_TO_ADDR(&argv[0], offset);
+        argc = 2;
+    }
+    else
+#endif
+    {
+        argv[0] = (uint32)offset;
+        argc = 1;
+    }
 
 
     if (exec_env) {
     if (exec_env) {
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
@@ -1531,7 +1558,7 @@ execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
         }
         }
     }
     }
 
 
-    ret = wasm_call_function(exec_env, free_func, 1, argv);
+    ret = wasm_call_function(exec_env, free_func, argc, argv);
 
 
     if (module_inst_old)
     if (module_inst_old)
         /* Restore the existing exec_env's module inst */
         /* Restore the existing exec_env's module inst */
@@ -3336,7 +3363,7 @@ wasm_module_malloc_internal(WASMModuleInstance *module_inst,
 {
 {
     WASMMemoryInstance *memory = wasm_get_default_memory(module_inst);
     WASMMemoryInstance *memory = wasm_get_default_memory(module_inst);
     uint8 *addr = NULL;
     uint8 *addr = NULL;
-    uint32 offset = 0;
+    uint64 offset = 0;
 
 
     /* TODO: Memory64 size check based on memory idx type */
     /* TODO: Memory64 size check based on memory idx type */
     bh_assert(size <= UINT32_MAX);
     bh_assert(size <= UINT32_MAX);
@@ -3352,7 +3379,7 @@ wasm_module_malloc_internal(WASMModuleInstance *module_inst,
     else if (module_inst->e->malloc_function && module_inst->e->free_function) {
     else if (module_inst->e->malloc_function && module_inst->e->free_function) {
         if (!execute_malloc_function(
         if (!execute_malloc_function(
                 module_inst, exec_env, module_inst->e->malloc_function,
                 module_inst, exec_env, module_inst->e->malloc_function,
-                module_inst->e->retain_function, (uint32)size, &offset)) {
+                module_inst->e->retain_function, size, &offset)) {
             return 0;
             return 0;
         }
         }
         /* If we use app's malloc function,
         /* If we use app's malloc function,
@@ -3452,7 +3479,7 @@ wasm_module_free_internal(WASMModuleInstance *module_inst,
                  && module_inst->e->free_function && memory->memory_data <= addr
                  && module_inst->e->free_function && memory->memory_data <= addr
                  && addr < memory_data_end) {
                  && addr < memory_data_end) {
             execute_free_function(module_inst, exec_env,
             execute_free_function(module_inst, exec_env,
-                                  module_inst->e->free_function, (uint32)ptr);
+                                  module_inst->e->free_function, ptr);
         }
         }
     }
     }
 }
 }