From 88bb4f3c81dcb7c42f19eeac4972f890d9dcb98c Mon Sep 17 00:00:00 2001 From: FromLiQg <56512053+FromLiQg@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:52:02 +0800 Subject: [PATCH] Normalize wasm types (#1378) Normalize wasm types, for the two wasm types, if their parameter types and result types are the same, we only save one copy, so as to reduce the footprint and simplify the type comparison in opcode CALL_INDIRECT. And fix issue in interpreter globals_instantiate, and remove used codes. --- core/iwasm/aot/aot_runtime.c | 22 -------------- core/iwasm/aot/aot_runtime.h | 3 -- core/iwasm/interpreter/wasm.h | 4 +++ core/iwasm/interpreter/wasm_interp_classic.c | 6 ++-- core/iwasm/interpreter/wasm_interp_fast.c | 6 ++-- core/iwasm/interpreter/wasm_loader.c | 31 +++++++++++++++++++- core/iwasm/interpreter/wasm_mini_loader.c | 27 ++++++++++++++++- core/iwasm/interpreter/wasm_runtime.c | 11 ++++--- 8 files changed, 75 insertions(+), 35 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 00a22fff..4515e4a9 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -2205,28 +2205,6 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) } #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ -bool -aot_is_wasm_type_equal(AOTModuleInstance *module_inst, uint32 type1_idx, - uint32 type2_idx) -{ - WASMType *type1, *type2; - AOTModule *module = (AOTModule *)module_inst->aot_module.ptr; - - if (type1_idx >= module->func_type_count - || type2_idx >= module->func_type_count) { - aot_set_exception(module_inst, "type index out of bounds"); - return false; - } - - if (type1_idx == type2_idx) - return true; - - type1 = module->func_types[type1_idx]; - type2 = module->func_types[type2_idx]; - - return wasm_type_equal(type1, type2); -} - bool aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, uint32 *argv) diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index ef3568fd..f9823896 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -633,9 +633,6 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count); * * @return true if equal, false otherwise */ -bool -aot_is_wasm_type_equal(AOTModuleInstance *module_inst, uint32 type1_idx, - uint32 type2_idx); /** * Invoke native function from aot code diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 49961b08..1da303d8 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -122,6 +122,7 @@ typedef struct WASMType { uint16 result_count; uint16 param_cell_num; uint16 ret_cell_num; + uint16 ref_count; /* types of params and results */ uint8 types[1]; } WASMType; @@ -612,6 +613,9 @@ wasm_value_type_cell_num_outside(uint8 value_type) inline static bool wasm_type_equal(const WASMType *type1, const WASMType *type2) { + if (type1 == type2) { + return true; + } return (type1->param_count == type2->param_count && type1->result_count == type2->result_count && memcmp(type1->types, type2->types, diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 24071cf1..9df1df08 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1391,7 +1391,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, tbl_inst = wasm_get_table_inst(module, tbl_idx); val = POP_I32(); - if (val < 0 || val >= (int32)tbl_inst->cur_size) { + if ((uint32)val >= tbl_inst->cur_size) { wasm_set_exception(module, "undefined element"); goto got_exception; } @@ -1419,10 +1419,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, cur_func_type = cur_func->u.func_import->func_type; else cur_func_type = cur_func->u.func->func_type; - if (!wasm_type_equal(cur_type, cur_func_type)) { + + if (cur_type != cur_func_type) { wasm_set_exception(module, "indirect call type mismatch"); goto got_exception; } + #if WASM_ENABLE_TAIL_CALL != 0 if (opcode == WASM_OP_RETURN_CALL_INDIRECT) goto call_func_from_return_call; diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 49cbce5c..6fad303e 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1316,7 +1316,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, val = GET_OPERAND(uint32, I32, 0); frame_ip += 2; - if (val < 0 || val >= (int32)tbl_inst->cur_size) { + if ((uint32)val >= tbl_inst->cur_size) { wasm_set_exception(module, "undefined element"); goto got_exception; } @@ -1344,10 +1344,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, cur_func_type = cur_func->u.func_import->func_type; else cur_func_type = cur_func->u.func->func_type; - if (!wasm_type_equal(cur_type, cur_func_type)) { + + if (cur_type != cur_func_type) { wasm_set_exception(module, "indirect call type mismatch"); goto got_exception; } + #if WASM_ENABLE_TAIL_CALL != 0 if (opcode == WASM_OP_RETURN_CALL_INDIRECT) goto call_func_from_return_call; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 658aa005..cf106c8a 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -415,6 +415,19 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, return node->str; } +static void +destroy_wasm_type(WASMType *type) +{ + if (type->ref_count > 1) { + /* The type is referenced by other types + of current wasm module */ + type->ref_count--; + return; + } + + wasm_runtime_free(type); +} + static bool load_init_expr(const uint8 **p_buf, const uint8 *buf_end, InitializerExpression *init_expr, uint8 type, char *error_buf, @@ -582,6 +595,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } /* Resolve param types and result types */ + type->ref_count = 1; type->param_count = (uint16)param_count; type->result_count = (uint16)result_count; for (j = 0; j < param_count; j++) { @@ -611,6 +625,21 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } type->param_cell_num = (uint16)param_cell_num; type->ret_cell_num = (uint16)ret_cell_num; + + /* If there is already a same type created, use it instead */ + for (j = 0; j < i; j++) { + if (wasm_type_equal(type, module->types[j])) { + if (module->types[j]->ref_count == UINT16_MAX) { + set_error_buf(error_buf, error_buf_size, + "wasm type's ref count too large"); + return false; + } + destroy_wasm_type(type); + module->types[i] = module->types[j]; + module->types[j]->ref_count++; + break; + } + } } } @@ -3729,7 +3758,7 @@ wasm_loader_unload(WASMModule *module) if (module->types) { for (i = 0; i < module->type_count; i++) { if (module->types[i]) - wasm_runtime_free(module->types[i]); + destroy_wasm_type(module->types[i]); } wasm_runtime_free(module->types); } diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index b1a1380c..c7c83d22 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -248,6 +248,19 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, return node->str; } +static void +destroy_wasm_type(WASMType *type) +{ + if (type->ref_count > 1) { + /* The type is referenced by other types + of current wasm module */ + type->ref_count--; + return; + } + + wasm_runtime_free(type); +} + static bool load_init_expr(const uint8 **p_buf, const uint8 *buf_end, InitializerExpression *init_expr, uint8 type, char *error_buf, @@ -372,6 +385,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } /* Resolve param types and result types */ + type->ref_count = 1; type->param_count = (uint16)param_count; type->result_count = (uint16)result_count; for (j = 0; j < param_count; j++) { @@ -394,6 +408,17 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, && ret_cell_num <= UINT16_MAX); type->param_cell_num = (uint16)param_cell_num; type->ret_cell_num = (uint16)ret_cell_num; + + /* If there is already a same type created, use it instead */ + for (j = 0; j < i; ++j) { + if (wasm_type_equal(type, j)) { + bh_assert(module->types[j]->ref_count != UINT16_MAX); + destroy_wasm_type(type); + module->types[i] = module->types[j]; + module->types[j]->ref_count++; + break; + } + } } } @@ -2400,7 +2425,7 @@ wasm_loader_unload(WASMModule *module) if (module->types) { for (i = 0; i < module->type_count; i++) { if (module->types[i]) - wasm_runtime_free(module->types[i]); + destroy_wasm_type(module->types[i]); } wasm_runtime_free(module->types); } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 02284f3a..f66c0660 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -787,13 +787,13 @@ globals_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, if (!(global->import_module_inst = get_sub_module_inst( module_inst, global_import->import_module))) { set_error_buf(error_buf, error_buf_size, "unknown global"); - return NULL; + goto fail; } if (!(global->import_global_inst = wasm_lookup_global( global->import_module_inst, global_import->field_name))) { set_error_buf(error_buf, error_buf_size, "unknown global"); - return NULL; + goto fail; } /* The linked global instance has been initialized, we @@ -829,7 +829,7 @@ globals_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, if (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { if (!check_global_init_expr(module, init_expr->u.global_index, error_buf, error_buf_size)) { - return NULL; + goto fail; } bh_memcpy_s( @@ -853,6 +853,9 @@ globals_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, *p_global_data_size = global_data_offset; (void)module_inst; return globals; +fail: + wasm_runtime_free(globals); + return NULL; } /** @@ -2663,7 +2666,7 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, else cur_func_type = func_inst->u.func->func_type; - if (!wasm_type_equal(cur_type, cur_func_type)) { + if (cur_type != cur_func_type) { wasm_set_exception(module_inst, "indirect call type mismatch"); goto got_exception; }