Optimize for multi-module support in AOT mode (#3563)

- Split the `aot_loader_resolve_function` into two functions to prevent
  redundant module lookups and loads
- Access pre-associated module instances from `import_func_module_insts`,
  avoiding unnecessary instance lookups and improving performance
This commit is contained in:
Xenia Lu 2024-06-26 09:56:01 +08:00 committed by GitHub
parent 867dbd8912
commit 6754b62195
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 78 additions and 31 deletions

View File

@ -591,15 +591,17 @@ str2uint64(const char *buf, uint64 *p_res);
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
static void * static void *
aot_loader_resolve_function(const char *module_name, const char *function_name, aot_loader_resolve_function(const AOTModule *module, const char *function_name,
const AOTFuncType *expected_function_type, const AOTFuncType *expected_function_type,
char *error_buf, uint32 error_buf_size) char *error_buf, uint32 error_buf_size);
static void *
aot_loader_resolve_function_ex(const char *module_name,
const char *function_name,
const AOTFuncType *expected_function_type,
char *error_buf, uint32 error_buf_size)
{ {
WASMModuleCommon *module_reg; WASMModuleCommon *module_reg;
void *function = NULL;
AOTExport *export = NULL;
AOTModule *module = NULL;
AOTFuncType *target_function_type = NULL;
module_reg = wasm_runtime_find_module_registered(module_name); module_reg = wasm_runtime_find_module_registered(module_name);
if (!module_reg || module_reg->module_type != Wasm_Module_AoT) { if (!module_reg || module_reg->module_type != Wasm_Module_AoT) {
@ -608,10 +610,23 @@ aot_loader_resolve_function(const char *module_name, const char *function_name,
set_error_buf(error_buf, error_buf_size, "unknown import"); set_error_buf(error_buf, error_buf_size, "unknown import");
return NULL; return NULL;
} }
return aot_loader_resolve_function((AOTModule *)module_reg, function_name,
expected_function_type, error_buf,
error_buf_size);
}
module = (AOTModule *)module_reg; static void *
export = loader_find_export(module_reg, module_name, function_name, aot_loader_resolve_function(const AOTModule *module, const char *function_name,
EXPORT_KIND_FUNC, error_buf, error_buf_size); const AOTFuncType *expected_function_type,
char *error_buf, uint32 error_buf_size)
{
void *function = NULL;
AOTExport *export = NULL;
AOTFuncType *target_function_type = NULL;
export = loader_find_export((WASMModuleCommon *)module, module->name,
function_name, EXPORT_KIND_FUNC, error_buf,
error_buf_size);
if (!export) { if (!export) {
return NULL; return NULL;
} }
@ -633,7 +648,7 @@ aot_loader_resolve_function(const char *module_name, const char *function_name,
if (!wasm_type_equal((WASMType *)expected_function_type, if (!wasm_type_equal((WASMType *)expected_function_type,
(WASMType *)target_function_type, module->types, (WASMType *)target_function_type, module->types,
module->type_count)) { module->type_count)) {
LOG_DEBUG("%s.%s failed the type check", module_name, function_name); LOG_DEBUG("%s.%s failed the type check", module->name, function_name);
set_error_buf(error_buf, error_buf_size, "incompatible import type"); set_error_buf(error_buf, error_buf_size, "incompatible import type");
return NULL; return NULL;
} }
@ -2260,17 +2275,24 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
&import_funcs[i].signature, &import_funcs[i].attachment, &import_funcs[i].signature, &import_funcs[i].attachment,
&import_funcs[i].call_conv_raw); &import_funcs[i].call_conv_raw);
if (!linked_func) { if (!linked_func) {
sub_module = NULL;
if (!wasm_runtime_is_built_in_module(module_name)) { if (!wasm_runtime_is_built_in_module(module_name)) {
sub_module = (AOTModule *)wasm_runtime_load_depended_module( sub_module = (AOTModule *)wasm_runtime_load_depended_module(
(WASMModuleCommon *)module, module_name, error_buf, (WASMModuleCommon *)module, module_name, error_buf,
error_buf_size); error_buf_size);
if (!sub_module) { if (!sub_module) {
LOG_ERROR("failed to load sub module: %s", error_buf);
return false; return false;
} }
} }
linked_func = aot_loader_resolve_function( if (!sub_module)
module_name, field_name, declare_func_type, error_buf, linked_func = aot_loader_resolve_function_ex(
error_buf_size); module_name, field_name, declare_func_type, error_buf,
error_buf_size);
else
linked_func = aot_loader_resolve_function(
sub_module, field_name, declare_func_type, error_buf,
error_buf_size);
} }
import_funcs[i].func_ptr_linked = linked_func; import_funcs[i].func_ptr_linked = linked_func;
import_funcs[i].func_type = declare_func_type; import_funcs[i].func_type = declare_func_type;

View File

@ -1640,6 +1640,16 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
extra->sub_module_inst_list = &extra->sub_module_inst_list_head; extra->sub_module_inst_list = &extra->sub_module_inst_list_head;
/* Allocate memory for import_func_module_insts*/
if (module->import_func_count > 0
&& !(extra->import_func_module_insts =
runtime_malloc((uint64)module->import_func_count
* sizeof(WASMModuleInstanceCommon *),
error_buf, error_buf_size))) {
goto fail;
}
ret = wasm_runtime_sub_module_instantiate( ret = wasm_runtime_sub_module_instantiate(
(WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst, (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst,
stack_size, heap_size, max_memory_pages, error_buf, error_buf_size); stack_size, heap_size, max_memory_pages, error_buf, error_buf_size);
@ -1980,6 +1990,8 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
wasm_runtime_sub_module_deinstantiate( wasm_runtime_sub_module_deinstantiate(
(WASMModuleInstanceCommon *)module_inst); (WASMModuleInstanceCommon *)module_inst);
if (extra->import_func_module_insts)
wasm_runtime_free(extra->import_func_module_insts);
#endif #endif
if (module_inst->tables) if (module_inst->tables)
@ -2835,10 +2847,6 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
void *attachment; void *attachment;
char buf[96]; char buf[96];
bool ret = false; bool ret = false;
#if WASM_ENABLE_MULTI_MODULE != 0
bh_list *sub_module_list_node = NULL;
const char *sub_inst_name = NULL;
#endif
bh_assert(func_idx < aot_module->import_func_count); bh_assert(func_idx < aot_module->import_func_count);
import_func = aot_module->import_funcs + func_idx; import_func = aot_module->import_funcs + func_idx;
@ -2863,20 +2871,10 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
else if (!import_func->call_conv_raw) { else if (!import_func->call_conv_raw) {
signature = import_func->signature; signature = import_func->signature;
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
sub_module_list_node = WASMModuleInstanceCommon *sub_inst = NULL;
((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list; if ((sub_inst = ((AOTModuleInstanceExtra *)module_inst->e)
sub_module_list_node = bh_list_first_elem(sub_module_list_node); ->import_func_module_insts[func_idx])) {
while (sub_module_list_node) { exec_env = wasm_runtime_get_exec_env_singleton(sub_inst);
sub_inst_name =
((AOTSubModInstNode *)sub_module_list_node)->module_name;
if (strcmp(sub_inst_name, import_func->module_name) == 0) {
exec_env = wasm_runtime_get_exec_env_singleton(
(WASMModuleInstanceCommon *)((AOTSubModInstNode *)
sub_module_list_node)
->module_inst);
break;
}
sub_module_list_node = bh_list_elem_next(sub_module_list_node);
} }
if (exec_env == NULL) { if (exec_env == NULL) {
wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst, wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst,

View File

@ -109,6 +109,7 @@ typedef struct AOTModuleInstanceExtra {
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
bh_list sub_module_inst_list_head; bh_list sub_module_inst_list_head;
bh_list *sub_module_inst_list; bh_list *sub_module_inst_list;
WASMModuleInstanceCommon **import_func_module_insts;
#endif #endif
} AOTModuleInstanceExtra; } AOTModuleInstanceExtra;

View File

@ -7325,6 +7325,32 @@ wasm_runtime_sub_module_instantiate(WASMModuleCommon *module,
(WASMModuleInstance *)sub_module_inst; (WASMModuleInstance *)sub_module_inst;
sub_module_inst_list_node->module_name = sub_module_inst_list_node->module_name =
sub_module_list_node->module_name; sub_module_list_node->module_name;
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
AOTModuleInstance *aot_module_inst =
(AOTModuleInstance *)module_inst;
AOTModule *aot_module = (AOTModule *)module;
AOTModuleInstanceExtra *aot_extra =
(AOTModuleInstanceExtra *)aot_module_inst->e;
uint32 i;
AOTImportFunc *import_func;
for (i = 0; i < aot_module->import_func_count; i++) {
if (aot_extra->import_func_module_insts[i])
continue;
import_func = &aot_module->import_funcs[i];
if (strcmp(sub_module_inst_list_node->module_name,
import_func->module_name)
== 0) {
aot_extra->import_func_module_insts[i] =
(WASMModuleInstanceCommon *)
sub_module_inst_list_node->module_inst;
}
}
}
#endif
bh_list_status ret = bh_list_status ret =
bh_list_insert(sub_module_inst_list, sub_module_inst_list_node); bh_list_insert(sub_module_inst_list, sub_module_inst_list_node);
bh_assert(BH_LIST_SUCCESS == ret); bh_assert(BH_LIST_SUCCESS == ret);