From 76e42da6f80c18f3cea28ccbfded3a1e8cc98716 Mon Sep 17 00:00:00 2001 From: Benbuck Nason Date: Mon, 16 Sep 2024 12:55:19 -0700 Subject: [PATCH] Add memory import support --- core/iwasm/aot/aot_runtime.c | 26 ++-- core/iwasm/aot/aot_runtime.h | 4 +- core/iwasm/common/wasm_application.c | 2 +- core/iwasm/common/wasm_c_api.c | 11 +- core/iwasm/common/wasm_memory.c | 75 ++++++++++-- core/iwasm/common/wasm_runtime_common.c | 24 ++-- core/iwasm/common/wasm_runtime_common.h | 2 + core/iwasm/common/wasm_shared_memory.c | 27 ++-- core/iwasm/fast-jit/fe/jit_emit_memory.c | 8 +- core/iwasm/include/wasm_export.h | 32 +++++ core/iwasm/interpreter/wasm_interp_classic.c | 4 +- core/iwasm/interpreter/wasm_runtime.c | 115 ++++++++++++------ core/iwasm/interpreter/wasm_runtime.h | 10 +- .../lib-pthread/lib_pthread_wrapper.c | 3 +- .../lib_wasi_threads_wrapper.c | 3 +- .../libraries/thread-mgr/thread_manager.c | 3 +- 16 files changed, 247 insertions(+), 102 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 13664ca0ef..3dd639096d 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -819,7 +819,7 @@ memories_deinstantiate(AOTModuleInstance *module_inst) AOTMemoryInstance *memory_inst; for (i = 0; i < module_inst->memory_count; i++) { - memory_inst = module_inst->memories[i]; + memory_inst = module_inst->memories[i].memory; if (memory_inst) { #if WASM_ENABLE_SHARED_MEMORY != 0 if (shared_memory_is_shared(memory_inst)) { @@ -872,7 +872,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, AOTMemoryInstance *shared_memory_instance; bh_assert(memory_idx == 0); bh_assert(parent->memory_count > memory_idx); - shared_memory_instance = parent->memories[memory_idx]; + shared_memory_instance = parent->memories[memory_idx].memory; shared_memory_inc_reference(shared_memory_instance); return shared_memory_instance; } @@ -1071,7 +1071,7 @@ aot_lookup_memory(AOTModuleInstance *module_inst, char const *name) (void)module_inst->export_memories; if (!module_inst->memories) return NULL; - return module_inst->memories[0]; + return module_inst->memories[0].memory; #endif } @@ -1079,7 +1079,7 @@ AOTMemoryInstance * aot_get_default_memory(AOTModuleInstance *module_inst) { if (module_inst->memories) - return module_inst->memories[0]; + return module_inst->memories[0].memory; else return NULL; } @@ -1089,7 +1089,7 @@ aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index) { if ((index >= module_inst->memory_count) || !module_inst->memories) return NULL; - return module_inst->memories[index]; + return module_inst->memories[index].memory; } static bool @@ -1106,7 +1106,7 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, mem_offset_t base_offset; module_inst->memory_count = memory_count; - total_size = sizeof(AOTMemoryInstance *) * (uint64)memory_count; + total_size = sizeof(AOTMemoryWrapper *) * (uint64)memory_count; if (!(module_inst->memories = runtime_malloc(total_size, error_buf, error_buf_size))) { return false; @@ -1121,7 +1121,7 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, return false; } - module_inst->memories[i] = memory_inst; + module_inst->memories[i].memory = memory_inst; } /* Get default memory instance */ @@ -1434,7 +1434,7 @@ export_memories_instantiate(const AOTModule *module, for (i = 0; i < module->export_count; i++, export ++) if (export->kind == EXPORT_KIND_MEMORY) { export_memory->name = export->name; - export_memory->memory = module_inst->memories[export->index]; + export_memory->memory = module_inst->memories[export->index].memory; export_memory++; } @@ -1684,7 +1684,9 @@ check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size) AOTModuleInstance * aot_instantiate(AOTModule *module, AOTModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, - uint32 max_memory_pages, char *error_buf, uint32 error_buf_size) + uint32 max_memory_pages, uint32 import_count, + const WASMImportInst *imports, char *error_buf, + uint32 error_buf_size) { AOTModuleInstance *module_inst; #if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0 @@ -2591,7 +2593,7 @@ execute_malloc_function(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, bool ret; #if WASM_ENABLE_MEMORY64 != 0 - bool is_memory64 = module_inst->memories[0]->is_memory64; + bool is_memory64 = module_inst->memories[0].memory->is_memory64; if (is_memory64) { argc = 2; PUT_I64_TO_ADDR(&argv.u64, size); @@ -2694,7 +2696,7 @@ execute_free_function(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, bool ret; #if WASM_ENABLE_MEMORY64 != 0 - if (module_inst->memories[0]->is_memory64) { + if (module_inst->memories[0].memory->is_memory64) { PUT_I64_TO_ADDR(&argv.u64, offset); argc = 2; } @@ -3490,7 +3492,7 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst, sizeof(void *) * module_inst->memory_count + sizeof(AOTMemoryInstance) * module_inst->memory_count; for (i = 0; i < module_inst->memory_count; i++) { - AOTMemoryInstance *mem_inst = module_inst->memories[i]; + AOTMemoryInstance *mem_inst = module_inst->memories[i].memory; mem_conspn->memories_size += mem_inst->num_bytes_per_page * mem_inst->cur_page_count; mem_conspn->app_heap_size = diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index f13d7eefc0..0fb437e08a 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -336,6 +336,7 @@ typedef struct AOTModule { #endif } AOTModule; +#define AOTMemoryWrapper WASMMemoryWrapper #define AOTMemoryInstance WASMMemoryInstance #define AOTTableInstance WASMTableInstance #define AOTModuleInstance WASMModuleInstance @@ -509,7 +510,8 @@ aot_unload(AOTModule *module); AOTModuleInstance * aot_instantiate(AOTModule *module, AOTModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, - uint32 max_memory_pages, char *error_buf, + uint32 max_memory_pages, uint32 import_count, + const WASMImportInst *imports, char *error_buf, uint32 error_buf_size); /** diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 3b3be16c05..74f589a6a1 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -105,7 +105,7 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) bool ret, is_import_func = true, is_memory64 = false; #if WASM_ENABLE_MEMORY64 != 0 WASMModuleInstance *wasm_module_inst = (WASMModuleInstance *)module_inst; - is_memory64 = wasm_module_inst->memories[0]->is_memory64; + is_memory64 = wasm_module_inst->memories[0].memory->is_memory64; #endif exec_env = wasm_runtime_get_exec_env_singleton(module_inst); diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 01109658ff..a008207883 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -4294,8 +4294,9 @@ wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt, #if WASM_ENABLE_INTERP != 0 if (inst_comm_rt->module_type == Wasm_Module_Bytecode) { - WASMMemoryInstance *memory_interp = - ((WASMModuleInstance *)inst_comm_rt)->memories[memory_idx_rt]; + WASMMemoryInstance *memory_interp = ((WASMModuleInstance *)inst_comm_rt) + ->memories[memory_idx_rt] + .memory; min_pages = memory_interp->cur_page_count; max_pages = memory_interp->max_page_count; init_flag = true; @@ -4379,7 +4380,7 @@ wasm_memory_data(wasm_memory_t *memory) WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst = - module_inst->memories[memory->memory_idx_rt]; + module_inst->memories[memory->memory_idx_rt].memory; return (byte_t *)memory_inst->memory_data; } #endif @@ -4416,7 +4417,7 @@ wasm_memory_data_size(const wasm_memory_t *memory) WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst = - module_inst->memories[memory->memory_idx_rt]; + module_inst->memories[memory->memory_idx_rt].memory; return (size_t)memory_inst->cur_page_count * memory_inst->num_bytes_per_page; } @@ -4455,7 +4456,7 @@ wasm_memory_size(const wasm_memory_t *memory) WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst = - module_inst->memories[memory->memory_idx_rt]; + module_inst->memories[memory->memory_idx_rt].memory; return memory_inst->cur_page_count; } #endif diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 03260589d3..c9a317f61a 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -379,7 +379,7 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm, goto fail; #if WASM_ENABLE_MEMORY64 != 0 - if (module_inst->memories[0]->is_memory64) + if (module_inst->memories[0].memory->is_memory64) max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE; #endif /* boundary overflow check, max start offset can only be size - 1, while end @@ -665,7 +665,7 @@ WASMMemoryInstance * wasm_get_default_memory(WASMModuleInstance *module_inst) { if (module_inst->memories) - return module_inst->memories[0]; + return module_inst->memories[0].memory; else return NULL; } @@ -675,7 +675,7 @@ wasm_get_memory_with_idx(WASMModuleInstance *module_inst, uint32 index) { if ((index >= module_inst->memory_count) || !module_inst->memories) return NULL; - return module_inst->memories[index]; + return module_inst->memories[index].memory; } void @@ -965,12 +965,13 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) if (module->memory_count > 0) { #if WASM_ENABLE_SHARED_MEMORY != 0 - shared_memory_lock(module->memories[0]); + shared_memory_lock(module->memories[0].memory); #endif ret = wasm_enlarge_memory_internal((WASMModuleInstanceCommon *)module, - module->memories[0], inc_page_count); + module->memories[0].memory, + inc_page_count); #if WASM_ENABLE_SHARED_MEMORY != 0 - shared_memory_unlock(module->memories[0]); + shared_memory_unlock(module->memories[0].memory); #endif } @@ -985,19 +986,75 @@ wasm_enlarge_memory_with_idx(WASMModuleInstance *module, uint32 inc_page_count, if (memidx < module->memory_count) { #if WASM_ENABLE_SHARED_MEMORY != 0 - shared_memory_lock(module->memories[memidx]); + shared_memory_lock(module->memories[memidx].memory); #endif ret = wasm_enlarge_memory_internal((WASMModuleInstanceCommon *)module, - module->memories[memidx], + module->memories[memidx].memory, inc_page_count); #if WASM_ENABLE_SHARED_MEMORY != 0 - shared_memory_unlock(module->memories[memidx]); + shared_memory_unlock(module->memories[memidx].memory); #endif } return ret; } +WASMMemoryInstance * +wasm_runtime_memory_create(uint64 initial_pages, uint64 max_pages, bool shared) +{ + WASMMemoryInstance *memory; + + if (!initial_pages || (max_pages && (max_pages < initial_pages))) { + return NULL; + } + + if (!(memory = wasm_runtime_malloc(sizeof(WASMMemoryInstance)))) { + return NULL; + } + + memset(memory, 0, sizeof(WASMMemoryInstance)); + + memory->module_type = Package_Type_Unknown; + memory->num_bytes_per_page = 64 * 1024; + memory->cur_page_count = (uint32)initial_pages; + memory->max_page_count = (uint32)max_pages; + memory->memory_data_size = + (uint64)memory->num_bytes_per_page * memory->max_page_count; + bh_assert(memory->memory_data_size + <= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)); + +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (shared) { + memory->is_shared_memory = 1; + memory->ref_count = 1; + } +#endif + + if (wasm_allocate_linear_memory( + &memory->memory_data, memory->is_shared_memory, memory->is_memory64, + memory->num_bytes_per_page, memory->cur_page_count, + memory->max_page_count, &memory->memory_data_size) + != BHT_OK) { + wasm_runtime_free(memory); + return NULL; + } + + if (memory->memory_data_size > 0) { + wasm_runtime_set_mem_bound_check_bytes(memory, + memory->memory_data_size); + } + + return memory; +} + +void +wasm_memory_destroy(WASMMemoryInstance *memory_inst) +{ + if (memory_inst) { + wasm_runtime_free(memory_inst); + } +} + WASMMemoryInstance * wasm_runtime_lookup_memory(WASMModuleInstanceCommon *module_inst, const char *name) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 314dc7ddb1..7e55a74a4e 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1589,19 +1589,23 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, WASMModuleInstanceCommon *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, uint32 max_memory_pages, + uint32 import_count, + const WASMImportInst *imports, char *error_buf, uint32 error_buf_size) { #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) return (WASMModuleInstanceCommon *)wasm_instantiate( (WASMModule *)module, (WASMModuleInstance *)parent, exec_env_main, - stack_size, heap_size, max_memory_pages, error_buf, error_buf_size); + stack_size, heap_size, max_memory_pages, import_count, imports, + error_buf, error_buf_size); #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) return (WASMModuleInstanceCommon *)aot_instantiate( (AOTModule *)module, (AOTModuleInstance *)parent, exec_env_main, - stack_size, heap_size, max_memory_pages, error_buf, error_buf_size); + stack_size, heap_size, max_memory_pages, import_count, imports, + error_buf, error_buf_size); #endif set_error_buf(error_buf, error_buf_size, "Instantiate module failed, invalid module type"); @@ -1614,7 +1618,7 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, uint32 error_buf_size) { return wasm_runtime_instantiate_internal(module, NULL, NULL, stack_size, - heap_size, 0, error_buf, + heap_size, 0, 0, NULL, error_buf, error_buf_size); } @@ -1625,8 +1629,8 @@ wasm_runtime_instantiate_ex(WASMModuleCommon *module, { return wasm_runtime_instantiate_internal( module, NULL, NULL, args->default_stack_size, - args->host_managed_heap_size, args->max_memory_pages, error_buf, - error_buf_size); + args->host_managed_heap_size, args->max_memory_pages, + args->import_count, args->imports, error_buf, error_buf_size); } void @@ -1865,7 +1869,7 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) WASMModule *wasm_module = wasm_module_inst->module; module_common = (WASMModuleCommon *)wasm_module; if (wasm_module_inst->memories) { - heap_handle = wasm_module_inst->memories[0]->heap_handle; + heap_handle = wasm_module_inst->memories[0].memory->heap_handle; } wasm_get_module_inst_mem_consumption(wasm_module_inst, &module_inst_mem_consps); @@ -1881,8 +1885,8 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) AOTModule *aot_module = (AOTModule *)aot_module_inst->module; module_common = (WASMModuleCommon *)aot_module; if (aot_module_inst->memories) { - AOTMemoryInstance **memories = aot_module_inst->memories; - heap_handle = memories[0]->heap_handle; + AOTMemoryWrapper *memories = aot_module_inst->memories; + heap_handle = memories[0].memory->heap_handle; } aot_get_module_inst_mem_consumption(aot_module_inst, &module_inst_mem_consps); @@ -7434,8 +7438,8 @@ wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, WASMModuleCommon *sub_module = sub_module_list_node->module; WASMModuleInstanceCommon *sub_module_inst = NULL; sub_module_inst = wasm_runtime_instantiate_internal( - sub_module, NULL, NULL, stack_size, heap_size, max_memory_pages, - error_buf, error_buf_size); + sub_module, NULL, NULL, stack_size, heap_size, max_memory_pages, 0, + NULL, error_buf, error_buf_size); if (!sub_module_inst) { LOG_DEBUG("instantiate %s failed", sub_module_list_node->module_name); diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index fb2c79408d..a4b7aaeb34 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -575,6 +575,8 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, WASMModuleInstanceCommon *parent, WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size, uint32 max_memory_pages, + uint32 import_count, + const WASMImportInst *imports, char *error_buf, uint32 error_buf_size); /* Internal API */ diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index 9cfdd0926c..8f749dbab8 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -265,20 +265,20 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, } /* Currently we have only one memory instance */ - if (!shared_memory_is_shared(module_inst->memories[0])) { + if (!shared_memory_is_shared(module_inst->memories[0].memory)) { wasm_runtime_set_exception(module, "expected shared memory"); return -1; } - shared_memory_lock(module_inst->memories[0]); - if ((uint8 *)address < module_inst->memories[0]->memory_data + shared_memory_lock(module_inst->memories[0].memory); + if ((uint8 *)address < module_inst->memories[0].memory->memory_data || (uint8 *)address + (wait64 ? 8 : 4) - > module_inst->memories[0]->memory_data_end) { - shared_memory_unlock(module_inst->memories[0]); + > module_inst->memories[0].memory->memory_data_end) { + shared_memory_unlock(module_inst->memories[0].memory); wasm_runtime_set_exception(module, "out of bounds memory access"); return -1; } - shared_memory_unlock(module_inst->memories[0]); + shared_memory_unlock(module_inst->memories[0].memory); #if WASM_ENABLE_THREAD_MGR != 0 exec_env = @@ -286,7 +286,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, bh_assert(exec_env); #endif - lock = shared_memory_get_lock_pointer(module_inst->memories[0]); + lock = shared_memory_get_lock_pointer(module_inst->memories[0].memory); /* Lock the shared_mem_lock for the whole atomic wait process, and use it to os_cond_reltimedwait */ @@ -395,11 +395,12 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, bh_assert(module->module_type == Wasm_Module_Bytecode || module->module_type == Wasm_Module_AoT); - shared_memory_lock(module_inst->memories[0]); + shared_memory_lock(module_inst->memories[0].memory); out_of_bounds = - ((uint8 *)address < module_inst->memories[0]->memory_data - || (uint8 *)address + 4 > module_inst->memories[0]->memory_data_end); - shared_memory_unlock(module_inst->memories[0]); + ((uint8 *)address < module_inst->memories[0].memory->memory_data + || (uint8 *)address + 4 + > module_inst->memories[0].memory->memory_data_end); + shared_memory_unlock(module_inst->memories[0].memory); if (out_of_bounds) { wasm_runtime_set_exception(module, "out of bounds memory access"); @@ -407,13 +408,13 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, } /* Currently we have only one memory instance */ - if (!shared_memory_is_shared(module_inst->memories[0])) { + if (!shared_memory_is_shared(module_inst->memories[0].memory)) { /* Always return 0 for ushared linear memory since there is no way to create a waiter on it */ return 0; } - lock = shared_memory_get_lock_pointer(module_inst->memories[0]); + lock = shared_memory_get_lock_pointer(module_inst->memories[0].memory); /* Lock the shared_mem_lock for the whole atomic notify process, and use it to os_cond_signal */ diff --git a/core/iwasm/fast-jit/fe/jit_emit_memory.c b/core/iwasm/fast-jit/fe/jit_emit_memory.c index bbe82cf674..2fe003489a 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_memory.c +++ b/core/iwasm/fast-jit/fe/jit_emit_memory.c @@ -636,7 +636,7 @@ wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx, uint32 seg_len; /* if d + n > the length of mem.data */ - mem_inst = inst->memories[mem_idx]; + mem_inst = inst->memories[mem_idx].memory; mem_size = mem_inst->cur_page_count * (uint64)mem_inst->num_bytes_per_page; if (mem_size < mem_offset || mem_size - mem_offset < len) goto out_of_bounds; @@ -723,8 +723,8 @@ wasm_copy_memory(WASMModuleInstance *inst, uint32 src_mem_idx, uint64 src_mem_size, dst_mem_size; uint8 *src_addr, *dst_addr; - src_mem = inst->memories[src_mem_idx]; - dst_mem = inst->memories[dst_mem_idx]; + src_mem = inst->memories[src_mem_idx].memory; + dst_mem = inst->memories[dst_mem_idx].memory; src_mem_size = src_mem->cur_page_count * (uint64)src_mem->num_bytes_per_page; dst_mem_size = @@ -790,7 +790,7 @@ wasm_fill_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 len, uint64 mem_size; uint8 *dst_addr; - mem_inst = inst->memories[mem_idx]; + mem_inst = inst->memories[mem_idx].memory; mem_size = mem_inst->cur_page_count * (uint64)mem_inst->num_bytes_per_page; if (mem_size < dst || mem_size - dst < len) diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 1a03f7280d..3d4f850b11 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -256,6 +256,15 @@ typedef struct LoadArgs { } LoadArgs; #endif /* LOAD_ARGS_OPTION_DEFINED */ +typedef struct WASMImportInst { + const char *module_name; + const char *name; + wasm_import_export_kind_t kind; + union { + wasm_memory_inst_t memory_inst; + } u; +} WASMImportInst; + #ifndef INSTANTIATION_ARGS_OPTION_DEFINED #define INSTANTIATION_ARGS_OPTION_DEFINED /* WASM module instantiation arguments */ @@ -263,6 +272,8 @@ typedef struct InstantiationArgs { uint32_t default_stack_size; uint32_t host_managed_heap_size; uint32_t max_memory_pages; + uint32_t import_count; + const WASMImportInst *imports; } InstantiationArgs; #endif /* INSTANTIATION_ARGS_OPTION_DEFINED */ @@ -943,6 +954,27 @@ WASM_RUNTIME_API_EXTERN void wasm_runtime_set_module_inst(wasm_exec_env_t exec_env, const wasm_module_inst_t module_inst); +/** + * Create a memory instance + * + * @param initial_pages The initial number of pages + * @param max_pages The maximum number of pages, or zero for no maximum + * @param shared Whether the memory is shared + * + * @return The created memory instance if successful, NULL otherwise + */ +WASM_RUNTIME_API_EXTERN wasm_memory_inst_t +wasm_runtime_memory_create(uint64_t initial_pages, uint64_t max_pages, + bool shared); + +/** + * @brief Destroy a memory instance + * + * @param memory_inst The memory instance to destroy + */ +WASM_RUNTIME_API_EXTERN void +wasm_memory_destroy(wasm_memory_inst_t memory_inst); + /** * @brief Lookup a memory instance by name * diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 67f8c2d455..c3a3c6da98 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -3455,7 +3455,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, str_obj = (WASMString)wasm_stringref_obj_get_value( stringref_obj); - memory_inst = module->memories[mem_idx]; + memory_inst = module->memories[mem_idx].memory; maddr = memory_inst->memory_data + addr; if (opcode == WASM_OP_STRING_ENCODE_WTF16) { @@ -3623,7 +3623,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr = POP_I32(); stringview_wtf8_obj = POP_REF(); - memory_inst = module->memories[mem_idx]; + memory_inst = module->memories[mem_idx].memory; maddr = memory_inst->memory_data + addr; bytes_written = wasm_string_encode( diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index e8f4c749e0..99ac67eac8 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -117,12 +117,12 @@ get_sub_module_inst(const WASMModuleInstance *parent_module_inst, */ static void memories_deinstantiate(WASMModuleInstance *module_inst, - WASMMemoryInstance **memories, uint32 count) + WASMMemoryWrapper *memories, uint32 count) { uint32 i; if (memories) { for (i = 0; i < count; i++) { - if (memories[i]) { + if (memories[i].memory) { #if WASM_ENABLE_MULTI_MODULE != 0 WASMModule *module = module_inst->module; if (i < module->import_memory_count @@ -131,21 +131,22 @@ memories_deinstantiate(WASMModuleInstance *module_inst, } #endif #if WASM_ENABLE_SHARED_MEMORY != 0 - if (shared_memory_is_shared(memories[i])) { - uint32 ref_count = shared_memory_dec_reference(memories[i]); + if (shared_memory_is_shared(memories[i].memory)) { + uint32 ref_count = + shared_memory_dec_reference(memories[i].memory); /* if the reference count is not zero, don't free the memory */ if (ref_count > 0) continue; } #endif - if (memories[i]->heap_handle) { - mem_allocator_destroy(memories[i]->heap_handle); - wasm_runtime_free(memories[i]->heap_handle); - memories[i]->heap_handle = NULL; + if (memories[i].memory->heap_handle) { + mem_allocator_destroy(memories[i].memory->heap_handle); + wasm_runtime_free(memories[i].memory->heap_handle); + memories[i].memory->heap_handle = NULL; } - if (memories[i]->memory_data) { - wasm_deallocate_linear_memory(memories[i]); + if (memories[i].memory->memory_data) { + wasm_deallocate_linear_memory(memories[i].memory); } } } @@ -176,7 +177,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, /* shared memory */ if (is_shared_memory && parent != NULL) { bh_assert(parent->memory_count > memory_idx); - memory = parent->memories[memory_idx]; + memory = parent->memories[memory_idx].memory; shared_memory_inc_reference(memory); return memory; } @@ -380,19 +381,21 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, /** * Instantiate memories in a module. */ -static WASMMemoryInstance ** +static WASMMemoryWrapper * memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, WASMModuleInstance *parent, uint32 heap_size, - uint32 max_memory_pages, char *error_buf, + uint32 max_memory_pages, uint32 import_count, + const WASMImportInst *imports, char *error_buf, uint32 error_buf_size) { WASMImport *import; uint32 mem_index = 0, i, memory_count = module->import_memory_count + module->memory_count; uint64 total_size; - WASMMemoryInstance **memories, *memory; + WASMMemoryWrapper *memories; + WASMMemoryInstance *memory; - total_size = sizeof(WASMMemoryInstance *) * (uint64)memory_count; + total_size = sizeof(WASMMemoryWrapper *) * (uint64)memory_count; if (!(memories = runtime_malloc(total_size, error_buf, error_buf_size))) { return NULL; @@ -403,14 +406,27 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, /* instantiate memories from import section */ import = module->import_memories; for (i = 0; i < module->import_memory_count; i++, import++, memory++) { - uint32 num_bytes_per_page = - import->u.memory.mem_type.num_bytes_per_page; - uint32 init_page_count = import->u.memory.mem_type.init_page_count; - uint32 max_page_count = wasm_runtime_get_max_mem( - max_memory_pages, import->u.memory.mem_type.init_page_count, - import->u.memory.mem_type.max_page_count); - uint32 flags = import->u.memory.mem_type.flags; - uint32 actual_heap_size = heap_size; + bool found = false; + for (uint32 j = 0; j < import_count; j++) { + if (import->kind != WASM_IMPORT_EXPORT_KIND_MEMORY) { + continue; + } + if (strcmp(import->u.memory.module_name, imports[j].module_name)) { + continue; + } + if (strcmp(import->u.memory.field_name, imports[j].name)) { + continue; + } + + memories[mem_index].memory = imports[j].u.memory_inst; + memories[mem_index].memory_import = &import->u.memory; + mem_index++; + found = true; + break; + } + if (found) { + continue; + } #if WASM_ENABLE_MULTI_MODULE != 0 if (import->u.memory.import_module != NULL) { @@ -423,23 +439,37 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, return NULL; } - if (!(memories[mem_index++] = wasm_lookup_memory( + if (!(memories[mem_index].memory = wasm_lookup_memory( module_inst_linked, import->u.memory.field_name))) { set_error_buf(error_buf, error_buf_size, "unknown memory"); memories_deinstantiate(module_inst, memories, memory_count); return NULL; } + + memories[mem_index].memory_import = &import->u.memory; + mem_index++; + continue; } - else #endif + { - if (!(memories[mem_index] = memory_instantiate( + uint32 num_bytes_per_page = + import->u.memory.mem_type.num_bytes_per_page; + uint32 init_page_count = import->u.memory.mem_type.init_page_count; + uint32 max_page_count = wasm_runtime_get_max_mem( + max_memory_pages, import->u.memory.mem_type.init_page_count, + import->u.memory.mem_type.max_page_count); + uint32 flags = import->u.memory.mem_type.flags; + uint32 actual_heap_size = heap_size; + + if (!(memories[mem_index].memory = memory_instantiate( module_inst, parent, memory, mem_index, num_bytes_per_page, init_page_count, max_page_count, actual_heap_size, flags, error_buf, error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } + memories[mem_index].memory_import = &import->u.memory; mem_index++; } } @@ -449,7 +479,7 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, uint32 max_page_count = wasm_runtime_get_max_mem( max_memory_pages, module->memories[i].init_page_count, module->memories[i].max_page_count); - if (!(memories[mem_index] = memory_instantiate( + if (!(memories[mem_index].memory = memory_instantiate( module_inst, parent, memory, mem_index, module->memories[i].num_bytes_per_page, module->memories[i].init_page_count, max_page_count, @@ -1351,7 +1381,7 @@ export_memories_instantiate(const WASMModule *module, for (i = 0; i < module->export_count; i++, export ++) if (export->kind == EXPORT_KIND_MEMORY) { export_memory->name = export->name; - export_memory->memory = module_inst->memories[export->index]; + export_memory->memory = module_inst->memories[export->index].memory; export_memory++; } @@ -1577,7 +1607,7 @@ execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, uint32 argc; bool ret; #if WASM_ENABLE_MEMORY64 != 0 - bool is_memory64 = module_inst->memories[0]->is_memory64; + bool is_memory64 = module_inst->memories[0].memory->is_memory64; if (is_memory64) { argc = 2; PUT_I64_TO_ADDR(&argv.u64, size); @@ -1680,7 +1710,7 @@ execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, bool ret; #if WASM_ENABLE_MEMORY64 != 0 - if (module_inst->memories[0]->is_memory64) { + if (module_inst->memories[0].memory->is_memory64) { PUT_I64_TO_ADDR(&argv.u64, offset); argc = 2; } @@ -1795,11 +1825,15 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, for (i = 0; i < module->import_memory_count; i++) { WASMMemoryImport *memory = &((module->import_memories + i)->u.memory); - if (!wasm_runtime_is_built_in_module(memory->module_name) -#if WASM_ENABLE_MULTI_MODULE != 0 - && !memory->import_memory_linked -#endif - ) { + bool found = false; + for (uint32 j = 0; j < module_inst->memory_count; j++) { + if (module_inst->memories[j].memory_import == memory) { + found = true; + break; + } + } + + if (!found) { set_error_buf_v(error_buf, error_buf_size, "failed to link import memory (%s, %s)", memory->module_name, memory->field_name); @@ -2201,7 +2235,8 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode) WASMModuleInstance * wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, - uint32 heap_size, uint32 max_memory_pages, char *error_buf, + uint32 heap_size, uint32 max_memory_pages, uint32 import_count, + const WASMImportInst *imports, char *error_buf, uint32 error_buf_size) { WASMModuleInstance *module_inst; @@ -2407,7 +2442,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, if ((module_inst->memory_count > 0 && !(module_inst->memories = memories_instantiate( module, module_inst, parent, heap_size, max_memory_pages, - error_buf, error_buf_size))) + import_count, imports, error_buf, error_buf_size))) || (module_inst->table_count > 0 && !(module_inst->tables = tables_instantiate(module, module_inst, first_table, @@ -2570,7 +2605,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, continue; /* has check it in loader */ - memory = module_inst->memories[data_seg->memory_index]; + memory = module_inst->memories[data_seg->memory_index].memory; bh_assert(memory); memory_data = memory->memory_data; @@ -3307,7 +3342,7 @@ wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name) (void)module_inst->export_memories; if (!module_inst->memories) return NULL; - return module_inst->memories[0]; + return module_inst->memories[0].memory; #endif } @@ -4004,7 +4039,7 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst, mem_conspn->memories_size = sizeof(WASMMemoryInstance *) * module_inst->memory_count; for (i = 0; i < module_inst->memory_count; i++) { - WASMMemoryInstance *memory = module_inst->memories[i]; + WASMMemoryInstance *memory = module_inst->memories[i].memory; size = memory->num_bytes_per_page * memory->cur_page_count; mem_conspn->memories_size += size; mem_conspn->app_heap_size += memory->heap_data_end - memory->heap_data; diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index c430186952..73d0a653ec 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -362,6 +362,11 @@ typedef struct WASMModuleInstanceExtra { struct AOTFuncPerfProfInfo; +typedef struct WASMMemoryWrapper { + WASMMemoryInstance *memory; + WASMMemoryImport *memory_import; +} WASMMemoryWrapper; + struct WASMModuleInstance { /* Module instance type, for module instance loaded from WASM bytecode binary, this field is Wasm_Module_Bytecode; @@ -371,7 +376,7 @@ struct WASMModuleInstance { uint32 module_type; uint32 memory_count; - DefPointer(WASMMemoryInstance **, memories); + DefPointer(WASMMemoryWrapper *, memories); /* global and table info */ uint32 global_data_size; @@ -516,7 +521,8 @@ wasm_unload(WASMModule *module); WASMModuleInstance * wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMExecEnv *exec_env_main, uint32 stack_size, - uint32 heap_size, uint32 max_memory_pages, char *error_buf, + uint32 heap_size, uint32 max_memory_pages, uint32 import_count, + const WASMImportInst *imports, char *error_buf, uint32 error_buf_size); void diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index b3fa57d721..6bae2bf8a4 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -580,7 +580,8 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, #endif if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, module_inst, exec_env, stack_size, 0, 0, NULL, 0))) + module, module_inst, exec_env, stack_size, 0, 0, 0, NULL, NULL, + 0))) return -1; /* Set custom_data to new module instance */ diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c index c9512fb432..7c7d6b589b 100644 --- a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c +++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c @@ -87,7 +87,8 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size; if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, module_inst, exec_env, stack_size, 0, 0, NULL, 0))) + module, module_inst, exec_env, stack_size, 0, 0, 0, NULL, NULL, + 0))) return -1; wasm_runtime_set_custom_data_internal( diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index ebb56ba7ca..9bd36a4d06 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -506,7 +506,8 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) } if (!(new_module_inst = wasm_runtime_instantiate_internal( - module, module_inst, exec_env, stack_size, 0, 0, NULL, 0))) { + module, module_inst, exec_env, stack_size, 0, 0, 0, NULL, NULL, + 0))) { return NULL; }