From fd7f738451f55cc7095a4d5d94e7f9c4faf25a6a Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Fri, 19 Apr 2024 10:15:54 +0100 Subject: [PATCH] Allow executing malloc/free from native in memory64 mode (#3315) --- core/iwasm/interpreter/wasm_loader.c | 43 ++++++++++------ core/iwasm/interpreter/wasm_mini_loader.c | 43 ++++++++++------ core/iwasm/interpreter/wasm_runtime.c | 63 ++++++++++++++++------- 3 files changed, 101 insertions(+), 48 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 513484fce..6bde9cceb 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -36,6 +36,21 @@ #define TEMPLATE_READ_VALUE(Type, p) \ (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 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_heap_base_global_index = (uint32)-1; WASMFuncType *func_type; + uint8 malloc_free_io_type = VALUE_TYPE_I32; /* Find code and function sections if have */ while (section) { @@ -5887,6 +5903,10 @@ load_from_sections(WASMModule *module, WASMSection *sections, module->retain_function = (uint32)-1; /* 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; for (i = 0; i < module->export_count; i++, export ++) { 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_type = module->functions[func_index]->func_type; 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); module->malloc_function = export->index; 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_type = module->functions[func_index]->func_type; 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[2] == VALUE_TYPE_I32) { + && func_type->types[2] == malloc_free_io_type) { uint32 j; WASMExport *export_tmp; @@ -5935,8 +5955,8 @@ load_from_sections(WASMModule *module, WASMSection *sections, module->functions[func_index]->func_type; 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->retain_function == (uint32)-1); 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_type = module->functions[func_index]->func_type; 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); module->free_function = export->index; 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); #endif #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; #else mem_offset_type = VALUE_TYPE_I32; diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 3deec511f..e82c85278 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -25,6 +25,21 @@ #define TEMPLATE_READ_VALUE(Type, p) \ (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 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_heap_base_global_index = (uint32)-1; WASMFuncType *func_type; + uint8 malloc_free_io_type = VALUE_TYPE_I32; /* Find code and function sections if have */ while (section) { @@ -2781,6 +2797,10 @@ load_from_sections(WASMModule *module, WASMSection *sections, module->retain_function = (uint32)-1; /* 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; for (i = 0; i < module->export_count; i++, export ++) { 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_type = module->functions[func_index]->func_type; 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); module->malloc_function = export->index; 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_type = module->functions[func_index]->func_type; 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[2] == VALUE_TYPE_I32) { + && func_type->types[2] == malloc_free_io_type) { uint32 j; WASMExport *export_tmp; @@ -2829,8 +2849,8 @@ load_from_sections(WASMModule *module, WASMSection *sections, module->functions[func_index]->func_type; 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->retain_function == (uint32)-1); 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_type = module->functions[func_index]->func_type; 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); module->free_function = export->index; 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); #endif #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; #else mem_offset_type = VALUE_TYPE_I32; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index cb5e384fa..c08e09a8c 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1400,30 +1400,39 @@ fail: static bool execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, 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 WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls(); #endif WASMExecEnv *exec_env_created = NULL; WASMModuleInstanceCommon *module_inst_old = NULL; - uint32 argv[2], argc; + uint32 argv[3], argc; 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 assemblyscript, the memory should be managed by as's runtime, in this case we need to call the retain function after malloc the memory */ if (retain_func) { - /* the malloc functino from assemblyscript is: + /* the malloc function from assemblyscript is: function __new(size: usize, id: u32) id = 0 means this is an ArrayBuffer object */ - argv[1] = 0; - argc = 2; + argv[argc] = 0; + argc++; } if (exec_env) { @@ -1475,24 +1484,42 @@ execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, if (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; } static bool 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 WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls(); #endif WASMExecEnv *exec_env_created = NULL; WASMModuleInstanceCommon *module_inst_old = NULL; - uint32 argv[2]; + uint32 argv[2], argc; 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) { #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) /* 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); uint8 *addr = NULL; - uint32 offset = 0; + uint64 offset = 0; /* TODO: Memory64 size check based on memory idx type */ 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) { if (!execute_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; } /* 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 && addr < memory_data_end) { execute_free_function(module_inst, exec_env, - module_inst->e->free_function, (uint32)ptr); + module_inst->e->free_function, ptr); } } }