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

This commit is contained in:
Marcin Kolny 2024-04-19 10:15:54 +01:00 committed by GitHub
parent 902aa525d1
commit fd7f738451
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 101 additions and 48 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}
}