From 926f6622312b52ce24bf55690cfba771299f36fa Mon Sep 17 00:00:00 2001 From: Benbuck Nason Date: Fri, 13 Sep 2024 19:31:13 -0700 Subject: [PATCH] Add memory instance support apis (#3786) Now that WAMR supports multiple memory instances, this PR adds some APIs to access them in a standard way. This involves moving some existing utility functions out from the `WASM_ENABLE_MULTI_MODULE` blocks they were nested in, but multi-memory and multi-module seem independent as far as I can tell so I assume that's okay. APIs added: ```C wasm_runtime_lookup_memory wasm_runtime_get_default_memory wasm_runtime_get_memory wasm_memory_get_cur_page_count wasm_memory_get_max_page_count wasm_memory_get_bytes_per_page wasm_memory_get_shared wasm_memory_get_base_address wasm_memory_enlarge ``` --- core/iwasm/aot/aot_runtime.c | 27 ++++- core/iwasm/aot/aot_runtime.h | 9 ++ core/iwasm/common/wasm_memory.c | 137 ++++++++++++++++++++++---- core/iwasm/include/wasm_export.h | 98 ++++++++++++++++++ core/iwasm/interpreter/wasm_runtime.c | 106 ++++++++++---------- core/iwasm/interpreter/wasm_runtime.h | 6 +- 6 files changed, 307 insertions(+), 76 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 4b6d25b83..dc6cba3f6 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1058,7 +1058,24 @@ fail1: return NULL; } -static AOTMemoryInstance * +AOTMemoryInstance * +aot_lookup_memory(AOTModuleInstance *module_inst, char const *name) +{ +#if WASM_ENABLE_MULTI_MEMORY != 0 + uint32 i; + for (i = 0; i < module_inst->export_memory_count; i++) + if (!strcmp(module_inst->export_memories[i].name, name)) + return module_inst->export_memories[i].memory; + return NULL; +#else + (void)module_inst->export_memories; + if (!module_inst->memories) + return NULL; + return module_inst->memories[0]; +#endif +} + +AOTMemoryInstance * aot_get_default_memory(AOTModuleInstance *module_inst) { if (module_inst->memories) @@ -1067,6 +1084,14 @@ aot_get_default_memory(AOTModuleInstance *module_inst) return NULL; } +AOTMemoryInstance * +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]; +} + static bool memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, AOTModule *module, uint32 heap_size, diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 56d11a22d..f13d7eefc 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -532,6 +532,15 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst); AOTFunctionInstance * aot_lookup_function(const AOTModuleInstance *module_inst, const char *name); +AOTMemoryInstance * +aot_lookup_memory(AOTModuleInstance *module_inst, char const *name); + +AOTMemoryInstance * +aot_get_default_memory(AOTModuleInstance *module_inst); + +AOTMemoryInstance * +aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index); + /** * Get a function in the AOT module instance. * diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 82eebbf30..03260589d 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -673,11 +673,9 @@ wasm_get_default_memory(WASMModuleInstance *module_inst) WASMMemoryInstance * wasm_get_memory_with_idx(WASMModuleInstance *module_inst, uint32 index) { - bh_assert(index < module_inst->memory_count); - if (module_inst->memories) - return module_inst->memories[index]; - else + if ((index >= module_inst->memory_count) || !module_inst->memories) return NULL; + return module_inst->memories[index]; } void @@ -756,15 +754,10 @@ wasm_mmap_linear_memory(uint64_t map_size, uint64 commit_size) return wasm_mremap_linear_memory(NULL, 0, map_size, commit_size); } -bool -wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count, - uint32 memidx) +static bool +wasm_enlarge_memory_internal(WASMModuleInstanceCommon *module, + WASMMemoryInstance *memory, uint32 inc_page_count) { -#if WASM_ENABLE_MULTI_MEMORY != 0 - WASMMemoryInstance *memory = wasm_get_memory_with_idx(module, memidx); -#else - WASMMemoryInstance *memory = wasm_get_default_memory(module); -#endif uint8 *memory_data_old, *memory_data_new, *heap_data_old; uint32 num_bytes_per_page, heap_size; uint32 cur_page_count, max_page_count, total_page_count; @@ -913,7 +906,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count, wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new); return_func: - if (!ret && enlarge_memory_error_cb) { + if (!ret && module && enlarge_memory_error_cb) { WASMExecEnv *exec_env = NULL; #if WASM_ENABLE_INTERP != 0 @@ -926,8 +919,7 @@ return_func: #endif enlarge_memory_error_cb(inc_page_count, total_size_old, 0, - failure_reason, - (WASMModuleInstanceCommon *)module, exec_env, + failure_reason, module, exec_env, enlarge_memory_error_user_data); } @@ -971,15 +963,16 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) { bool ret = false; + if (module->memory_count > 0) { #if WASM_ENABLE_SHARED_MEMORY != 0 - if (module->memory_count > 0) shared_memory_lock(module->memories[0]); #endif - ret = wasm_enlarge_memory_internal(module, inc_page_count, 0); + ret = wasm_enlarge_memory_internal((WASMModuleInstanceCommon *)module, + module->memories[0], inc_page_count); #if WASM_ENABLE_SHARED_MEMORY != 0 - if (module->memory_count > 0) shared_memory_unlock(module->memories[0]); #endif + } return ret; } @@ -990,15 +983,117 @@ wasm_enlarge_memory_with_idx(WASMModuleInstance *module, uint32 inc_page_count, { bool ret = false; + if (memidx < module->memory_count) { #if WASM_ENABLE_SHARED_MEMORY != 0 - if (memidx < module->memory_count) shared_memory_lock(module->memories[memidx]); #endif - ret = wasm_enlarge_memory_internal(module, inc_page_count, memidx); + ret = wasm_enlarge_memory_internal((WASMModuleInstanceCommon *)module, + module->memories[memidx], + inc_page_count); #if WASM_ENABLE_SHARED_MEMORY != 0 - if (memidx < module->memory_count) shared_memory_unlock(module->memories[memidx]); #endif + } + + return ret; +} + +WASMMemoryInstance * +wasm_runtime_lookup_memory(WASMModuleInstanceCommon *module_inst, + const char *name) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_lookup_memory((WASMModuleInstance *)module_inst, name); +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_lookup_memory((WASMModuleInstance *)module_inst, name); +#endif + + return NULL; +} + +WASMMemoryInstance * +wasm_runtime_get_default_memory(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_get_default_memory((WASMModuleInstance *)module_inst); +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_get_default_memory((AOTModuleInstance *)module_inst); +#endif + + return NULL; +} + +WASMMemoryInstance * +wasm_runtime_get_memory(WASMModuleInstanceCommon *module_inst, uint32 index) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_get_memory_with_idx((WASMModuleInstance *)module_inst, + index); +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_get_memory_with_index((AOTModuleInstance *)module_inst, + index); +#endif + + return NULL; +} + +uint64 +wasm_memory_get_cur_page_count(WASMMemoryInstance *memory) +{ + return memory->cur_page_count; +} + +uint64 +wasm_memory_get_max_page_count(WASMMemoryInstance *memory) +{ + return memory->max_page_count; +} + +uint64 +wasm_memory_get_bytes_per_page(WASMMemoryInstance *memory) +{ + return memory->num_bytes_per_page; +} + +bool +wasm_memory_get_shared(WASMMemoryInstance *memory) +{ + return memory->is_shared_memory; +} + +void * +wasm_memory_get_base_address(WASMMemoryInstance *memory) +{ + return memory->memory_data; +} + +bool +wasm_memory_enlarge(WASMMemoryInstance *memory, uint64 inc_page_count) +{ + bool ret = false; + + if (memory) { +#if WASM_ENABLE_SHARED_MEMORY != 0 + shared_memory_lock(memory); +#endif + ret = + wasm_enlarge_memory_internal(NULL, memory, (uint32)inc_page_count); +#if WASM_ENABLE_SHARED_MEMORY != 0 + shared_memory_unlock(memory); +#endif + } return ret; } diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 569c4deaa..1a03f7280 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -120,6 +120,10 @@ typedef struct WASMModuleInstanceCommon *wasm_module_inst_t; typedef void WASMFunctionInstanceCommon; typedef WASMFunctionInstanceCommon *wasm_function_inst_t; +/* Memory instance */ +struct WASMMemoryInstance; +typedef struct WASMMemoryInstance *wasm_memory_inst_t; + /* WASM section */ typedef struct wasm_section_t { struct wasm_section_t *next; @@ -939,6 +943,100 @@ WASM_RUNTIME_API_EXTERN void wasm_runtime_set_module_inst(wasm_exec_env_t exec_env, const wasm_module_inst_t module_inst); +/** + * @brief Lookup a memory instance by name + * + * @param module_inst The module instance + * @param name The name of the memory instance + * + * @return The memory instance if found, NULL otherwise + */ +WASM_RUNTIME_API_EXTERN wasm_memory_inst_t +wasm_runtime_lookup_memory(const wasm_module_inst_t module_inst, + const char *name); + +/** + * @brief Get the default memory instance + * + * @param module_inst The module instance + * + * @return The memory instance if found, NULL otherwise + */ +WASM_RUNTIME_API_EXTERN wasm_memory_inst_t +wasm_runtime_get_default_memory(const wasm_module_inst_t module_inst); + +/** + * @brief Get a memory instance by index + * + * @param module_inst The module instance + * @param index The index of the memory instance + * + * @return The memory instance if found, NULL otherwise + */ +WASM_RUNTIME_API_EXTERN wasm_memory_inst_t +wasm_runtime_get_memory(const wasm_module_inst_t module_inst, uint32_t index); + +/** + * @brief Get the current number of pages for a memory instance + * + * @param memory_inst The memory instance + * + * @return The current number of pages + */ +WASM_RUNTIME_API_EXTERN uint64_t +wasm_memory_get_cur_page_count(const wasm_memory_inst_t memory_inst); + +/** + * @brief Get the maximum number of pages for a memory instance + * + * @param memory_inst The memory instance + * + * @return The maximum number of pages + */ +WASM_RUNTIME_API_EXTERN uint64_t +wasm_memory_get_max_page_count(const wasm_memory_inst_t memory_inst); + +/** + * @brief Get the number of bytes per page for a memory instance + * + * @param memory_inst The memory instance + * + * @return The number of bytes per page + */ +WASM_RUNTIME_API_EXTERN uint64_t +wasm_memory_get_bytes_per_page(const wasm_memory_inst_t memory_inst); + +/** + * @brief Get the shared status for a memory instance + * + * @param memory_inst The memory instance + * + * @return True if shared, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_memory_get_shared(const wasm_memory_inst_t memory_inst); + +/** + * @brief Get the base address for a memory instance + * + * @param memory_inst The memory instance + * + * @return The base address on success, false otherwise + */ +WASM_RUNTIME_API_EXTERN void * +wasm_memory_get_base_address(const wasm_memory_inst_t memory_inst); + +/** + * @brief Enlarge a memory instance by a number of pages + * + * @param memory_inst The memory instance + * @param inc_page_count The number of pages to add + * + * @return True if successful, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_memory_enlarge(wasm_memory_inst_t memory_inst, uint64_t inc_page_count); + /** * Call the given WASM function of a WASM module instance with * arguments (bytecode and AoT). diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index f70f9cb73..e8f4c749e 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1323,42 +1323,6 @@ export_tags_instantiate(const WASMModule *module, } #endif /* end of WASM_ENABLE_TAGS != 0 */ -#if WASM_ENABLE_MULTI_MODULE != 0 -static void -export_globals_deinstantiate(WASMExportGlobInstance *globals) -{ - if (globals) - wasm_runtime_free(globals); -} - -static WASMExportGlobInstance * -export_globals_instantiate(const WASMModule *module, - WASMModuleInstance *module_inst, - uint32 export_glob_count, char *error_buf, - uint32 error_buf_size) -{ - WASMExportGlobInstance *export_globals, *export_global; - WASMExport *export = module->exports; - uint32 i; - uint64 total_size = - sizeof(WASMExportGlobInstance) * (uint64)export_glob_count; - - if (!(export_global = export_globals = - runtime_malloc(total_size, error_buf, error_buf_size))) { - return NULL; - } - - for (i = 0; i < module->export_count; i++, export ++) - if (export->kind == EXPORT_KIND_GLOBAL) { - export_global->name = export->name; - export_global->global = &module_inst->e->globals[export->index]; - export_global++; - } - - bh_assert((uint32)(export_global - export_globals) == export_glob_count); - return export_globals; -} - #if WASM_ENABLE_MULTI_MEMORY != 0 static void export_memories_deinstantiate(WASMExportMemInstance *memories) @@ -1396,6 +1360,42 @@ export_memories_instantiate(const WASMModule *module, } #endif /* end of if WASM_ENABLE_MULTI_MEMORY != 0 */ +#if WASM_ENABLE_MULTI_MODULE != 0 +static void +export_globals_deinstantiate(WASMExportGlobInstance *globals) +{ + if (globals) + wasm_runtime_free(globals); +} + +static WASMExportGlobInstance * +export_globals_instantiate(const WASMModule *module, + WASMModuleInstance *module_inst, + uint32 export_glob_count, char *error_buf, + uint32 error_buf_size) +{ + WASMExportGlobInstance *export_globals, *export_global; + WASMExport *export = module->exports; + uint32 i; + uint64 total_size = + sizeof(WASMExportGlobInstance) * (uint64)export_glob_count; + + if (!(export_global = export_globals = + runtime_malloc(total_size, error_buf, error_buf_size))) { + return NULL; + } + + for (i = 0; i < module->export_count; i++, export ++) + if (export->kind == EXPORT_KIND_GLOBAL) { + export_global->name = export->name; + export_global->global = &module_inst->e->globals[export->index]; + export_global++; + } + + bh_assert((uint32)(export_global - export_globals) == export_glob_count); + return export_globals; +} + #endif /* end of if WASM_ENABLE_MULTI_MODULE != 0 */ static WASMFunctionInstance * @@ -2388,11 +2388,13 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, /* export */ module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC); +#if WASM_ENABLE_MULTI_MEMORY != 0 + module_inst->export_memory_count = + get_export_count(module, EXPORT_KIND_MEMORY); +#endif #if WASM_ENABLE_MULTI_MODULE != 0 module_inst->export_table_count = get_export_count(module, EXPORT_KIND_TABLE); - module_inst->export_memory_count = - get_export_count(module, EXPORT_KIND_MEMORY); #if WASM_ENABLE_TAGS != 0 module_inst->e->export_tag_count = get_export_count(module, EXPORT_KIND_TAG); @@ -2432,7 +2434,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, module, module_inst, module_inst->export_global_count, error_buf, error_buf_size))) #endif -#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_MULTI_MEMORY != 0 +#if WASM_ENABLE_MULTI_MEMORY != 0 || (module_inst->export_memory_count > 0 && !(module_inst->export_memories = export_memories_instantiate( module, module_inst, module_inst->export_memory_count, @@ -3240,7 +3242,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) export_globals_deinstantiate(module_inst->export_globals); #endif -#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_MULTI_MEMORY != 0 +#if WASM_ENABLE_MULTI_MEMORY != 0 export_memories_deinstantiate(module_inst->export_memories); #endif @@ -3292,17 +3294,6 @@ wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name) return NULL; } -#if WASM_ENABLE_MULTI_MODULE != 0 -WASMGlobalInstance * -wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name) -{ - uint32 i; - for (i = 0; i < module_inst->export_global_count; i++) - if (!strcmp(module_inst->export_globals[i].name, name)) - return module_inst->export_globals[i].global; - return NULL; -} - WASMMemoryInstance * wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name) { @@ -3314,10 +3305,23 @@ wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name) return NULL; #else (void)module_inst->export_memories; + if (!module_inst->memories) + return NULL; return module_inst->memories[0]; #endif } +#if WASM_ENABLE_MULTI_MODULE != 0 +WASMGlobalInstance * +wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name) +{ + uint32 i; + for (i = 0; i < module_inst->export_global_count; i++) + if (!strcmp(module_inst->export_globals[i].name, name)) + return module_inst->export_globals[i].global; + return NULL; +} + WASMTableInstance * wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name) { diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 8666541f2..c43018695 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -539,13 +539,13 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, WASMFunctionInstance * wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name); +WASMMemoryInstance * +wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name); + #if WASM_ENABLE_MULTI_MODULE != 0 WASMGlobalInstance * wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name); -WASMMemoryInstance * -wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name); - WASMTableInstance * wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name);