diff --git a/core/config.h b/core/config.h index f08d828d2..d8cc989eb 100644 --- a/core/config.h +++ b/core/config.h @@ -84,6 +84,7 @@ #endif #define AOT_MAGIC_NUMBER 0x746f6100 +/* FIXME: maybe 5? need a discussion */ #define AOT_CURRENT_VERSION 4 #ifndef WASM_ENABLE_JIT diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index b8d326aab..b2bf1a96d 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -507,6 +507,14 @@ check_feature_flags(char *error_buf, uint32 error_buf_size, } #endif +#if WASM_ENABLE_MULTI_MODULE == 0 + if (feature_flags & WASM_FEATURE_MULTI_MODULE) { + set_error_buf(error_buf, error_buf_size, + "multi-module is not enabled in this build"); + return false; + } +#endif + return true; } @@ -530,7 +538,7 @@ load_target_info_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { - AOTTargetInfo target_info; + AOTTargetInfo target_info = { 0 }; const uint8 *p = buf, *p_end = buf_end; bool is_target_little_endian, is_target_64_bit; @@ -1364,8 +1372,8 @@ fail: static bool load_import_table_list(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, char *error_buf, - uint32 error_buf_size) + AOTModule *module, bool is_load_from_file_buf, + char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; AOTImportTable *import_table; @@ -1382,7 +1390,7 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end, return false; } - /* keep sync with aot_emit_table_info() aot_emit_aot_file */ + /* keep sync with aot_emit_import_table_info() aot_emit_aot_file */ for (i = 0; i < module->import_table_count; i++, import_table++) { read_uint8(buf, buf_end, import_table->table_type.elem_type); read_uint8(buf, buf_end, import_table->table_type.flags); @@ -1391,7 +1399,13 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end, if (wasm_is_type_multi_byte_type(import_table->table_type.elem_type)) { read_uint8(buf, buf_end, ref_type.ref_ht_common.nullable); } + else #endif + { + /* Skip 1 byte */ + buf += 1; + } + read_uint32(buf, buf_end, import_table->table_type.init_size); read_uint32(buf, buf_end, import_table->table_type.max_size); #if WASM_ENABLE_GC != 0 @@ -1409,6 +1423,9 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end, } } #endif + + read_string(buf, buf_end, import_table->module_name); + read_string(buf, buf_end, import_table->table_name); } *p_buf = buf; @@ -1451,7 +1468,13 @@ load_table_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, if (wasm_is_type_multi_byte_type(table->table_type.elem_type)) { read_uint8(buf, buf_end, ref_type.ref_ht_common.nullable); } + else #endif + { + /* Skip 1 byte */ + buf += 1; + } + read_uint32(buf, buf_end, table->table_type.init_size); read_uint32(buf, buf_end, table->table_type.max_size); #if WASM_ENABLE_GC != 0 @@ -1582,14 +1605,15 @@ fail: static bool load_table_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, - char *error_buf, uint32 error_buf_size) + bool is_load_from_file_buf, char *error_buf, + uint32 error_buf_size) { const uint8 *buf = *p_buf; read_uint32(buf, buf_end, module->import_table_count); if (module->import_table_count > 0 - && !load_import_table_list(&buf, buf_end, module, error_buf, - error_buf_size)) + && !load_import_table_list(&buf, buf_end, module, is_load_from_file_buf, + error_buf, error_buf_size)) return false; read_uint32(buf, buf_end, module->table_count); @@ -2475,7 +2499,8 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end, if (!load_memory_info(&p, p_end, module, is_load_from_file_buf, error_buf, error_buf_size) - || !load_table_info(&p, p_end, module, error_buf, error_buf_size) + || !load_table_info(&p, p_end, module, is_load_from_file_buf, error_buf, + error_buf_size) || !load_type_info(&p, p_end, module, error_buf, error_buf_size) || !load_import_global_info(&p, p_end, module, is_load_from_file_buf, error_buf, error_buf_size) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index cee2515c7..80bccb7b0 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -662,73 +662,151 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, return true; } +/** + * Destroy table instances. + */ +static void +tables_deinstantiate(AOTModuleInstance *inst) +{ + if (!inst || !inst->tables) { + return; + } + +#if WASM_ENABLE_MULTI_MODULE == 0 + AOTModule *module = (AOTModule *)inst->module; + /* only imported tables */ + for (uint32 i = 0; i < module->import_table_count; i++) { + WASMTableInstance *table = inst->tables[i]; + if (!table) { + continue; + } + + table_elem_type_t *table_elems = + aot_locate_table_elems(module, table, i); + + if (!table_elems) { + continue; + } + + void *table_imported = + ((uint8 *)(table_elems)) - offsetof(WASMTableInstance, elems); + + wasm_runtime_free(table_imported); + } +#endif + + wasm_runtime_free(inst->tables); +} + static bool tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module, - AOTTableInstance *first_tbl_inst, char *error_buf, - uint32 error_buf_size) + AOTTableInstance *tables_data, + const WASMExternInstance *imports, uint32 import_count, + char *error_buf, uint32 error_buf_size) { - uint32 i, global_index, global_data_offset, base_offset, length; - uint64 total_size; - AOTTableInitData *table_seg; - AOTTableInstance *tbl_inst = first_tbl_inst; - - total_size = (uint64)sizeof(AOTTableInstance *) * module_inst->table_count; + uint64 total_size = + (uint64)sizeof(AOTTableInstance *) * module_inst->table_count; if (total_size > 0 && !(module_inst->tables = runtime_malloc(total_size, error_buf, error_buf_size))) { return false; } - /* - * treat import table like a local one until we enable module linking - * in AOT mode - */ - for (i = 0; i != module_inst->table_count; ++i) { - if (i < module->import_table_count) { - AOTImportTable *import_table = module->import_tables + i; - tbl_inst->cur_size = import_table->table_type.init_size; - tbl_inst->max_size = - aot_get_imp_tbl_data_slots(import_table, false); - tbl_inst->elem_type = module->tables[i].table_type.elem_type; + AOTTableInstance *table = tables_data; + uint32 table_index; + for (table_index = 0; table_index < module->import_table_count; + table_index++) { + AOTTableType *table_type = + &((module->import_tables + table_index)->table_type); + + table->cur_size = table_type->init_size; + table->max_size = aot_get_tbl_data_slots(table_type, false); + table->elem_type = table_type->elem_type; #if WASM_ENABLE_GC != 0 - tbl_inst->elem_ref_type.elem_ref_type = - module->tables[i].table_type.elem_ref_type; + table->elem_ref_type.elem_ref_type = table_type->elem_ref_type; #endif + +#if WASM_ENABLE_MULTI_MODULE != 0 + /* Set all elements to -1 or NULL_REF to mark them as uninitialized + * elements */ + memset(table->elems, +#if WASM_ENABLE_GC == 0 + 0xff, +#else + 0x00, +#endif + sizeof(table_elem_type_t) * table->max_size); + +#else + /* use import table elem */ + AOTImportTable *import_table_type = module->import_tables + table_index; + const WASMExternInstance *extern_inst = + wasm_runtime_get_extern_instance(imports, import_count, + WASM_IMPORT_EXPORT_KIND_TABLE, + table_index); + if (!extern_inst) { + LOG_ERROR("missing an import table(%s, %s)", + import_table_type->module_name, + import_table_type->table_name); + return false; } - else { - AOTTable *table = module->tables + (i - module->import_table_count); - tbl_inst->cur_size = table->table_type.init_size; - tbl_inst->max_size = aot_get_tbl_data_slots(table, false); - tbl_inst->elem_type = module->tables[i].table_type.elem_type; + + /* just in case */ +#ifndef NDEBUG + if (strcmp(import_table_type->table_name, extern_inst->field_name)) { + LOG_ERROR("mismatched import table name: expect \"%s\", got \"%s\"", + import_table_type->table_name, extern_inst->field_name); + return false; + } +#endif + + /* store the pointer value */ + table->elems[0] = (table_elem_type_t)extern_inst->u.table->elems; +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ + + module_inst->tables[table_index] = table; + +#if WASM_ENABLE_MULTI_MODULE != 0 + table = + (AOTTableInstance *)((uint8 *)table + + offsetof(AOTTableInstance, elems) + + sizeof(table_elem_type_t) * table->max_size); +#else + table = (AOTTableInstance *)((uint8 *)table + + offsetof(AOTTableInstance, elems) + + sizeof(table_elem_type_t)); +#endif + } + + for (table_index = 0; table_index < module->table_count; table_index++) { + AOTTableType *table_type = + &((module->tables + table_index)->table_type); + + table->cur_size = table_type->init_size; + table->max_size = aot_get_tbl_data_slots(table_type, false); + table->elem_type = table_type->elem_type; #if WASM_ENABLE_GC != 0 - tbl_inst->elem_ref_type.elem_ref_type = - module->tables[i].table_type.elem_ref_type; + table->elem_ref_type.elem_ref_type = table_type->elem_ref_type; #endif - } /* Set all elements to -1 or NULL_REF to mark them as uninitialized * elements */ #if WASM_ENABLE_GC == 0 - memset(tbl_inst->elems, 0xff, - sizeof(table_elem_type_t) * tbl_inst->max_size); + memset(table->elems, 0xff, sizeof(table_elem_type_t) * table->max_size); #else - memset(tbl_inst->elems, 0x00, - sizeof(table_elem_type_t) * tbl_inst->max_size); + memset(table->elems, 0x00, sizeof(table_elem_type_t) * table->max_size); #endif - module_inst->tables[i] = tbl_inst; - tbl_inst = (AOTTableInstance *)((uint8 *)tbl_inst - + offsetof(AOTTableInstance, elems) - + sizeof(table_elem_type_t) - * tbl_inst->max_size); + module_inst->tables[table_index] = table; + table = + (AOTTableInstance *)((uint8 *)table + + offsetof(AOTTableInstance, elems) + + sizeof(table_elem_type_t) * table->max_size); } /* fill table with element segment content */ - for (i = 0; i < module->table_init_data_count; i++) { -#if WASM_ENABLE_GC == 0 - uint32 j; -#endif - table_seg = module->table_init_data_list[i]; + for (uint32 i = 0; i < module->table_init_data_count; i++) { + AOTTableInitData *table_seg = module->table_init_data_list[i]; #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 if (!wasm_elem_is_active(table_seg->mode)) @@ -737,31 +815,32 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module, bh_assert(table_seg->table_index < module_inst->table_count); - tbl_inst = module_inst->tables[table_seg->table_index]; - bh_assert(tbl_inst); - + table = module_inst->tables[table_seg->table_index]; #if WASM_ENABLE_REF_TYPES != 0 bh_assert( table_seg->offset.init_expr_type - == (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST - : INIT_EXPR_TYPE_I32_CONST) + == (table->is_table64 ? INIT_EXPR_TYPE_I64_CONST + : INIT_EXPR_TYPE_I32_CONST) || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST); #else bh_assert(table_seg->offset.init_expr_type - == (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST - : INIT_EXPR_TYPE_I32_CONST) + == (table->is_table64 ? INIT_EXPR_TYPE_I64_CONST + : INIT_EXPR_TYPE_I32_CONST) || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL); #endif + bh_assert(table); /* Resolve table data base offset */ /* TODO: The table64 current implementation assumes table max size * UINT32_MAX, so the offset conversion here is safe */ + uint32 base_offset; if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { - global_index = table_seg->offset.u.global_index; + uint32 global_index = table_seg->offset.u.global_index; + uint32 global_data_offset; if (!check_global_init_expr(module, global_index, error_buf, error_buf_size)) { @@ -784,7 +863,7 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module, /* Copy table data */ /* base_offset only since length might negative */ - if (base_offset > tbl_inst->cur_size) { + if (base_offset > table->cur_size) { #if WASM_ENABLE_REF_TYPES != 0 set_error_buf(error_buf, error_buf_size, "out of bounds table access"); @@ -796,8 +875,8 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module, } /* base_offset + length(could be zero) */ - length = table_seg->value_count; - if (base_offset + length > tbl_inst->cur_size) { + uint32 length = table_seg->value_count; + if (base_offset + length > table->cur_size) { #if WASM_ENABLE_REF_TYPES != 0 set_error_buf(error_buf, error_buf_size, "out of bounds table access"); @@ -813,8 +892,10 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module, * will check the linked table inst owner in future */ #if WASM_ENABLE_GC == 0 - for (j = 0; j < length; j++) { - tbl_inst->elems[base_offset + j] = + table_elem_type_t *table_elems = + aot_locate_table_elems(module, table, table_seg->table_index); + for (uint32 j = 0; j < length; j++) { + table_elems[base_offset + j] = table_seg->init_values[j].u.ref_index; } #endif @@ -856,11 +937,34 @@ memory_deinstantiate(AOTMemoryInstance *memory) static void memories_deinstantiate(AOTModuleInstance *module_inst) { - if (!module_inst->memories) + if (!module_inst->memories) { return; + } - for (uint32 i = 0; i < module_inst->memory_count; i++) { - memory_deinstantiate(module_inst->memories[i]); + uint32 mem_index = 0; + AOTModule *module = (AOTModule *)module_inst->module; + for (; mem_index < module->import_memory_count; mem_index++) { + AOTMemoryInstance *memory = module_inst->memories[mem_index]; + if (!memory) { + continue; + } + + memory_deinstantiate(memory); + +#if WASM_ENABLE_MULTI_MODULE == 0 && WASM_ENABLE_SHARED_MEMORY != 0 + /* for spawned only */ + if (!shared_memory_is_shared(memory)) { + continue; + } + + if (shared_memory_get_reference(memory) == 0) { + wasm_runtime_free(memory); + } +#endif + } + + for (; mem_index < module->memory_count; mem_index++) { + memory_deinstantiate(module_inst->memories[mem_index]); } wasm_runtime_free(module_inst->memories); @@ -958,7 +1062,7 @@ memory_instantiate(const AOTModule *module, AOTModuleInstance *parent, < (uint64)num_bytes_per_page * init_page_count) { /* Insert app heap before __heap_base */ aux_heap_base = module->aux_heap_base; - bytes_of_last_page = aux_heap_base % num_bytes_per_page; + bytes_of_last_page = (uint32)(aux_heap_base % num_bytes_per_page); if (bytes_of_last_page == 0) bytes_of_last_page = num_bytes_per_page; bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; @@ -968,7 +1072,7 @@ memory_instantiate(const AOTModule *module, AOTModuleInstance *parent, heap_offset = aux_heap_base; aux_heap_base += heap_size; - bytes_of_last_page = aux_heap_base % num_bytes_per_page; + bytes_of_last_page = (uint32)(aux_heap_base % num_bytes_per_page); if (bytes_of_last_page == 0) bytes_of_last_page = num_bytes_per_page; bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; @@ -1959,21 +2063,26 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, */ for (i = 0; i != module->import_table_count; ++i) { table_size += offsetof(AOTTableInstance, elems); +#if WASM_ENABLE_MULTI_MODULE != 0 table_size += (uint64)sizeof(table_elem_type_t) - * (uint64)aot_get_imp_tbl_data_slots( - module->import_tables + i, false); + * (uint64)aot_get_tbl_data_slots( + &(module->import_tables + i)->table_type, false); +#else + /* keep a reference to the imported table's elem */ + table_size += sizeof(void *); +#endif } for (i = 0; i != module->table_count; ++i) { table_size += offsetof(AOTTableInstance, elems); - table_size += - (uint64)sizeof(table_elem_type_t) - * (uint64)aot_get_tbl_data_slots(module->tables + i, false); + table_size += (uint64)sizeof(table_elem_type_t) + * (uint64)aot_get_tbl_data_slots( + &((module->tables + i)->table_type), false); } total_size += table_size; /* The offset of AOTModuleInstanceExtra, make it 8-byte aligned */ - total_size = (total_size + 7LL) & ~7LL; + total_size = (total_size + 7ULL) & ~7ULL; extra_info_offset = (uint32)total_size; total_size += sizeof(AOTModuleInstanceExtra); @@ -2093,8 +2202,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, /* Initialize table info */ p += module->global_data_size; module_inst->table_count = module->table_count + module->import_table_count; - if (!tables_instantiate(module_inst, module, (AOTTableInstance *)p, - error_buf, error_buf_size)) + if (!tables_instantiate(module_inst, module, (AOTTableInstance *)p, imports, + import_count, error_buf, error_buf_size)) goto fail; /* Initialize memory space */ @@ -2187,7 +2296,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, table_inst = module_inst->tables[i]; bh_assert(table_inst); - table_data = table_inst->elems; + table_data = aot_locate_table_elems(module, table_inst, i); bh_assert(table_data); for (j = 0; j < table_inst->cur_size; j++) { @@ -2217,7 +2326,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, table = module_inst->tables[table_init_data->table_index]; bh_assert(table); - table_data = table->elems; + table_data = + aot_locate_table_elems(module, table, table_init_data->table_index); bh_assert(table_data); wasm_runtime_get_table_inst_elem_type( @@ -2392,8 +2502,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free(extra->import_func_module_insts); #endif - if (module_inst->tables) - wasm_runtime_free(module_inst->tables); + tables_deinstantiate(module_inst); if (module_inst->memories) memories_deinstantiate(module_inst); @@ -2451,6 +2560,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) #if WASM_ENABLE_REF_TYPES != 0 bh_bitmap_delete(common->elem_dropped); #endif + (void)common; wasm_runtime_free(module_inst); } @@ -3372,7 +3482,10 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, goto fail; } - tbl_elem_val = ((table_elem_type_t *)tbl_inst->elems)[table_elem_idx]; + table_elem_type_t *table_elems = + aot_locate_table_elems(aot_module, tbl_inst, tbl_idx); + + tbl_elem_val = table_elems[table_elem_idx]; if (tbl_elem_val == NULL_REF) { aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT); goto fail; @@ -3793,6 +3906,7 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst, for (i = 0; i < module_inst->table_count; i++) { tbl_inst = module_inst->tables[i]; mem_conspn->tables_size += offsetof(AOTTableInstance, elems); + /*TODO: correct import tables' elems */ mem_conspn->tables_size += sizeof(uint32) * tbl_inst->max_size; } @@ -3834,7 +3948,6 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, AOTTableInstance *tbl_inst; AOTTableInitData *tbl_seg; const AOTModule *module = (AOTModule *)module_inst->module; - table_elem_type_t *table_elems; InitializerExpression *tbl_seg_init_values = NULL, *init_values; uint32 i, tbl_seg_len = 0; #if WASM_ENABLE_GC != 0 @@ -3865,7 +3978,9 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, return; } - table_elems = tbl_inst->elems + dst_offset; + table_elem_type_t *table_elems = + aot_locate_table_elems(module, tbl_inst, tbl_idx); + table_elems += dst_offset; init_values = tbl_seg_init_values + src_offset; for (i = 0; i < length; i++) { @@ -3909,16 +4024,21 @@ aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx, return; } + table_elem_type_t *src_table_elems = aot_locate_table_elems( + (AOTModule *)module_inst->module, src_tbl_inst, src_tbl_idx); + src_table_elems += src_offset; + + table_elem_type_t *dst_table_elems = aot_locate_table_elems( + (AOTModule *)module_inst->module, dst_tbl_inst, dst_tbl_idx); + dst_table_elems += dst_offset; + /* if src_offset >= dst_offset, copy from front to back */ /* if src_offset < dst_offset, copy from back to front */ /* merge all together */ - bh_memmove_s((uint8 *)dst_tbl_inst + offsetof(AOTTableInstance, elems) - + dst_offset * sizeof(table_elem_type_t), + bh_memmove_s(dst_table_elems, (dst_tbl_inst->cur_size - dst_offset) * sizeof(table_elem_type_t), - (uint8 *)src_tbl_inst + offsetof(AOTTableInstance, elems) - + src_offset * sizeof(table_elem_type_t), - length * sizeof(table_elem_type_t)); + src_table_elems, length * sizeof(table_elem_type_t)); } void @@ -3935,8 +4055,11 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length, return; } + table_elem_type_t *table_elems = aot_locate_table_elems( + (AOTModule *)module_inst->module, tbl_inst, tbl_idx); + for (; length != 0; data_offset++, length--) { - tbl_inst->elems[data_offset] = val; + table_elems[data_offset] = val; } } @@ -3978,8 +4101,11 @@ aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 inc_size, } /* fill in */ + table_elem_type_t *table_elems = aot_locate_table_elems( + (AOTModule *)module_inst->module, tbl_inst, tbl_idx); + for (i = 0; i < inc_size; ++i) { - tbl_inst->elems[tbl_inst->cur_size + i] = init_val; + table_elems[tbl_inst->cur_size + i] = init_val; } tbl_inst->cur_size = total_size; @@ -5199,6 +5325,7 @@ aot_global_traverse_gc_rootset(AOTModuleInstance *module_inst, void *heap) static bool aot_table_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap) { + AOTModule *module = (AOTModule *)module_inst->module; AOTTableInstance **tables = (AOTTableInstance **)module_inst->tables; AOTTableInstance *table; uint32 table_count = module_inst->table_count, i, j; @@ -5206,7 +5333,9 @@ aot_table_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap) for (i = 0; i < table_count; i++) { table = tables[i]; - table_elems = (WASMObjectRef *)table->elems; + + table_elems = (WASMObjectRef *)aot_locate_table_elems(module, table, i); + for (j = 0; j < table->cur_size; j++) { gc_obj = table_elems[j]; if (wasm_obj_is_created_from_heap(gc_obj)) { @@ -5343,7 +5472,7 @@ aot_const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, else #endif { - bh_memcpy_s(c_str, len, str, (uint32)len); + bh_memcpy_s(c_str, (uint32)len, str, (uint32)len); } if ((value = bh_hash_map_find(set, c_str))) { @@ -5381,7 +5510,7 @@ aot_set_module_name(AOTModule *module, const char *name, char *error_buf, return false; module->name = aot_const_str_set_insert((const uint8 *)name, - (uint32)(strlen(name) + 1), module, + (int32)(strlen(name) + 1), module, #if (WASM_ENABLE_WORD_ALIGN_READ != 0) false, #endif @@ -5535,20 +5664,25 @@ aot_resolve_import_func(AOTModule *module, AOTImportFunc *import_func) */ int32 aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst, - WASMExternInstance *out, int32 out_len) + WASMExternInstance *out, uint32 out_len) { if (!module || !inst || !out) return -1; - int32 spawned_import_count = + int32 spawned_import_count_s = wasm_runtime_get_import_count((WASMModuleCommon *)module); + if (spawned_import_count_s < 0) { + return -1; + } + + uint32 spawned_import_count = spawned_import_count_s; if (spawned_import_count > out_len) { LOG_WARNING("The number of imported functions is more than the " "length of provided buffer "); return -1; } - for (int32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) { + for (uint32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) { wasm_import_t import_type = { 0 }; wasm_runtime_get_import_type((WASMModuleCommon *)module, i, @@ -5577,20 +5711,21 @@ aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst, void aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports, - int32 import_count) + uint32 import_count) { if (!module || !imports) return; int32 spawned_import_count = wasm_runtime_get_import_count((WASMModuleCommon *)module); - if (spawned_import_count > import_count) { + if (spawned_import_count < 0 + || (uint32)spawned_import_count > import_count) { LOG_WARNING("The number of imported functions is more than the " "length of provided buffer "); return; } - for (int32 i = 0; i < import_count; i++) { + for (uint32 i = 0; i < import_count; i++) { WASMExternInstance *import = imports + i; if (import->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { @@ -5608,3 +5743,42 @@ aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports, } } #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */ + +AOTTableInstance * +aot_create_table(const AOTModule *module, const AOTTableType *type) +{ + uint32 max_size = aot_get_tbl_data_slots(type, false); + uint64 table_size = offsetof(AOTTableInstance, elems) + + sizeof(table_elem_type_t) * (uint64)max_size; + + AOTTableInstance *table = runtime_malloc(table_size, NULL, 0); + if (!table) { + return NULL; + } + + table->cur_size = type->init_size; + table->elem_type = type->elem_type; + table->max_size = max_size; +#if WASM_ENABLE_GC != 0 + table->elem_ref_type.elem_ref_type = type->elem_ref_type; +#endif + + /* Set all elements to -1 or NULL_REF to mark them as uninitialized + * elements */ +#if WASM_ENABLE_GC == 0 + memset(table->elems, 0xff, sizeof(table_elem_type_t) * table->max_size); +#else + memset(table->elems, 0x00, sizeof(table_elem_type_t) * table->max_size); +#endif + + return table; +} + +void +aot_destroy_table(AOTTableInstance *table) +{ + if (!table) + return; + + wasm_runtime_free(table); +} \ No newline at end of file diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 7bbb572c8..6cfa565fa 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -35,6 +35,7 @@ extern "C" { * and not at the beginning of each function call */ #define WASM_FEATURE_FRAME_PER_FUNCTION (1 << 12) #define WASM_FEATURE_FRAME_NO_FUNC_IDX (1 << 13) +#define WASM_FEATURE_MULTI_MODULE (1 << 14) typedef enum AOTSectionType { AOT_SECTION_TYPE_TARGET_INFO = 0, @@ -484,6 +485,21 @@ typedef struct LLVMProfileData_64 { } LLVMProfileData_64; #endif /* end of WASM_ENABLE_STATIC_PGO != 0 */ +static inline table_elem_type_t * +aot_locate_table_elems(const AOTModule *module, AOTTableInstance *table, + uint32 table_index) +{ +#if WASM_ENABLE_MULTI_MODULE == 0 + if (table_index < module->import_table_count) { + table_elem_type_t **table_elems = + (table_elem_type_t **)(uintptr_t)table->elems; + + return *table_elems; + } +#endif + return table->elems; +} + /** * Load a AOT module from aot file buffer * @param buf the byte buffer which contains the AOT file data @@ -884,13 +900,23 @@ aot_get_module_name(AOTModule *module); #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 int32 aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst, - WASMExternInstance *out, int32 out_len); + WASMExternInstance *out, uint32 out_len); void aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports, - int32 import_count); + uint32 import_count); #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */ +AOTTableInstance * +aot_create_table(const AOTModule *module, const AOTTableType *type); + +bool +aot_set_table_elem(const AOTModule *module, AOTTableInstance *table, + uint32 index, uint32 func_idx); + +void +aot_destroy_table(AOTTableInstance *table); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 0c5e37eab..cbb99bb1b 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -4011,24 +4011,34 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index) #if WASM_ENABLE_INTERP != 0 if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) { - WASMTableInstance *table_interp = - ((WASMModuleInstance *)table->inst_comm_rt) - ->tables[table->table_idx_rt]; - if (index >= table_interp->cur_size) { + WASMModuleInstance *inst_wasm = + (WASMModuleInstance *)table->inst_comm_rt; + WASMModule *module_wasm = inst_wasm->module; + WASMTableInstance *table_wasm = inst_wasm->tables[table->table_idx_rt]; + + if (index >= table_wasm->cur_size) { return NULL; } - ref_idx = (uint32)table_interp->elems[index]; + + table_elem_type_t *table_elems = wasm_locate_table_elems( + module_wasm, table_wasm, table->table_idx_rt); + ref_idx = (uint32)table_elems[index]; } #endif #if WASM_ENABLE_AOT != 0 if (table->inst_comm_rt->module_type == Wasm_Module_AoT) { AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt; + AOTModule *module_aot = (AOTModule *)inst_aot->module; AOTTableInstance *table_aot = inst_aot->tables[table->table_idx_rt]; + if (index >= table_aot->cur_size) { return NULL; } - ref_idx = (uint32)table_aot->elems[index]; + + table_elem_type_t *table_elems = + aot_locate_table_elems(module_aot, table_aot, table->table_idx_rt); + ref_idx = (uint32)table_elems[index]; } #endif @@ -4080,17 +4090,19 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index, #if WASM_ENABLE_INTERP != 0 if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) { - WASMTableInstance *table_interp = - ((WASMModuleInstance *)table->inst_comm_rt) - ->tables[table->table_idx_rt]; + WASMModuleInstance *inst_wasm = + (WASMModuleInstance *)table->inst_comm_rt; + WASMModule *module_wasm = inst_wasm->module; + WASMTableInstance *table_wasm = inst_wasm->tables[table->table_idx_rt]; - if (index >= table_interp->cur_size) { + if (index >= table_wasm->cur_size) { return false; } - p_ref_idx = (uint32 *)(table_interp->elems + index); - function_count = - ((WASMModuleInstance *)table->inst_comm_rt)->e->function_count; + table_elem_type_t *table_elems = wasm_locate_table_elems( + module_wasm, table_wasm, table->table_idx_rt); + p_ref_idx = (uint32 *)(table_elems + index); + function_count = inst_wasm->e->function_count; } #endif @@ -4104,7 +4116,9 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index, return false; } - p_ref_idx = (uint32 *)(table_aot->elems + index); + table_elem_type_t *table_elems = + aot_locate_table_elems(module_aot, table_aot, table->table_idx_rt); + p_ref_idx = (uint32 *)(table_elems + index); function_count = module_aot->func_count; } #endif diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 487d812a9..10691956b 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -454,6 +454,55 @@ wasm_runtime_get_exec_env_tls() } #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ +/* FIXME: remove when merging wasm_table_inst_t with WASMTableInstance and + * AOTTableInstance */ +#if WASM_ENABLE_INTERP != 0 +static void +WASMTableInstance_to_wasm_table_inst_t(const WASMModule *module, + const WASMTableInstance *table_rt, + int64 table_index, + wasm_table_inst_t *out) +{ + out->elem_kind = val_type_to_val_kind(table_rt->elem_type); + out->max_size = table_rt->max_size; + out->cur_size = table_rt->cur_size; + + /* table_index < 0, it means it is created by host */ + uintptr_t tmp = (uintptr_t)table_rt->elems; + if (table_index > 0 && table_index < (int64)module->import_table_count) { + out->elems = *(void **)tmp; + } + else { + out->elems = (void *)tmp; + } + + bh_assert(out->elems); +} +#endif + +#if WASM_ENABLE_AOT != 0 +static void +AOTTableInstance_to_wasm_table_inst_t(const AOTModule *module, + const AOTTableInstance *table_rt, + int64 table_index, wasm_table_inst_t *out) +{ + out->elem_kind = val_type_to_val_kind(table_rt->elem_type); + out->max_size = table_rt->max_size; + out->cur_size = table_rt->cur_size; + + /* table_index < 0, it means it is created by host */ + uintptr_t tmp = (uintptr_t)table_rt->elems; + if (table_index > 0 && table_index < (int64)module->import_table_count) { + out->elems = *(void **)tmp; + } + else { + out->elems = (void *)tmp; + } + + bh_assert(out->elems); +} +#endif + static bool wasm_runtime_env_init(void) { @@ -2122,20 +2171,23 @@ wasm_runtime_get_export_table_inst(WASMModuleInstanceCommon *const module_inst, const WASMModuleInstance *wasm_module_inst = (const WASMModuleInstance *)module_inst; const WASMModule *wasm_module = wasm_module_inst->module; - uint32 i; - for (i = 0; i < wasm_module->export_count; i++) { + + for (uint32 i = 0; i < wasm_module->export_count; i++) { const WASMExport *wasm_export = &wasm_module->exports[i]; - if ((wasm_export->kind == WASM_IMPORT_EXPORT_KIND_TABLE) - && !strcmp(wasm_export->name, name)) { - const WASMTableInstance *wasm_table_inst = - wasm_module_inst->tables[wasm_export->index]; - table_inst->elem_kind = - val_type_to_val_kind(wasm_table_inst->elem_type); - table_inst->cur_size = wasm_table_inst->cur_size; - table_inst->max_size = wasm_table_inst->max_size; - table_inst->elems = (void *)wasm_table_inst->elems; - return true; + + if (wasm_export->kind != WASM_IMPORT_EXPORT_KIND_TABLE) { + continue; } + + if (strcmp(wasm_export->name, name)) { + continue; + } + + const WASMTableInstance *wasm_table_inst = + wasm_module_inst->tables[wasm_export->index]; + WASMTableInstance_to_wasm_table_inst_t( + wasm_module, wasm_table_inst, wasm_export->index, table_inst); + return true; } } #endif @@ -2144,20 +2196,23 @@ wasm_runtime_get_export_table_inst(WASMModuleInstanceCommon *const module_inst, const AOTModuleInstance *aot_module_inst = (AOTModuleInstance *)module_inst; const AOTModule *aot_module = (AOTModule *)aot_module_inst->module; - uint32 i; - for (i = 0; i < aot_module->export_count; i++) { + + for (uint32 i = 0; i < aot_module->export_count; i++) { const AOTExport *aot_export = &aot_module->exports[i]; - if ((aot_export->kind == WASM_IMPORT_EXPORT_KIND_TABLE) - && !strcmp(aot_export->name, name)) { - const AOTTableInstance *aot_table_inst = - aot_module_inst->tables[aot_export->index]; - table_inst->elem_kind = - val_type_to_val_kind(aot_table_inst->elem_type); - table_inst->cur_size = aot_table_inst->cur_size; - table_inst->max_size = aot_table_inst->max_size; - table_inst->elems = (void *)aot_table_inst->elems; - return true; + + if (aot_export->kind != WASM_IMPORT_EXPORT_KIND_TABLE) { + continue; } + + if (strcmp(aot_export->name, name)) { + continue; + } + + const AOTTableInstance *aot_table_inst = + aot_module_inst->tables[aot_export->index]; + AOTTableInstance_to_wasm_table_inst_t( + aot_module, aot_table_inst, aot_export->index, table_inst); + return true; } } #endif @@ -4102,8 +4157,8 @@ wasm_runtime_get_import_count(WASMModuleCommon *const module) } void -wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index, - wasm_import_t *import_type) +wasm_runtime_get_import_type(WASMModuleCommon *const module, + uint32 import_index, wasm_import_t *import_type) { if (!import_type) { bh_assert(0); @@ -4121,7 +4176,7 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index, if (module->module_type == Wasm_Module_AoT) { const AOTModule *aot_module = (const AOTModule *)module; - uint32 func_index = (uint32)import_index; + uint32 func_index = import_index; if (func_index < aot_module->import_func_count) { const AOTImportFunc *aot_import_func = &aot_module->import_funcs[func_index]; @@ -4182,7 +4237,7 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index, if (module->module_type == Wasm_Module_Bytecode) { const WASMModule *wasm_module = (const WASMModule *)module; - if ((uint32)import_index >= wasm_module->import_count) { + if (import_index >= wasm_module->import_count) { bh_assert(0); return; } @@ -6470,7 +6525,6 @@ static void interp_mark_all_externrefs(WASMModuleInstance *module_inst) { uint32 i, j, externref_idx; - table_elem_type_t *table_data; uint8 *global_data = module_inst->global_data; WASMGlobalInstance *global; WASMTableInstance *table; @@ -6493,9 +6547,11 @@ interp_mark_all_externrefs(WASMModuleInstance *module_inst) &max_size); if (elem_type == VALUE_TYPE_EXTERNREF) { - table_data = table->elems; + table_elem_type_t *table_elems = + wasm_locate_table_elems(module_inst->module, table, i); + for (j = 0; j < table->cur_size; j++) { - externref_idx = table_data[j]; + externref_idx = (uint32)table_elems[j]; mark_externref(externref_idx); } } @@ -6513,7 +6569,7 @@ aot_mark_all_externrefs(AOTModuleInstance *module_inst) const AOTModule *module = (AOTModule *)module_inst->module; const AOTTable *table = module->tables; const AOTGlobal *global = module->globals; - const AOTTableInstance *table_inst; + AOTTableInstance *table_inst; for (i = 0; i < module->global_count; i++, global++) { if (global->type.val_type == VALUE_TYPE_EXTERNREF) { @@ -6525,8 +6581,11 @@ aot_mark_all_externrefs(AOTModuleInstance *module_inst) for (i = 0; i < module->table_count; i++) { table_inst = module_inst->tables[i]; if ((table + i)->table_type.elem_type == VALUE_TYPE_EXTERNREF) { + table_elem_type_t *table_elems = + aot_locate_table_elems(module, table_inst, i); + while (j < table_inst->cur_size) { - mark_externref(table_inst->elems[j++]); + mark_externref(table_elems[j++]); } } } @@ -7759,6 +7818,99 @@ wasm_runtime_is_underlying_binary_freeable(WASMModuleCommon *const module) return true; } +wasm_table_inst_t * +wasm_runtime_create_table(WASMModuleCommon *const module, + wasm_table_type_t const type) +{ + if (!module || !type) + return NULL; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + wasm_table_inst_t *out_table = + runtime_malloc(sizeof(wasm_table_inst_t), NULL, NULL, 0); + if (!out_table) + return NULL; + + WASMTableInstance *wasm_table = + wasm_create_table((WASMModule *)module, type); + if (!wasm_table) { + wasm_runtime_free(wasm_table); + return NULL; + } + + WASMTableInstance_to_wasm_table_inst_t((WASMModule *)module, wasm_table, + -1, out_table); + /* TODO: wasm_table ownership ?*/ + return out_table; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + wasm_table_inst_t *out_table = + runtime_malloc(sizeof(wasm_table_inst_t), NULL, NULL, 0); + if (!out_table) + return NULL; + + AOTTableInstance *aot_table = + aot_create_table((AOTModule *)module, type); + if (!aot_table) { + wasm_runtime_free(aot_table); + return NULL; + } + + AOTTableInstance_to_wasm_table_inst_t((AOTModule *)module, aot_table, + -1, out_table); + /* TODO: aot_table ownership ?*/ + return out_table; + } +#endif + + LOG_ERROR("create table failed, invalid module type"); + return NULL; +} + +void +wasm_runtime_destroy_table(WASMModuleCommon *const module, + wasm_table_inst_t *table) +{ + if (!module || !table) + return; + +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + /* + * TODO: for now we only release the shell itself + * but after optimize the wasm_table_inst_t in wasm_export.h + * we shall focus on wasm_table itself + */ + // void *wasm_table = + // (void *)((uint8 *)table - offsetof(WASMTableInstance, elems)); + // wasm_destroy_table((WASMTableInstance *)wasm_table); + wasm_runtime_free(table); + return; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + /* + * TODO: for now we only release the shell itself + * but after optimize the wasm_table_inst_t in wasm_export.h + * we shall focus on aot_table itself + */ + // void *aot_table = + // (void *)((uint8 *)table - offsetof(AOTTableInstance, elems)); + // aot_destroy_table((AOTTableInstance *)aot_table); + wasm_runtime_free(table); + return; + } +#endif + + LOG_ERROR("destroy table failed, invalid module type"); +} + /*TODO: take us(below) out when have a linker */ WASMModuleInstanceCommon * wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module, @@ -7766,14 +7918,15 @@ wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module, uint32 heap_size, char *error_buf, uint32 error_buf_size) { - int32 import_count = 0; + int32 import_count_s = 0; WASMExternInstance *imports = NULL; - import_count = wasm_runtime_get_import_count(module); - if (import_count < 0) { + import_count_s = wasm_runtime_get_import_count(module); + if (import_count_s < 0) { return NULL; } + uint32 import_count = (uint32)import_count_s; if (import_count) { imports = runtime_malloc(sizeof(WASMExternInstance) * (uint64)import_count, @@ -7797,6 +7950,18 @@ wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module, 0, // max_memory_pages imports, (uint32)import_count, error_buf, error_buf_size); + /* + * during wasm_instantiate()/aot_instantiate() + * + * WASModuleInstance->memories[i] takes the ownership of + * WASMExternInstance->u.memory + * + * WASModuleInstance->tables[i].elems takes + * the ownership of WASMExternInstance->u.table + * + * WASMModuleInstance->e->globals[i] copies the content of + * WASMExternInstance->u.global + */ if (imports) { wasm_runtime_free(imports); } @@ -7806,30 +7971,40 @@ wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module, bool wasm_runtime_create_extern_inst(WASMModuleCommon *module, - wasm_import_t import_type, + wasm_import_t *import_type, WASMExternInstance *out) { if (!out) return false; - LOG_DEBUG("create import(%s,%s) kind %d", import_type.module_name, - import_type.name, import_type.kind); + LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name, + import_type->name, import_type->kind); - out->module_name = import_type.module_name; - out->field_name = import_type.name; - out->kind = import_type.kind; + out->module_name = import_type->module_name; + out->field_name = import_type->name; + out->kind = import_type->kind; - if (import_type.kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { + if (import_type->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { out->u.memory = - wasm_runtime_create_memory(module, import_type.u.memory_type); + wasm_runtime_create_memory(module, import_type->u.memory_type); if (!out->u.memory) { LOG_ERROR("create memory failed\n"); return false; } } + else if (import_type->kind == WASM_IMPORT_EXPORT_KIND_TABLE) { + wasm_table_inst_t *table = + wasm_runtime_create_table(module, import_type->u.table_type); + out->u.table = table; + if (!out->u.table) { + LOG_ERROR("create table failed\n"); + return false; + } + } else { LOG_DEBUG("unimplemented import(%s,%s) kind %d", - import_type.module_name, import_type.name, import_type.kind); + import_type->module_name, import_type->name, + import_type->kind); } return true; @@ -7856,37 +8031,6 @@ wasm_runtime_destroy_extern_inst(WASMModuleCommon *module, extern_inst->field_name = NULL; } -/* - * willn't take the ownership of new_extern_inst - * take the ownership of the content of new_extern_inst - */ -bool -wasm_runtime_overwirte_imports(WASMModuleCommon *module, - WASMExternInstance *orig_extern_inst_list, - WASMExternInstance *new_extern_inst, int32 index) -{ - // argument check - if (!module || !orig_extern_inst_list || !new_extern_inst) { - return false; - } - - // check index with the import count of the module - if (index < 0 || index >= wasm_runtime_get_import_count(module)) { - return false; - } - - // get the targeted extern_inst. allow to be NULL - WASMExternInstance *old_extern_inst = orig_extern_inst_list + index; - - // release the targeted extern_inst if not NULL - wasm_runtime_destroy_extern_inst(module, old_extern_inst); - - // overwrite the targeted extern_inst - bh_memcpy_s(old_extern_inst, sizeof(WASMExternInstance), new_extern_inst, - sizeof(WASMExternInstance)); - return true; -} - /* * Be aware that it will remove all items in the list, regardless of whether * they were created by the runtime (for built-ins) or by users. @@ -7907,23 +8051,24 @@ wasm_runtime_destroy_imports(WASMModuleCommon *module, bool wasm_runtime_create_imports(WASMModuleCommon *module, bool (*module_name_filter)(const char *), - WASMExternInstance *out, int32 out_len) + WASMExternInstance *out, uint32 out_len) { - int32 import_count = wasm_runtime_get_import_count(module); + int32 import_count_s = wasm_runtime_get_import_count(module); - if (import_count < 0) + if (import_count_s < 0) return false; - if (import_count == 0) + if (import_count_s == 0) return true; + uint32 import_count = (uint32)import_count_s; if (!out || out_len < import_count) { LOG_ERROR("invalid arguments"); return false; } - memset(out, 0, sizeof(WASMExternInstance) * (uint32)import_count); - for (int32 i = 0; i < import_count; i++) { + memset(out, 0, sizeof(WASMExternInstance) * import_count); + for (uint32 i = 0; i < import_count; i++) { wasm_import_t import_type = { 0 }; wasm_runtime_get_import_type(module, i, &import_type); @@ -7935,7 +8080,7 @@ wasm_runtime_create_imports(WASMModuleCommon *module, } WASMExternInstance *extern_instance = out + i; - if (!wasm_runtime_create_extern_inst(module, import_type, + if (!wasm_runtime_create_extern_inst(module, &import_type, extern_instance)) { wasm_runtime_destroy_imports(module, out); LOG_ERROR("create import failed"); @@ -7948,7 +8093,8 @@ wasm_runtime_create_imports(WASMModuleCommon *module, bool wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module, - WASMExternInstance *out, int32 out_len) + WASMExternInstance *out, + uint32 out_len) { LOG_DEBUG("create imports with builtin"); return wasm_runtime_create_imports(module, wasm_runtime_is_built_in_module, @@ -7964,7 +8110,7 @@ wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module, static int32 wasm_runtime_inherit_imports(WASMModuleCommon *module, WASMModuleInstanceCommon *inst, - WASMExternInstance *out, int32 out_len) + WASMExternInstance *out, uint32 out_len) { #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) { @@ -7988,25 +8134,28 @@ wasm_runtime_instantiate_with_inheritance( WASMExecEnv *exec_env, uint32 stack_size, uint32 heap_size, uint32 max_memory_pages, char *error_buf, uint32 error_buf_size) { - int32 spawned_import_count = wasm_runtime_get_import_count(module); - if (spawned_import_count < 0) { + int32 spawned_import_count_s = wasm_runtime_get_import_count(module); + if (spawned_import_count_s < 0) { return NULL; } - WASMExternInstance *spawned_imports = runtime_malloc( - sizeof(WASMExternInstance) * (uint64)spawned_import_count, NULL, - error_buf, error_buf_size); - if (spawned_imports == NULL) { - LOG_ERROR("Failed to allocate memory for imports"); - return NULL; - } - - int ret = wasm_runtime_inherit_imports(module, parent_inst, spawned_imports, - spawned_import_count); - if (ret != 0) { - LOG_ERROR("Failed to inherit imports"); - wasm_runtime_free(spawned_imports); - return NULL; + uint32 spawned_import_count = (uint32)spawned_import_count_s; + WASMExternInstance *spawned_imports = NULL; + if (spawned_import_count > 0) { + spawned_imports = runtime_malloc(sizeof(WASMExternInstance) + * (uint64)spawned_import_count, + NULL, error_buf, error_buf_size); + if (spawned_imports == NULL) { + LOG_ERROR("Failed to allocate memory for imports"); + return NULL; + } + int ret = wasm_runtime_inherit_imports( + module, parent_inst, spawned_imports, spawned_import_count); + if (ret != 0) { + LOG_ERROR("Failed to inherit imports"); + wasm_runtime_free(spawned_imports); + return NULL; + } } wasm_module_inst_t child_inst = wasm_runtime_instantiate_internal( diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index 2027a5720..2a14d44ef 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -110,6 +110,24 @@ shared_memory_dec_reference(WASMMemoryInstance *memory) return old - 1; } +uint16 +shared_memory_get_reference(WASMMemoryInstance *memory) +{ + bh_assert(shared_memory_is_shared(memory)); + +#if BH_ATOMIC_16_IS_ATOMIC == 0 + os_mutex_lock(&g_shared_memory_lock); +#endif + + uint16 old = BH_ATOMIC_16_FETCH_OR(memory->ref_count, 0); + +#if BH_ATOMIC_16_IS_ATOMIC == 0 + os_mutex_unlock(&g_shared_memory_lock); +#endif + + return old; +} + static korp_mutex * shared_memory_get_lock_pointer(WASMMemoryInstance *memory) { diff --git a/core/iwasm/common/wasm_shared_memory.h b/core/iwasm/common/wasm_shared_memory.h index e1c5154a5..618de6590 100644 --- a/core/iwasm/common/wasm_shared_memory.h +++ b/core/iwasm/common/wasm_shared_memory.h @@ -28,6 +28,9 @@ shared_memory_inc_reference(WASMMemoryInstance *memory); uint16 shared_memory_dec_reference(WASMMemoryInstance *memory); +uint16 +shared_memory_get_reference(WASMMemoryInstance *memory); + #define shared_memory_is_shared(memory) memory->is_shared_memory #define shared_memory_lock(memory) \ diff --git a/core/iwasm/common/wasm_table.c b/core/iwasm/common/wasm_table.c new file mode 100644 index 000000000..e69de29bb diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index f42c27488..2eb4b32a3 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -48,7 +48,7 @@ aot_create_import_memories(const WASMModule *module, uint32 import_memory_count) import_memories = wasm_runtime_malloc((uint32)size); if (!import_memories) { - aot_set_last_error("allocate memory failed."); + aot_set_last_error("allocate import memories failed."); return NULL; } @@ -161,6 +161,89 @@ fail: return NULL; } +static AOTImportTable * +aot_create_import_tables(const WASMModule *module) +{ + uint64 size = sizeof(AOTImportTable) * (uint64)module->import_table_count; + if (size >= UINT32_MAX) { + aot_set_last_error("too big allocate size"); + return NULL; + } + + AOTImportTable *import_tables = wasm_runtime_malloc((uint32)size); + if (!import_tables) { + aot_set_last_error("allocate import tables failed."); + return NULL; + } + + memset(import_tables, 0, (uint32)size); + + for (uint32 i = 0; i < module->import_table_count; i++) { + AOTImportTable *table_aot = import_tables + i; + WASMImport *table_wasm = module->import_tables + i; + + table_aot->module_name = table_wasm->u.table.module_name; + table_aot->table_name = table_wasm->u.table.field_name; + table_aot->table_type.elem_type = + table_wasm->u.table.table_type.elem_type; + table_aot->table_type.flags = table_wasm->u.table.table_type.flags; + table_aot->table_type.init_size = + table_wasm->u.table.table_type.init_size; + table_aot->table_type.max_size = + table_wasm->u.table.table_type.max_size; +#if WASM_ENABLE_GC != 0 + table_aot->table_type.elem_ref_type = + table_wasm->u.table.table_type.elem_ref_type; +#endif + table_aot->table_type.possible_grow = + table_wasm->u.table.table_type.possible_grow; + } + + return import_tables; +} + +static AOTTable * +aot_create_tables(const WASMModule *module) +{ + uint64 size = sizeof(AOTTable) * (uint64)module->table_count; + if (size >= UINT32_MAX) { + aot_set_last_error("too big allocate size"); + return NULL; + } + + AOTTable *tables = wasm_runtime_malloc((uint32)size); + if (!tables) { + aot_set_last_error("allocate tables failed."); + return NULL; + } + + memset(tables, 0, (uint32)size); + + for (uint32 i = 0; i < module->table_count; i++) { + AOTTable *table_aot = tables + i; + WASMTable *table_wasm = module->tables + i; + + table_aot->table_type.elem_type = table_wasm->table_type.elem_type; + table_aot->table_type.flags = table_wasm->table_type.flags; + table_aot->table_type.init_size = table_wasm->table_type.init_size; + table_aot->table_type.max_size = table_wasm->table_type.max_size; + table_aot->table_type.possible_grow = + table_wasm->table_type.possible_grow; +#if WASM_ENABLE_GC != 0 + table_aot->table_type.elem_ref_type = + table_wasm->table_type.elem_ref_type; + /* Note: if the init_expr contains extra data for struct/array + * initialization information (init_expr.u.data), the pointer is + * copied. + * The pointers should still belong to wasm module, so DO NOT + * free the pointers copied to comp_data */ + table_aot->init_expr = table_wasm->init_expr; +#endif + } + + return tables; +} + static void aot_destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count) { @@ -568,9 +651,8 @@ aot_create_comp_data(WASMModule *module, const char *target_arch, bool gc_enabled) { AOTCompData *comp_data; - uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0, i, j; + uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0; uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0; - uint64 size; bool is_64bit_target = false; #if WASM_ENABLE_GC != 0 bool is_target_x86 = false; @@ -647,57 +729,21 @@ aot_create_comp_data(WASMModule *module, const char *target_arch, aot_create_mem_init_data_list(module))) goto fail; - /* Create tables */ - comp_data->table_count = module->import_table_count + module->table_count; - - if (comp_data->table_count > 0) { - size = sizeof(AOTTable) * (uint64)comp_data->table_count; - if (size >= UINT32_MAX - || !(comp_data->tables = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("create memories array failed.\n"); + /* Create import tables */ + comp_data->import_table_count = module->import_table_count; + if (comp_data->import_table_count > 0) { + comp_data->import_tables = aot_create_import_tables(module); + if (!comp_data->import_tables) { goto fail; } - memset(comp_data->tables, 0, size); - for (i = 0; i < comp_data->table_count; i++) { - if (i < module->import_table_count) { - comp_data->tables[i].table_type.elem_type = - module->import_tables[i].u.table.table_type.elem_type; - comp_data->tables[i].table_type.flags = - module->import_tables[i].u.table.table_type.flags; - comp_data->tables[i].table_type.init_size = - module->import_tables[i].u.table.table_type.init_size; - comp_data->tables[i].table_type.max_size = - module->import_tables[i].u.table.table_type.max_size; -#if WASM_ENABLE_GC != 0 - comp_data->tables[i].table_type.elem_ref_type = - module->import_tables[i].u.table.table_type.elem_ref_type; -#endif - comp_data->tables[i].table_type.possible_grow = - module->import_tables[i].u.table.table_type.possible_grow; - } - else { - j = i - module->import_table_count; - comp_data->tables[i].table_type.elem_type = - module->tables[j].table_type.elem_type; - comp_data->tables[i].table_type.flags = - module->tables[j].table_type.flags; - comp_data->tables[i].table_type.init_size = - module->tables[j].table_type.init_size; - comp_data->tables[i].table_type.max_size = - module->tables[j].table_type.max_size; - comp_data->tables[i].table_type.possible_grow = - module->tables[j].table_type.possible_grow; -#if WASM_ENABLE_GC != 0 - comp_data->tables[j].table_type.elem_ref_type = - module->tables[j].table_type.elem_ref_type; - /* Note: if the init_expr contains extra data for struct/array - * initialization information (init_expr.u.data), the pointer is - * copied. - * The pointers should still belong to wasm module, so DO NOT - * free the pointers copied to comp_data */ - comp_data->tables[j].init_expr = module->tables[j].init_expr; -#endif - } + } + + /* Create tables */ + comp_data->table_count = module->table_count; + if (comp_data->table_count > 0) { + comp_data->tables = aot_create_tables(module); + if (!comp_data->tables) { + goto fail; } } diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index 98d2cc6cc..c662f52f5 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -334,29 +334,19 @@ aot_set_last_error_v(const char *format, ...); #endif static inline uint32 -aot_get_imp_tbl_data_slots(const AOTImportTable *tbl, bool is_jit_mode) +aot_get_tbl_data_slots(const AOTTableType *type, bool is_jit_mode) { #if WASM_ENABLE_MULTI_MODULE != 0 if (is_jit_mode) - return tbl->table_type.max_size; + return type->max_size; #else (void)is_jit_mode; #endif - return tbl->table_type.possible_grow ? tbl->table_type.max_size - : tbl->table_type.init_size; -} - -static inline uint32 -aot_get_tbl_data_slots(const AOTTable *tbl, bool is_jit_mode) -{ -#if WASM_ENABLE_MULTI_MODULE != 0 - if (is_jit_mode) - return tbl->table_type.max_size; -#else - (void)is_jit_mode; -#endif - return tbl->table_type.possible_grow ? tbl->table_type.max_size - : tbl->table_type.init_size; + /* + * TODO: if it is a host created table or a to be exported table, might need + * to ignore possible_grow + */ + return type->possible_grow ? type->max_size : type->init_size; } #ifdef __cplusplus diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index a4a5c9fec..8f329e506 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -534,6 +534,13 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type) ? comp_ctx->comp_data->import_memories[0].mem_type \ : comp_ctx->comp_data->memories[0]) +#define TABLE_TYPE(i) \ + (i < comp_ctx->comp_data->import_table_count \ + ? comp_ctx->comp_data->import_tables[i].table_type \ + : comp_ctx->comp_data \ + ->tables[i - comp_ctx->comp_data->import_table_count] \ + .table_type) + #define DEFAULT_MEMORY_TYPE_FLAG (DEFAULT_MEMORY_TYPE.flags) #define DEFAULT_MEMORY_TYPE_NUM_BYTES_PER_PAGE \ @@ -552,14 +559,14 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type) #define IS_MEMORY64 (DEFAULT_MEMORY_TYPE_FLAG & MEMORY64_FLAG) #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \ (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED) -#define IS_TABLE64(i) \ - (comp_ctx->comp_data->tables[i].table_type.flags & TABLE64_FLAG) +#define IS_TABLE64(i) (TABLE_TYPE(i).flags & TABLE64_FLAG) #define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) \ (IS_TABLE64(i) ? VAL_IF_ENABLED : VAL_IF_DISABLED) #else #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED) #define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED) -#endif +#define IS_TABLE64(i) false +#endif /* WASM_ENABLE_MEMORY64 != 0 */ #define POP_I32(v) POP(v, VALUE_TYPE_I32) #define POP_I64(v) POP(v, VALUE_TYPE_I64) diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 98654a734..1d7f08652 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -353,9 +353,7 @@ get_table_init_data_size(AOTCompContext *comp_ctx, } static uint32 -get_table_init_data_list_size(AOTCompContext *comp_ctx, - AOTTableInitData **table_init_data_list, - uint32 table_init_data_count) +get_table_init_data_list_size(AOTCompContext *comp_ctx, AOTCompData *comp_data) { /* * ------------------------------ @@ -370,13 +368,13 @@ get_table_init_data_list_size(AOTCompContext *comp_ctx, * | | UINTPTR [func_index_count] / [elem_count] * ------------------------------ */ - AOTTableInitData **table_init_data = table_init_data_list; + AOTTableInitData **table_init_data = comp_data->table_init_data_list; uint32 size = 0, i; /* table_init_data_count(4 bytes) */ size = (uint32)sizeof(uint32); - for (i = 0; i < table_init_data_count; i++, table_init_data++) { + for (i = 0; i < comp_data->table_init_data_count; i++, table_init_data++) { size = align_uint(size, 4); size += get_table_init_data_size(comp_ctx, *table_init_data); } @@ -384,57 +382,44 @@ get_table_init_data_list_size(AOTCompContext *comp_ctx, } static uint32 -get_import_table_size(const AOTCompContext *comp_ctx, - const AOTCompData *comp_data) +get_import_table_size(AOTCompContext *comp_ctx, AOTCompData *comp_data) { - /* - * ------------------------------ - * | import_table_count - * ------------------------------ - * | | U8 elem_type - * | | U8 flags - * | | U8 possible_grow - * | AOTImportTable[N] | U8 elem_ref_type.nullable (for GC only) - * | | U32 init_size - * | | U32 max_size - * | | U32 elem_ref_type.heap_type (for GC only) - * ------------------------------ - */ - uint32 size = 0, i; + /* import_table_count */ + uint32 size = (uint32)sizeof(uint32); - size = (uint32)sizeof(uint32); - for (i = 0; i < comp_data->import_table_count; i++) { + for (uint32 i = 0; i < comp_data->import_table_count; i++) { + size = align_uint(size, 4); + /* + * u8 elem_type + u8 flags + * + u8 possible_grow + u8 elem_ref_type.nullable + * ------------------------------ =u32 + * + u32 init_size + u32 max_size + * + u32 elem_ref_type.heap_type (Optional) + */ size += sizeof(uint32) * 3; #if WASM_ENABLE_GC != 0 if (comp_ctx->enable_gc && comp_data->import_tables[i].table_type.elem_ref_type) size += sizeof(uint32); #endif + /* module_name */ + size += + get_string_size(comp_ctx, comp_data->import_tables[i].module_name); + size = align_uint(size, 2); + /* field_name */ + size += + get_string_size(comp_ctx, comp_data->import_tables[i].table_name); } return size; } static uint32 -get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data) +get_table_size(AOTCompContext *comp_ctx, AOTCompData *comp_data) { - /* - * ------------------------------ - * | table_count - * ------------------------------ - * | | U8 elem_type - * | | U8 flags - * | | U8 possible_grow - * | AOTTable[N] | U8 elem_ref_type.nullable (for GC only) - * | | U32 init_size - * | | U32 max_size - * | | U32 elem_ref_type.heap_type (for GC only) - * | | N init_expr (for GC only) - * ------------------------------ - */ - uint32 size = 0, i; + /* table_count */ + uint32 size = (uint32)sizeof(uint32); - size = (uint32)sizeof(uint32); - for (i = 0; i < comp_data->table_count; i++) { + for (uint32 i = 0; i < comp_data->table_count; i++) { size += sizeof(uint32) * 3; #if WASM_ENABLE_GC != 0 if (comp_ctx->enable_gc) { @@ -449,37 +434,6 @@ get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data) return size; } -static uint32 -get_table_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data) -{ - /* - * ------------------------------ - * | import_table_count - * ------------------------------ - * | - * | AOTImportTable[import_table_count] - * | - * ------------------------------ - * | table_count - * ------------------------------ - * | - * | AOTTable[table_count] - * | - * ------------------------------ - * | table_init_data_count - * ------------------------------ - * | - * | AOTTableInitData*[table_init_data_count] - * | - * ------------------------------ - */ - return get_import_table_size(comp_ctx, comp_data) - + get_table_size(comp_ctx, comp_data) - + get_table_init_data_list_size(comp_ctx, - comp_data->table_init_data_list, - comp_data->table_init_data_count); -} - static uint32 get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type) { @@ -780,32 +734,36 @@ get_init_data_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data, * ------------------------------------------------------- * | u32 import_memory_count * ------------------------------------------------------- - * | | u32 flags - * | AOTImportMemory[import_memory_count] | u32 num_bytes_per_page - * | | u32 init_page_count - * | | u32 max_page_count - * | | str module_name - * | | str field_name + * | | u32 flags + * | AOTImportMemory[N] | u32 num_bytes_per_page + * | | u32 init_page_count + * | | u32 max_page_count + * | | str module_name + * | | str field_name * ------------------------------------------------------- * | padding + * | previous version doesn't have it by design. + * | But alignment will make it 0 * ------------------------------------------------------- * | u32 memory_count * ------------------------------------------------------- - * | | u32 flags - * | AOTMemoryType[memory_count] | u32 num_bytes_per_page - * | | u32 init_page_count - * | | u32 max_page_count + * | | u32 flags + * | AOTMemoryType[N] | u32 num_bytes_per_page + * | | u32 init_page_count + * | | u32 max_page_count * ------------------------------------------------------- - * | padding (TBC: previous aot doesn't have this padding by design) + * | padding + * | previous version doesn't have it by design. + * | But alignment will make it 0 * ------------------------------------------------------- * | u32 mem_init_data_count * ------------------------------------------------------- - * | | u32 is_passive/placeholder - * | | u32 memory_index/placeholder - * | | u32 init expr type - * | AOTMemInitData[mem_init_data_count] | u32 init expr value - * | | u32 byte count - * | | u8* bytes + * | | u32 is_passive/placeholder + * | | u32 memory_index/placeholder + * | | u32 init expr type + * | AOTMemInitData[N] | u32 init expr value + * | | u32 byte count + * | | u8* bytes * ------------------------------------------------------- */ size += get_import_memory_size(comp_ctx, comp_data); @@ -816,8 +774,60 @@ get_init_data_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data, size = align_uint(size, 4); size += get_mem_init_data_list_size(comp_ctx, comp_data); + /* + * ------------------------------------------------------- + * | u32 import_table_count + * ------------------------------------------------------- + * | | u8 elem_type + * | | u8 flags + * | | u8 possible_grow + * | | u8 elem_ref_type.nullable(GC) + * | AOTImportTable[N] | u32 init_size + * | | u32 max_size + * | | u32 elem_ref_type.heap_type(GC) + * | | str module_name + * | | str field_name + * ------------------------------------------------------- + * | padding + * | previous version doesn't have it by design. + * | but import_table_count used to be 0 + * ------------------------------------------------------- + * | u32 table_count + * ------------------------------------------------------- + * | | u8 elem_type + * | | u8 flags + * | | u8 possible_grow + * | | u8 elem_ref_type.nullable(GC) + * | AOTTable[N] | u32 init_size + * | | u32 max_size + * | | u32 elem_ref_type.heap_type(GC) + * | | N init_expr(GC) + * ------------------------------------------------------- + * | padding + * | previous version doesn't have it by design. + * | But alignment will make it 0 + * | table_init_data_count + * ------------------------------------------------------- + * | u32 table_init_data_count + * ------------------------------------------------------- + * | | U32 mode + * | AOTTableInitData[N] | U32 elem_type + * | | U32 table_index + * | | U32 offset.init_expr_type + * | | U64 offset.u.i64 + * | | U32 func_index_count / elem_count + * | | UINTPTR [func_index_count] / [elem_count] + * ------------------------------------------------------- + */ + size = align_uint(size, 4); - size += get_table_info_size(comp_ctx, comp_data); + size += get_import_table_size(comp_ctx, comp_data); + + size = align_uint(size, 4); + size += get_table_size(comp_ctx, comp_data); + + size = align_uint(size, 4); + size += get_table_init_data_list_size(comp_ctx, comp_data); size = align_uint(size, 4); size += get_type_info_size(comp_ctx, comp_data); @@ -2040,31 +2050,27 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset, } static bool -aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, - AOTCompContext *comp_ctx, AOTCompData *comp_data, - AOTObjectData *obj_data) +aot_emit_import_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompContext *comp_ctx, AOTCompData *comp_data, + AOTObjectData *obj_data) { - uint32 offset = *p_offset, i, j; - AOTTableInitData **init_datas = comp_data->table_init_data_list; + uint32 offset = *p_offset; *p_offset = offset = align_uint(offset, 4); - /* Emit import table count */ EMIT_U32(comp_data->import_table_count); - /* Emit table items */ - for (i = 0; i < comp_data->import_table_count; i++) { - /* TODO: - * EMIT_STR(comp_data->import_tables[i].module_name ); - * EMIT_STR(comp_data->import_tables[i].table_name); - */ - EMIT_U8(comp_data->import_tables[i].table_type.elem_type); - EMIT_U8(comp_data->import_tables[i].table_type.flags); - EMIT_U8(comp_data->import_tables[i].table_type.possible_grow); + + AOTImportTable *import_table = comp_data->import_tables; + for (uint32 i = 0; i < comp_data->import_table_count; i++, import_table++) { + offset = align_uint(offset, 4); + + EMIT_U8(import_table->table_type.elem_type); + EMIT_U8(import_table->table_type.flags); + EMIT_U8(import_table->table_type.possible_grow); #if WASM_ENABLE_GC != 0 - if (comp_ctx->enable_gc - && comp_data->import_tables[i].table_type.elem_ref_type) { - EMIT_U8(comp_data->import_tables[i] - .table_type.elem_ref_type->ref_ht_common.nullable); + if (comp_ctx->enable_gc && import_table->table_type.elem_ref_type) { + EMIT_U8( + import_table->table_type.elem_ref_type->ref_ht_common.nullable); } else #endif @@ -2072,23 +2078,46 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, /* emit one placeholder to keep the same size */ EMIT_U8(0); } - EMIT_U32(comp_data->import_tables[i].table_type.init_size); - EMIT_U32(comp_data->import_tables[i].table_type.max_size); + + EMIT_U32(import_table->table_type.init_size); + EMIT_U32(import_table->table_type.max_size); + #if WASM_ENABLE_GC != 0 - if (comp_ctx->enable_gc - && comp_data->import_tables[i].table_type.elem_ref_type) { + if (comp_ctx->enable_gc && import_table->table_type.elem_ref_type) { bh_assert(wasm_is_type_multi_byte_type( - comp_data->import_tables[i].table_type.elem_type)); - EMIT_U32(comp_data->import_tables[i] - .table_type.elem_ref_type->ref_ht_common.heap_type); + import_table->table_type.elem_type)); + EMIT_U32(import_table->table_type.elem_ref_type->ref_ht_common + .heap_type); } #endif + + EMIT_STR(import_table->module_name); + offset = align_uint(offset, 2); + + EMIT_STR(import_table->table_name); } - /* Emit table count */ + if (offset - *p_offset != get_import_table_size(comp_ctx, comp_data)) { + aot_set_last_error("emit import table info failed."); + return false; + } + + *p_offset = offset; + return true; +} + +static bool +aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompContext *comp_ctx, AOTCompData *comp_data, + AOTObjectData *obj_data) +{ + uint32 offset = *p_offset; + + *p_offset = offset = align_uint(offset, 4); + EMIT_U32(comp_data->table_count); - /* Emit table items */ - for (i = 0; i < comp_data->table_count; i++) { + + for (uint32 i = 0; i < comp_data->table_count; i++) { EMIT_U8(comp_data->tables[i].table_type.elem_type); EMIT_U8(comp_data->tables[i].table_type.flags); EMIT_U8(comp_data->tables[i].table_type.possible_grow); @@ -2104,8 +2133,10 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, /* emit one placeholder to keep the same size */ EMIT_U8(0); } + EMIT_U32(comp_data->tables[i].table_type.init_size); EMIT_U32(comp_data->tables[i].table_type.max_size); + #if WASM_ENABLE_GC != 0 if (comp_ctx->enable_gc) { if (comp_data->tables[i].table_type.elem_ref_type) { @@ -2123,16 +2154,37 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, #endif } - /* Emit table init data count */ + if (offset - *p_offset != get_table_size(comp_ctx, comp_data)) { + aot_set_last_error("emit table info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_table_init_data_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompContext *comp_ctx, AOTCompData *comp_data, + AOTObjectData *obj_data) +{ + uint32 offset = *p_offset; + + *p_offset = offset = align_uint(offset, 4); + EMIT_U32(comp_data->table_init_data_count); - /* Emit table init data items */ - for (i = 0; i < comp_data->table_init_data_count; i++) { + + AOTTableInitData **init_datas = comp_data->table_init_data_list; + for (uint32 i = 0; i < comp_data->table_init_data_count; i++) { offset = align_uint(offset, 4); + EMIT_U32(init_datas[i]->mode); EMIT_U32(init_datas[i]->elem_type); EMIT_U32(init_datas[i]->table_index); EMIT_U32(init_datas[i]->offset.init_expr_type); EMIT_U64(init_datas[i]->offset.u.i64); + #if WASM_ENABLE_GC != 0 if (comp_ctx->enable_gc && init_datas[i]->elem_ref_type) { EMIT_U16(init_datas[i]->elem_ref_type->ref_ht_common.ref_type); @@ -2146,21 +2198,23 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, EMIT_U16(0); EMIT_U32(0); } + EMIT_U32(init_datas[i]->value_count); - for (j = 0; j < init_datas[i]->value_count; j++) { + + for (uint j = 0; j < init_datas[i]->value_count; j++) { if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx, &init_datas[i]->init_values[j])) return false; } } - if (offset - *p_offset != get_table_info_size(comp_ctx, comp_data)) { - aot_set_last_error("emit table info failed."); + if (offset - *p_offset + != get_table_init_data_list_size(comp_ctx, comp_data)) { + aot_set_last_error("emit table init data info failed."); return false; } *p_offset = offset; - return true; } @@ -2490,8 +2544,12 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, obj_data) || !aot_emit_memory_init_data_list(buf, buf_end, &offset, comp_ctx, comp_data, obj_data) + || !aot_emit_import_table_info(buf, buf_end, &offset, comp_ctx, + comp_data, obj_data) || !aot_emit_table_info(buf, buf_end, &offset, comp_ctx, comp_data, obj_data) + || !aot_emit_table_init_data_info(buf, buf_end, &offset, comp_ctx, + comp_data, obj_data) || !aot_emit_type_info(buf, buf_end, &offset, comp_ctx, comp_data, obj_data) || !aot_emit_import_global_info(buf, buf_end, &offset, comp_ctx, @@ -4534,6 +4592,9 @@ aot_obj_data_create(AOTCompContext *comp_ctx) if (!comp_ctx->call_stack_features.func_idx) { obj_data->target_info.feature_flags |= WASM_FEATURE_FRAME_NO_FUNC_IDX; } + if (comp_ctx->enable_multi_module) { + obj_data->target_info.feature_flags |= WASM_FEATURE_MULTI_MODULE; + } bh_print_time("Begin to resolve object file info"); diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index 49b1ac1cb..cf6503349 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -2239,17 +2239,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, cmp_elem_idx, check_elem_idx_succ))) goto fail; - /* load data as i32* */ - if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx) - + offsetof(AOTTableInstance, elems)))) { - HANDLE_FAILURE("LLVMConstInt"); - goto fail; - } - - if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, - func_ctx->aot_inst, &offset, - 1, "table_elem_base_i8p"))) { - aot_set_last_error("llvm build add failed."); + if (!(table_elem_base = + aot_compile_get_table_elem_base(comp_ctx, func_ctx, tbl_idx))) { goto fail; } diff --git a/core/iwasm/compilation/aot_emit_table.c b/core/iwasm/compilation/aot_emit_table.c index f8c9bf6be..c5d0cf6c8 100644 --- a/core/iwasm/compilation/aot_emit_table.c +++ b/core/iwasm/compilation/aot_emit_table.c @@ -86,25 +86,30 @@ uint64 get_tbl_inst_offset(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx, uint32 tbl_idx) { - uint64 offset = 0, i = 0; - AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables; - AOTTable *tbls = comp_ctx->comp_data->tables; - - offset = offsetof(AOTModuleInstance, global_table_data.bytes) - + (uint64)(comp_ctx->comp_data->memory_count - + comp_ctx->comp_data->import_memory_count) - * sizeof(AOTMemoryInstance) - /* Get global data size according to target info */ - + (comp_ctx->pointer_size == sizeof(uint64) - ? comp_ctx->comp_data->global_data_size_64bit - : comp_ctx->comp_data->global_data_size_32bit); + uint64 offset = offsetof(AOTModuleInstance, global_table_data.bytes) + + (uint64)(comp_ctx->comp_data->memory_count + + comp_ctx->comp_data->import_memory_count) + * sizeof(AOTMemoryInstance) + /* Get global data size according to target info */ + + (comp_ctx->pointer_size == sizeof(uint64) + ? comp_ctx->comp_data->global_data_size_64bit + : comp_ctx->comp_data->global_data_size_32bit); + uint64 i = 0; while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) { offset += offsetof(AOTTableInstance, elems); - /* avoid loading from current AOTTableInstance */ - offset += - (uint64)comp_ctx->pointer_size - * aot_get_imp_tbl_data_slots(imp_tbls + i, comp_ctx->is_jit_mode); + if (comp_ctx->enable_multi_module) { + AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables; + /* avoid loading from current AOTTableInstance */ + offset += (uint64)comp_ctx->pointer_size + * aot_get_tbl_data_slots(&(imp_tbls + i)->table_type, + comp_ctx->is_jit_mode); + } + else { + /* there is only one pointer for imported elem */ + offset += (uint64)comp_ctx->pointer_size; + } + ++i; } @@ -112,13 +117,15 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx, return offset; } + AOTTable *tbls = comp_ctx->comp_data->tables; tbl_idx -= comp_ctx->comp_data->import_table_count; i -= comp_ctx->comp_data->import_table_count; while (i < tbl_idx && i < comp_ctx->comp_data->table_count) { offset += offsetof(AOTTableInstance, elems); /* avoid loading from current AOTTableInstance */ offset += (uint64)comp_ctx->pointer_size - * aot_get_tbl_data_slots(tbls + i, comp_ctx->is_jit_mode); + * aot_get_tbl_data_slots(&(tbls + i)->table_type, + comp_ctx->is_jit_mode); ++i; } @@ -137,6 +144,70 @@ get_module_inst_extra_offset(AOTCompContext *comp_ctx) return offset_32; } +LLVMValueRef +aot_compile_get_table_elem_base(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, uint32 table_index) +{ + /* locate elems of a AOTTableInstance in a AOTModuleInstance */ + LLVMValueRef offset = + I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, table_index) + + offsetof(AOTTableInstance, elems)); + if (!offset) { + HANDLE_FAILURE("LLVMConstInt"); + goto fail; + } + + /* + * for local table, + * table_elem_base = (*(uint8*)WASMModuleInstance) + offset + * + * if for import table, if enable_multi_module == true + * table_elem_base = (*(uint8*)WASMModuleInstance) + offset + * table_elem_base = *(uintptr_t*)(table_elem_base) + */ + LLVMValueRef table_elem_base = + LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, + &offset, 1, "table_elem_base_i8p"); + if (!table_elem_base) { + HANDLE_FAILURE("LLVMBuildInBoundsGEP"); + goto fail; + } + + if (comp_ctx->enable_multi_module) { + return table_elem_base; + } + + if (table_index < comp_ctx->comp_data->import_table_count) { + table_elem_base = + LLVMBuildIntToPtr(comp_ctx->builder, table_elem_base, + INTPTR_T_PTR_TYPE, "import_table_elem_base_pp"); + if (!table_elem_base) { + HANDLE_FAILURE("LLVMBuildBitCast"); + goto fail; + } + + table_elem_base = + LLVMBuildLoad2(comp_ctx->builder, INTPTR_T_TYPE, table_elem_base, + "import_table_elem_base_p_addr"); + if (!table_elem_base) { + HANDLE_FAILURE("LLVMBuildLoad"); + goto fail; + } + + table_elem_base = + LLVMBuildIntToPtr(comp_ctx->builder, table_elem_base, + INTPTR_T_PTR_TYPE, "import_table_elem_base_p"); + if (!table_elem_base) { + HANDLE_FAILURE("LLVMBuildBitCast"); + goto fail; + } + } + + return table_elem_base; +fail: + return NULL; +} + #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 LLVMValueRef @@ -266,7 +337,7 @@ bool aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx) { - LLVMValueRef elem_idx, offset, func_idx; + LLVMValueRef elem_idx, func_idx; LLVMValueRef table_elem_base, table_elem_addr, table_elem; POP_TBL_ELEM_IDX(elem_idx); @@ -275,17 +346,9 @@ aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } - /* load data as i32* */ - if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx) - + offsetof(AOTTableInstance, elems)))) { - HANDLE_FAILURE("LLVMConstInt"); - goto fail; - } - - if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, - func_ctx->aot_inst, &offset, - 1, "table_elem_base_i8p"))) { - aot_set_last_error("llvm build add failed."); + if (!(table_elem_base = + aot_compile_get_table_elem_base(comp_ctx, func_ctx, tbl_idx))) { + aot_set_last_error("llvm build table_elem_base failed."); goto fail; } @@ -352,7 +415,7 @@ bool aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx) { - LLVMValueRef val = NULL, elem_idx, offset, table_elem_base, table_elem_addr; + LLVMValueRef val = NULL, elem_idx, table_elem_base, table_elem_addr; if (comp_ctx->enable_gc) POP_GC_REF(val); @@ -372,17 +435,9 @@ aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } - /* load data as gc_obj_ref* or i32* */ - if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx) - + offsetof(AOTTableInstance, elems)))) { - HANDLE_FAILURE("LLVMConstInt"); - goto fail; - } - - if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, - func_ctx->aot_inst, &offset, - 1, "table_elem_base_i8p"))) { - HANDLE_FAILURE("LLVMBuildInBoundsGEP"); + if (!(table_elem_base = + aot_compile_get_table_elem_base(comp_ctx, func_ctx, tbl_idx))) { + aot_set_last_error("llvm build table_elem_base failed."); goto fail; } @@ -519,8 +574,7 @@ aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* In table64, the length should be i32 type if any one of src/dst table * is i32 type, set the table index to the lesser-or-equal table when * popping length n */ - if (!(comp_ctx->comp_data->tables[src_tbl_idx].table_type.flags - & TABLE64_FLAG)) + if (!IS_TABLE64(src_tbl_idx)) tbl_idx = src_tbl_idx; else tbl_idx = dst_tbl_idx; diff --git a/core/iwasm/compilation/aot_emit_table.h b/core/iwasm/compilation/aot_emit_table.h index f294cca9a..718e497e5 100644 --- a/core/iwasm/compilation/aot_emit_table.h +++ b/core/iwasm/compilation/aot_emit_table.h @@ -56,6 +56,10 @@ LLVMValueRef aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx); +LLVMValueRef +aot_compile_get_table_elem_base(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, uint32 table_index); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 0a8af96f4..d9974eed4 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -2695,6 +2695,9 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option) if (option->enable_shared_heap) comp_ctx->enable_shared_heap = true; + if (option->enable_multi_module) + comp_ctx->enable_multi_module = true; + comp_ctx->opt_level = option->opt_level; comp_ctx->size_level = option->size_level; diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 9c608d301..ef9423cc5 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -484,6 +484,8 @@ typedef struct AOTCompContext { bool enable_shared_heap; + bool enable_multi_module; + uint32 opt_level; uint32 size_level; diff --git a/core/iwasm/fast-jit/fe/jit_emit_table.c b/core/iwasm/fast-jit/fe/jit_emit_table.c index 6da5b820f..8ef0de760 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_table.c +++ b/core/iwasm/fast-jit/fe/jit_emit_table.c @@ -290,8 +290,10 @@ wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst_offset, if (offset_len_out_of_bounds(dst_offset, len, tbl_sz)) goto out_of_bounds; + table_elem_type_t *table_elems = + wasm_locate_table_elems(inst->module, tbl, tbl_idx); for (; len != 0; dst_offset++, len--) { - tbl->elems[dst_offset] = val; + table_elems[dst_offset] = val; } return 0; diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index ca5521a14..40cf6852b 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -706,6 +706,19 @@ get_table_elems_reg(JitFrame *frame, uint32 tbl_idx) GEN_INSN(ADD, frame->table_regs[tbl_idx].table_elems, module_inst, NEW_CONST(PTR, offset)); } + + if (tbl_idx < cc->cur_wasm_module->import_table_count) { + /* + * If the table is imported, table_elems is a pointer to the + * imported table's elements. We need to load the actual elements. + */ + /* table_elems = *(void**)table_elems */ + JitReg tmp = jit_cc_new_reg_ptr(cc); + GEN_INSN(LDPTR, tmp, frame->table_regs[tbl_idx].table_elems, + NEW_CONST(I32, 0)); + GEN_INSN(MOV, frame->table_regs[tbl_idx].table_elems, tmp); + } + return frame->table_regs[tbl_idx].table_elems; } diff --git a/core/iwasm/include/aot_comp_option.h b/core/iwasm/include/aot_comp_option.h index a97275d24..ef03cae4b 100644 --- a/core/iwasm/include/aot_comp_option.h +++ b/core/iwasm/include/aot_comp_option.h @@ -74,6 +74,7 @@ typedef struct AOTCompOption { bool enable_stack_estimation; bool quick_invoke_c_api_import; bool enable_shared_heap; + bool enable_multi_module; char *use_prof_file; uint32_t opt_level; uint32_t size_level; diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index d896c42d1..a47446cbf 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -112,6 +112,20 @@ typedef struct wasm_export_t { } u; } wasm_export_t; +#ifndef WASM_VALKIND_T_DEFINED +#define WASM_VALKIND_T_DEFINED +typedef uint8_t wasm_valkind_t; +enum wasm_valkind_enum { + WASM_I32, + WASM_I64, + WASM_F32, + WASM_F64, + WASM_V128, + WASM_EXTERNREF = 128, + WASM_FUNCREF, +}; +#endif + /* Instantiated WASM module */ struct WASMModuleInstanceCommon; typedef struct WASMModuleInstanceCommon *wasm_module_inst_t; @@ -124,6 +138,17 @@ typedef WASMFunctionInstanceCommon *wasm_function_inst_t; struct WASMMemoryInstance; typedef struct WASMMemoryInstance *wasm_memory_inst_t; +/* Table instance*/ +/*TODO: better to use WASMTableInstance and AOTTableInstance directly */ +typedef struct wasm_table_inst_t { + wasm_valkind_t elem_kind; + uint32_t cur_size; + uint32_t max_size; + /* represents the elements of the table, for internal use only */ + /* always a table_elem_type_t elems[] */ + void *elems; +} wasm_table_inst_t; + /* WASM section */ typedef struct wasm_section_t { struct wasm_section_t *next; @@ -270,6 +295,7 @@ typedef struct WASMExternInstance { wasm_import_export_kind_t kind; union { wasm_memory_inst_t memory; + wasm_table_inst_t *table; } u; } WASMExternInstance, *wasm_extern_inst_t; @@ -296,20 +322,6 @@ typedef struct InstantiationArgs { } InstantiationArgs; #endif /* INSTANTIATION_ARGS_OPTION_DEFINED */ -#ifndef WASM_VALKIND_T_DEFINED -#define WASM_VALKIND_T_DEFINED -typedef uint8_t wasm_valkind_t; -enum wasm_valkind_enum { - WASM_I32, - WASM_I64, - WASM_F32, - WASM_F64, - WASM_V128, - WASM_EXTERNREF = 128, - WASM_FUNCREF, -}; -#endif - #ifndef WASM_VAL_T_DEFINED #define WASM_VAL_T_DEFINED struct wasm_ref_t; @@ -337,15 +349,6 @@ typedef struct wasm_global_inst_t { void *global_data; } wasm_global_inst_t; -/* Table instance*/ -typedef struct wasm_table_inst_t { - wasm_valkind_t elem_kind; - uint32_t cur_size; - uint32_t max_size; - /* represents the elements of the table, for internal use only */ - void *elems; -} wasm_table_inst_t; - typedef enum { WASM_LOG_LEVEL_FATAL = 0, WASM_LOG_LEVEL_ERROR = 1, @@ -733,6 +736,13 @@ wasm_runtime_instantiate(const wasm_module_t module, * * Same as wasm_runtime_instantiate, but it also allows overwriting maximum * memory + * + * The ownership of `imports.u`, globals and tables and memories, from `args` + * will be transferred to the runtime. You only need to worry about + * releasing them if the instantiate() fails. + * + * TODO: for now, wasm_table_inst still needs to be managed by the caller. + * but only the shell */ WASM_RUNTIME_API_EXTERN wasm_module_inst_t wasm_runtime_instantiate_ex(const wasm_module_t module, @@ -1000,7 +1010,7 @@ wasm_runtime_create_memory(const wasm_module_t module, */ WASM_RUNTIME_API_EXTERN void wasm_runtime_destroy_memory(const wasm_module_t module, - wasm_memory_inst_t memory_inst); + wasm_memory_inst_t memory); /** * @brief Lookup a memory instance by name @@ -1495,7 +1505,7 @@ wasm_runtime_get_import_count(const wasm_module_t module); * @param import_type the location to store information about the import */ WASM_RUNTIME_API_EXTERN void -wasm_runtime_get_import_type(const wasm_module_t module, int32_t import_index, +wasm_runtime_get_import_type(const wasm_module_t module, uint32_t import_index, wasm_import_t *import_type); /** @@ -2341,6 +2351,14 @@ wasm_runtime_shared_heap_malloc(wasm_module_inst_t module_inst, uint64_t size, WASM_RUNTIME_API_EXTERN void wasm_runtime_shared_heap_free(wasm_module_inst_t module_inst, uint64_t ptr); +WASM_RUNTIME_API_EXTERN wasm_table_inst_t * +wasm_runtime_create_table(const wasm_module_t module, + const wasm_table_type_t type); + +WASM_RUNTIME_API_EXTERN void +wasm_runtime_destroy_table(const wasm_module_t module, + wasm_table_inst_t *table); + /*TODO: take me out when have a linker */ WASM_RUNTIME_API_EXTERN wasm_module_inst_t wasm_runtime_instantiate_with_builtin_linker(wasm_module_t module, @@ -2355,7 +2373,7 @@ wasm_runtime_instantiate_with_builtin_linker(wasm_module_t module, WASM_RUNTIME_API_EXTERN bool wasm_runtime_create_imports_with_builtin(wasm_module_t module, wasm_extern_inst_t out, - int32_t out_len); + uint32_t out_len); WASM_RUNTIME_API_EXTERN void wasm_runtime_destroy_imports(wasm_module_t module, wasm_extern_inst_t imports); @@ -2363,7 +2381,7 @@ wasm_runtime_destroy_imports(wasm_module_t module, wasm_extern_inst_t imports); WASM_RUNTIME_API_EXTERN bool wasm_runtime_create_imports(wasm_module_t module, bool (*module_name_filter)(const char *), - wasm_extern_inst_t out, int32_t out_len); + wasm_extern_inst_t out, uint32_t out_len); #ifdef __cplusplus } diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 6023b0702..46129d517 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -1260,7 +1260,8 @@ wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size) inline static uint16 wasm_value_type_cell_num_internal(uint8 value_type, uint8 pointer_size) { - return wasm_value_type_size_internal(value_type, pointer_size) / 4; + return (uint16)(wasm_value_type_size_internal(value_type, pointer_size) + / 4); } /** @@ -1275,7 +1276,7 @@ wasm_value_type_size(uint8 value_type) inline static uint16 wasm_value_type_cell_num(uint8 value_type) { - return wasm_value_type_size(value_type) / 4; + return (uint16)(wasm_value_type_size(value_type) / 4); } inline static uint32 diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 7041fd89c..21b306cee 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -2399,15 +2399,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, tbl_idx); /* clang-format off */ #if WASM_ENABLE_GC == 0 - fidx = tbl_inst->elems[val]; + fidx = table_elems[val]; if (fidx == (uint32)-1) { wasm_set_exception(module, "uninitialized element"); goto got_exception; } #else - func_obj = (WASMFuncObjectRef)tbl_inst->elems[val]; + func_obj = (WASMFuncObjectRef)table_elems[val]; if (!func_obj) { wasm_set_exception(module, "uninitialized element"); goto got_exception; @@ -2558,10 +2560,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, tbl_idx); #if WASM_ENABLE_GC == 0 - PUSH_I32(tbl_inst->elems[elem_idx]); + PUSH_I32(table_elems[elem_idx]); #else - PUSH_REF(tbl_inst->elems[elem_idx]); + PUSH_REF(table_elems[elem_idx]); #endif HANDLE_OP_END(); } @@ -2592,7 +2596,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } - tbl_inst->elems[elem_idx] = elem_val; + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, tbl_idx); + table_elems[elem_idx] = elem_val; HANDLE_OP_END(); } @@ -5907,7 +5913,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, tbl_elem_idx_t elem_idx, d; uint32 n, s; WASMTableInstance *tbl_inst; - table_elem_type_t *table_elems; InitializerExpression *tbl_seg_init_values = NULL, *init_values; uint32 tbl_seg_len = 0; @@ -5957,7 +5962,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, break; } - table_elems = tbl_inst->elems + d; + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, + tbl_idx); + table_elems = table_elems + d; init_values = tbl_seg_init_values + s; #if WASM_ENABLE_GC != 0 SYNC_ALL_TO_FRAME(); @@ -6143,8 +6151,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, + tbl_idx); for (; n != 0; elem_idx++, n--) { - tbl_inst->elems[elem_idx] = fill_val; + table_elems[elem_idx] = fill_val; } break; } diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 531468282..84dbc14f3 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1745,15 +1745,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, tbl_idx); /* clang-format off */ #if WASM_ENABLE_GC == 0 - fidx = (uint32)tbl_inst->elems[val]; + fidx = (uint32)table_elems[val]; if (fidx == (uint32)-1) { wasm_set_exception(module, "uninitialized element"); goto got_exception; } #else - func_obj = (WASMFuncObjectRef)tbl_inst->elems[val]; + func_obj = (WASMFuncObjectRef)table_elems[val]; if (!func_obj) { wasm_set_exception(module, "uninitialized element"); goto got_exception; @@ -1908,10 +1910,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, tbl_idx); #if WASM_ENABLE_GC == 0 - PUSH_I32(tbl_inst->elems[elem_idx]); + PUSH_I32(table_elems[elem_idx]); #else - PUSH_REF(tbl_inst->elems[elem_idx]); + PUSH_REF(table_elems[elem_idx]); #endif HANDLE_OP_END(); } @@ -1938,7 +1942,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } - tbl_inst->elems[elem_idx] = elem_val; + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, tbl_idx); + table_elems[elem_idx] = elem_val; HANDLE_OP_END(); } @@ -5170,7 +5176,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 tbl_idx, elem_idx; uint32 n, s, d; WASMTableInstance *tbl_inst; - table_elem_type_t *table_elems; InitializerExpression *tbl_seg_init_values = NULL, *init_values; uint64 i; @@ -5211,7 +5216,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, break; } - table_elems = tbl_inst->elems + d; + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, + tbl_idx); + table_elems = table_elems + d; init_values = tbl_seg_init_values + s; #if WASM_ENABLE_GC != 0 SYNC_ALL_TO_FRAME(); @@ -5361,8 +5369,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } + table_elem_type_t *table_elems = + wasm_locate_table_elems(module->module, tbl_inst, + tbl_idx); for (; n != 0; i++, n--) { - tbl_inst->elems[i] = fill_val; + table_elems[i] = fill_val; } break; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 24fb9a39b..00a6a0693 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -263,24 +263,39 @@ memory_deinstantiate(WASMMemoryInstance *memory) } static void -memories_deinstantiate(WASMModuleInstance *module_inst, - WASMMemoryInstance **memories, uint32 count) +memories_deinstantiate(WASMModuleInstance *module_inst) { - - if (!memories) + if (!module_inst->memories) { return; + } - for (uint32 i = 0; i < count; i++) { + uint32 mem_index = 0; + WASMModule *module = module_inst->module; + WASMMemoryInstance **memories = module_inst->memories; + for (; mem_index < module->import_memory_count; mem_index++) { + WASMMemoryInstance *memory = memories[mem_index]; #if WASM_ENABLE_MULTI_MODULE != 0 - WASMModule *module = module_inst->module; - - if (i < module->import_memory_count - && module->import_memories[i].u.memory.import_module) { + if (module->import_memories[mem_index].u.memory.import_module) { continue; } + + memory_deinstantiate(memory); #endif - memory_deinstantiate(memories[i]); +#if WASM_ENABLE_MULTI_MODULE == 0 && WASM_ENABLE_SHARED_MEMORY != 0 + /* for spawned only */ + if (!shared_memory_is_shared(memory)) { + continue; + } + + if (shared_memory_get_reference(memory) == 0) { + wasm_runtime_free(memory); + } +#endif + } + + for (; mem_index < module->memory_count; mem_index++) { + memory_deinstantiate(memories[mem_index]); } wasm_runtime_free(memories); @@ -369,7 +384,8 @@ memory_instantiate(const WASMModule *module, WASMModuleInstance *parent, < (uint64)num_bytes_per_page * init_page_count) { /* Insert app heap before __heap_base */ uint64 aux_heap_base = module->aux_heap_base; - uint32 bytes_of_last_page = aux_heap_base % num_bytes_per_page; + uint32 bytes_of_last_page = + (uint32)(aux_heap_base % num_bytes_per_page); if (bytes_of_last_page == 0) bytes_of_last_page = num_bytes_per_page; uint32 bytes_to_page_end = @@ -380,7 +396,8 @@ memory_instantiate(const WASMModule *module, WASMModuleInstance *parent, heap_offset = aux_heap_base; aux_heap_base += heap_size; - bytes_of_last_page = aux_heap_base % num_bytes_per_page; + bytes_of_last_page = + (uint32)(aux_heap_base % num_bytes_per_page); if (bytes_of_last_page == 0) bytes_of_last_page = num_bytes_per_page; bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; @@ -562,14 +579,14 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, if (!(module_inst_linked = get_sub_module_inst( module_inst, memory_type->import_module))) { set_error_buf(error_buf, error_buf_size, "unknown memory"); - memories_deinstantiate(module_inst, memories, memory_count); + memories_deinstantiate(module_inst); return NULL; } if (!(memories[mem_index] = wasm_lookup_memory( module_inst_linked, memory_type->field_name))) { set_error_buf(error_buf, error_buf_size, "unknown memory"); - memories_deinstantiate(module_inst, memories, memory_count); + memories_deinstantiate(module_inst); return NULL; } } @@ -591,7 +608,7 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, /* only inst->memories[0] will have an app heap */ mem_index == 0 ? heap_size : 0, flags, aux_heap_base_global_data, error_buf, error_buf_size))) { - memories_deinstantiate(module_inst, memories, memory_count); + memories_deinstantiate(module_inst); return NULL; } } @@ -649,7 +666,7 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, /* only inst->memories[0] will have a app heap */ mem_index == 0 ? heap_size : 0, module->memories[i].flags, aux_heap_base_global_data, error_buf, error_buf_size))) { - memories_deinstantiate(module_inst, memories, memory_count); + memories_deinstantiate(module_inst); return NULL; } mem_index++; @@ -713,14 +730,44 @@ wasm_destroy_memory(WASMMemoryInstance *memory) static void tables_deinstantiate(WASMModuleInstance *module_inst) { - if (module_inst->tables) { - wasm_runtime_free(module_inst->tables); + if (!module_inst) { + return; } -#if WASM_ENABLE_MULTI_MODULE != 0 + +#if WASM_ENABLE_MULTI_MODULE == 0 + if (!module_inst->tables) { + return; + } + + WASMModule *module = module_inst->module; + /* only imported tables */ + for (uint32 i = 0; i < module->import_table_count; i++) { + WASMTableInstance *table = module_inst->tables[i]; + if (!table) { + continue; + } + + table_elem_type_t *table_elems = + wasm_locate_table_elems(module, table, i); + + if (!table_elems) { + continue; + } + + void *table_imported = + ((uint8 *)(table_elems)) - offsetof(WASMTableInstance, elems); + + wasm_runtime_free(table_imported); + } +#else if (module_inst->e->table_insts_linked) { wasm_runtime_free(module_inst->e->table_insts_linked); + module_inst->e->table_insts_linked = NULL; } #endif + + wasm_runtime_free(module_inst->tables); + module_inst->tables = NULL; } /** @@ -728,14 +775,15 @@ tables_deinstantiate(WASMModuleInstance *module_inst) */ static WASMTableInstance ** tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, - WASMTableInstance *first_table, char *error_buf, - uint32 error_buf_size) + WASMTableInstance *table_data, + const WASMExternInstance *imports, uint32 import_count, + char *error_buf, uint32 error_buf_size) { WASMImport *import; uint32 table_index = 0, i; uint32 table_count = module->import_table_count + module->table_count; uint64 total_size = (uint64)sizeof(WASMTableInstance *) * table_count; - WASMTableInstance **tables, *table = first_table; + WASMTableInstance **tables, *table = table_data; #if WASM_ENABLE_MULTI_MODULE != 0 uint64 total_size_of_tables_linked = (uint64)sizeof(WASMTableInstance *) * module->import_table_count; @@ -757,39 +805,43 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, /* instantiate tables from import section */ import = module->import_tables; for (i = 0; i < module->import_table_count; i++, import++) { - uint32 max_size_fixed = 0; + WASMTableImport *import_table_type = &(module->import_tables->u.table); + uint32 max_size_fixed = wasm_get_tbl_data_slots( + &import_table_type->table_type, import_table_type); + + /* sync up with table_size in wasm_instantiate() */ + total_size = offsetof(WASMTableInstance, elems); + #if WASM_ENABLE_MULTI_MODULE != 0 WASMTableInstance *table_inst_linked = NULL; WASMModuleInstance *module_inst_linked = NULL; - if (import->u.table.import_module) { + if (import_table_type->import_module) { if (!(module_inst_linked = get_sub_module_inst( - module_inst, import->u.table.import_module))) { + module_inst, import_table_type->import_module))) { set_error_buf(error_buf, error_buf_size, "unknown table"); goto fail; } if (!(table_inst_linked = wasm_lookup_table( - module_inst_linked, import->u.table.field_name))) { + module_inst_linked, import_table_type->field_name))) { set_error_buf(error_buf, error_buf_size, "unknown table"); goto fail; } - - total_size = offsetof(WASMTableInstance, elems); } - else -#endif - { + else { /* in order to save memory, alloc resource as few as possible */ - max_size_fixed = import->u.table.table_type.possible_grow - ? import->u.table.table_type.max_size - : import->u.table.table_type.init_size; + max_size_fixed = import_table_type->table_type.possible_grow + ? import_table_type->table_type.max_size + : import_table_type->table_type.init_size; /* it is a built-in table, every module has its own */ - total_size = offsetof(WASMTableInstance, elems); /* store function indexes for non-gc, object pointers for gc */ total_size += (uint64)sizeof(table_elem_type_t) * max_size_fixed; } +#else + total_size += sizeof(table_elem_type_t *); +#endif /* WASM_ENABLE_MULTI_MODULE != 0 */ tables[table_index++] = table; @@ -801,10 +853,11 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, uninitialized elements */ #endif - table->is_table64 = import->u.table.table_type.flags & TABLE64_FLAG; + table->is_table64 = import_table_type->table_type.flags & TABLE64_FLAG; #if WASM_ENABLE_MULTI_MODULE != 0 *table_linked = table_inst_linked; + if (table_inst_linked != NULL) { table->elem_type = table_inst_linked->elem_type; #if WASM_ENABLE_GC != 0 @@ -813,44 +866,61 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, table->cur_size = table_inst_linked->cur_size; table->max_size = table_inst_linked->max_size; } - else -#endif - { - table->elem_type = import->u.table.table_type.elem_type; + else { + table->elem_type = import_table_type->table_type.elem_type; #if WASM_ENABLE_GC != 0 table->elem_ref_type.elem_ref_type = - import->u.table.table_type.elem_ref_type; + import_table_type->table_type.elem_ref_type; #endif - table->cur_size = import->u.table.table_type.init_size; + table->cur_size = import_table_type->table_type.init_size; table->max_size = max_size_fixed; } - table = (WASMTableInstance *)((uint8 *)table + (uint32)total_size); -#if WASM_ENABLE_MULTI_MODULE != 0 - table_linked++; +#else + + table->elem_type = import_table_type->table_type.elem_type; +#if WASM_ENABLE_GC != 0 + table->elem_ref_type.elem_ref_type = + import_table_type->table_type.elem_ref_type; #endif + table->cur_size = import_table_type->table_type.init_size; + table->max_size = max_size_fixed; + + /* use import table elem */ + const WASMExternInstance *extern_inst = + wasm_runtime_get_extern_instance(imports, import_count, + WASM_IMPORT_EXPORT_KIND_TABLE, i); + if (!extern_inst) { + LOG_ERROR("missing an import table(%s, %s)", + import_table_type->module_name, + import_table_type->field_name); + return NULL; + } + + /* just in case */ +#ifndef NDEBUG + if (strcmp(import_table_type->field_name, extern_inst->field_name)) { + LOG_ERROR("mismatched import table name: expect \"%s\", got \"%s\"", + import_table_type->field_name, extern_inst->field_name); + return NULL; + } +#endif + + /* store the pointer value */ + table->elems[0] = (table_elem_type_t)extern_inst->u.table->elems; +#endif /* WASM_ENABLE_MULTI_MODULE == 0 */ + + table = (WASMTableInstance *)((uint8 *)table + (uint32)total_size); } /* instantiate tables from table section */ for (i = 0; i < module->table_count; i++) { - uint32 max_size_fixed = 0; + uint32 max_size_fixed = + wasm_get_tbl_data_slots(&module->tables[i].table_type, NULL); total_size = offsetof(WASMTableInstance, elems); -#if WASM_ENABLE_MULTI_MODULE != 0 - /* in case, a module which imports this table will grow it */ - max_size_fixed = module->tables[i].table_type.max_size; -#else - max_size_fixed = module->tables[i].table_type.possible_grow - ? module->tables[i].table_type.max_size - : module->tables[i].table_type.init_size; -#endif -#if WASM_ENABLE_GC == 0 - /* Store function indexes */ - total_size += sizeof(uintptr_t) * (uint64)max_size_fixed; -#else - /* Store object pointers */ - total_size += sizeof(uintptr_t) * (uint64)max_size_fixed; -#endif + /* Store function indexes or object pointer */ + total_size += sizeof(table_elem_type_t) * (uint64)max_size_fixed; tables[table_index++] = table; @@ -876,6 +946,7 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, bh_assert(table_index == table_count); (void)module_inst; return tables; + #if WASM_ENABLE_MULTI_MODULE != 0 fail: wasm_runtime_free(tables); @@ -972,7 +1043,7 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, function->local_offsets = function->u.func->local_offsets; #if WASM_ENABLE_FAST_INTERP != 0 - function->const_cell_num = function->u.func->const_cell_num; + function->const_cell_num = (uint16)function->u.func->const_cell_num; #endif function++; @@ -2241,13 +2312,15 @@ wasm_global_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap) static bool wasm_table_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap) { - WASMTableInstance **tables = module_inst->tables, *table; + WASMTableInstance **tables = module_inst->tables; uint32 table_count = module_inst->table_count, i, j; - WASMObjectRef gc_obj, *table_elems; + WASMObjectRef gc_obj; for (i = 0; i < table_count; i++) { - table = tables[i]; - table_elems = (WASMObjectRef *)table->elems; + WASMTableInstance *table = tables[i]; + WASMObjectRef *table_elems = (WASMObjectRef *)wasm_locate_table_elems( + module_inst->module, table, i); + for (j = 0; j < table->cur_size; j++) { gc_obj = table_elems[j]; if (wasm_obj_is_created_from_heap(gc_obj)) { @@ -2526,35 +2599,32 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, /* Calculate the size of table data */ for (i = 0; i < module->import_table_count; i++) { - WASMTableImport *import_table = &module->import_tables[i].u.table; table_size += offsetof(WASMTableInstance, elems); + #if WASM_ENABLE_MULTI_MODULE != 0 + WASMTableImport *import_table = &module->import_tables[i].u.table; + /* all tables have its own elems. */ table_size += (uint64)sizeof(table_elem_type_t) * import_table->table_type.max_size; #else - table_size += (uint64)sizeof(table_elem_type_t) - * (import_table->table_type.possible_grow - ? import_table->table_type.max_size - : import_table->table_type.init_size); + /* refer to the imported table's elems */ + table_size += (uint64)sizeof(table_elem_type_t); #endif } + for (i = 0; i < module->table_count; i++) { WASMTable *table = module->tables + i; + + uint32 max_size_fixed = + wasm_get_tbl_data_slots(&table->table_type, NULL); + table_size += offsetof(WASMTableInstance, elems); -#if WASM_ENABLE_MULTI_MODULE != 0 - table_size += - (uint64)sizeof(table_elem_type_t) * table->table_type.max_size; -#else - table_size += - (uint64)sizeof(table_elem_type_t) - * (table->table_type.possible_grow ? table->table_type.max_size - : table->table_type.init_size); -#endif + table_size += (uint64)sizeof(table_elem_type_t) * max_size_fixed; } total_size += table_size; /* The offset of WASMModuleInstanceExtra, make it 8-byte aligned */ - total_size = (total_size + 7LL) & ~7LL; + total_size = (total_size + 7ULL) & ~7ULL; extra_info_offset = (uint32)total_size; total_size += sizeof(WASMModuleInstanceExtra); @@ -2701,9 +2771,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, aux_heap_base_global_data, imports, import_count, error_buf, error_buf_size))) || (module_inst->table_count > 0 - && !(module_inst->tables = - tables_instantiate(module, module_inst, first_table, - error_buf, error_buf_size))) + && !(module_inst->tables = tables_instantiate( + module, module_inst, first_table, imports, import_count, + error_buf, error_buf_size))) || (module_inst->e->function_count > 0 && !(module_inst->e->functions = functions_instantiate( module, module_inst, error_buf, error_buf_size))) @@ -2976,10 +3046,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, #if WASM_ENABLE_GC != 0 /* Initialize the table data with init expr */ + /* bypass WASMTableImport */ for (i = 0; i < module->table_count; i++) { WASMTable *table = module->tables + i; - WASMTableInstance *table_inst = module_inst->tables[i]; - table_elem_type_t *table_data; + /*TBC: confirm*/ + WASMTableInstance *table_inst = + module_inst->tables[i + module->import_table_count]; uint32 j; if (table->init_expr.init_expr_type == 0) { @@ -2987,7 +3059,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, continue; } - table_data = table_inst->elems; + table_elem_type_t *table_data = + wasm_locate_table_elems(module, table_inst, i); bh_assert( table->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL @@ -3035,7 +3108,6 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, WASMTableSeg *table_seg = module->table_segments + i; /* has check it in loader */ WASMTableInstance *table = module_inst->tables[table_seg->table_index]; - table_elem_type_t *table_data; uint32 j; #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 uint8 tbl_elem_type; @@ -3078,7 +3150,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, (void)tbl_max_size; #endif /* end of WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */ - table_data = table->elems; + table_elem_type_t *table_data = + wasm_locate_table_elems(module, table, table_seg->table_index); + #if WASM_ENABLE_MULTI_MODULE != 0 if (table_seg->table_index < module->import_table_count && module_inst->e->table_insts_linked[table_seg->table_index]) { @@ -3521,8 +3595,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) #endif if (module_inst->memory_count > 0) { - memories_deinstantiate(module_inst, module_inst->memories, - module_inst->memory_count); + memories_deinstantiate(module_inst); } if (module_inst->import_func_ptrs) { @@ -4079,7 +4152,9 @@ wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx, } /* fill in */ - new_table_data_start = table_inst->elems + table_inst->cur_size; + table_elem_type_t *table_elems = + wasm_locate_table_elems(module_inst->module, table_inst, table_idx); + new_table_data_start = table_elems + table_inst->cur_size; for (i = 0; i < inc_size; ++i) { new_table_data_start[i] = init_val; } @@ -4113,7 +4188,9 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 tbl_elem_idx, goto got_exception; } - tbl_elem_val = ((table_elem_type_t *)table_inst->elems)[tbl_elem_idx]; + table_elem_type_t *table_elems = + wasm_locate_table_elems(module_inst->module, table_inst, tbl_idx); + tbl_elem_val = table_elems[tbl_elem_idx]; if (tbl_elem_val == NULL_REF) { wasm_set_exception(module_inst, "uninitialized element"); goto got_exception; @@ -4774,7 +4851,6 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, { WASMTableInstance *tbl_inst; WASMTableSeg *tbl_seg; - table_elem_type_t *table_elems; InitializerExpression *tbl_seg_init_values = NULL, *init_values; uint32 i, tbl_seg_len = 0; #if WASM_ENABLE_GC != 0 @@ -4805,7 +4881,9 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, return; } - table_elems = tbl_inst->elems + dst_offset; + table_elem_type_t *table_elems = + wasm_locate_table_elems(module_inst->module, tbl_inst, tbl_idx); + table_elems = table_elems + dst_offset; init_values = tbl_seg_init_values + src_offset; for (i = 0; i < length; i++) { @@ -4879,8 +4957,10 @@ llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx, return; } + table_elem_type_t *table_elems = + wasm_locate_table_elems(module_inst->module, tbl_inst, tbl_idx); for (; length != 0; data_offset++, length--) { - tbl_inst->elems[data_offset] = (table_elem_type_t)val; + table_elems[data_offset] = (table_elem_type_t)val; } } @@ -4924,8 +5004,10 @@ llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx, } /* fill in */ + table_elem_type_t *table_elems = + wasm_locate_table_elems(module_inst->module, tbl_inst, tbl_idx); for (i = 0; i < inc_size; ++i) { - tbl_inst->elems[tbl_inst->cur_size + i] = (table_elem_type_t)init_val; + table_elems[tbl_inst->cur_size + i] = (table_elem_type_t)init_val; } tbl_inst->cur_size = total_size; @@ -5195,19 +5277,19 @@ wasm_get_module_name(WASMModule *module) */ int32 wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst, - WASMExternInstance *out, int32 out_len) + WASMExternInstance *out, uint32 out_len) { if (!module || !inst || !out) return -1; - int32 spawned_import_count = module->import_count; + uint32 spawned_import_count = module->import_count; if (spawned_import_count > out_len) { LOG_WARNING("The number of imported functions is more than the " "length of provided buffer "); return -1; } - for (int32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) { + for (uint32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) { wasm_import_t import_type = { 0 }; wasm_runtime_get_import_type((WASMModuleCommon *)module, i, @@ -5224,6 +5306,7 @@ wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst, #endif import_memory_index++; } + /*TODO: shared_table, shared_global ?*/ else { LOG_WARNING("for spawned, inherit() import(%s,%s) kind %d", import_type.module_name, import_type.name, @@ -5236,19 +5319,19 @@ wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst, void wasm_disinherit_imports(WASMModule *module, WASMExternInstance *imports, - int32 import_count) + uint32 import_count) { if (!module || !imports) return; - int32 spawned_import_count = module->import_count; + uint32 spawned_import_count = module->import_count; if (spawned_import_count > import_count) { LOG_WARNING("The number of imported functions is more than the " "length of provided buffer "); return; } - for (int32 i = 0; i < import_count; i++) { + for (uint32 i = 0; i < import_count; i++) { WASMExternInstance *import = imports + i; if (import->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { @@ -5266,3 +5349,44 @@ wasm_disinherit_imports(WASMModule *module, WASMExternInstance *imports, } } #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */ + +WASMTableInstance * +wasm_create_table(const WASMModule *module, const WASMTableType *type) +{ + /* not an import table for sure */ + uint32 max_size = wasm_get_tbl_data_slots(type, NULL); + + uint64 table_size = offsetof(WASMTableInstance, elems); + table_size += sizeof(table_elem_type_t) * (uint64)max_size; + + WASMTableInstance *table = runtime_malloc(table_size, NULL, 0); + if (!table) { + return NULL; + } + + table->cur_size = type->init_size; + table->elem_type = type->elem_type; + table->max_size = max_size; +#if WASM_ENABLE_GC != 0 + table->elem_ref_type.elem_ref_type = type->elem_ref_type; +#endif + + /* Set all elements to -1 or NULL_REF to mark them as uninitialized + * elements */ +#if WASM_ENABLE_GC == 0 + memset(table->elems, 0xff, sizeof(table_elem_type_t) * table->max_size); +#else + memset(table->elems, 0x00, sizeof(table_elem_type_t) * table->max_size); +#endif + + return table; +} + +void +wasm_destroy_table(WASMTableInstance *table) +{ + if (!table) + return; + + wasm_runtime_free(table); +} \ No newline at end of file diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 363cffd90..6eebaa130 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -166,6 +166,7 @@ struct WASMMemoryInstance { struct WASMTableInstance { /* The element type */ uint8 elem_type; + /* TODO: may not used in AOTTableInstance */ uint8 is_table64; uint8 __padding__[6]; union { @@ -179,6 +180,10 @@ struct WASMTableInstance { /* Maximum size */ uint32 max_size; /* Table elements */ + /* + * if imported tables, it is table_elem_type_t[0][cur_size] + * if local tables, it is table_elem_type_t[cur_size] + */ table_elem_type_t elems[1]; }; @@ -522,6 +527,42 @@ wasm_get_func_code_end(WASMFunctionInstance *func) #endif } +static inline table_elem_type_t * +wasm_locate_table_elems(const WASMModule *module, WASMTableInstance *table, + uint32 table_index) +{ +#if WASM_ENABLE_MULTI_MODULE == 0 + if (table_index < module->import_table_count) { + table_elem_type_t **table_elems = + (table_elem_type_t **)(uintptr_t)table->elems; + + return *table_elems; + } +#endif + return table->elems; +} + +static inline uint32 +wasm_get_tbl_data_slots(const WASMTableType *table_type, + const WASMTableImport *import_type) +{ +#if WASM_ENABLE_MULTI_MODULE != 0 + if (import_type) { + if (import_type->import_module) { + /* linked with other modules */ + return table_type->max_size; + } + + /* else linked with built-ins */ + } + return table_type->max_size; +#else + /* in order to save memory, alloc resource as few as possible */ + return table_type->possible_grow ? table_type->max_size + : table_type->init_size; +#endif +} + WASMModule * wasm_load(uint8 *buf, uint32 size, #if WASM_ENABLE_MULTI_MODULE != 0 @@ -898,13 +939,23 @@ wasm_get_module_name(WASMModule *module); #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 int32 wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst, - WASMExternInstance *out, int32 out_len); + WASMExternInstance *out, uint32 out_len); void wasm_disinherit_imports(WASMModule *module, WASMExternInstance *imports, - int32 import_count); + uint32 import_count); #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */ +WASMTableInstance * +wasm_create_table(const WASMModule *module, const WASMTableType *type); + +bool +wasm_set_table_elem(const WASMModule *module, WASMTableInstance *table, + uint32 index, uint32 func_idx); + +void +wasm_destroy_table(WASMTableInstance *table); + #ifdef __cplusplus } #endif diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index af50223a4..9fa1ba33a 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -671,12 +671,12 @@ main(int argc, char *argv[]) else if (!strncmp(argv[0], "--stack-size=", 13)) { if (argv[0][13] == '\0') return print_help(); - stack_size = atoi(argv[0] + 13); + stack_size = (uint32)atoi(argv[0] + 13); } else if (!strncmp(argv[0], "--heap-size=", 12)) { if (argv[0][12] == '\0') return print_help(); - heap_size = atoi(argv[0] + 12); + heap_size = (uint32)atoi(argv[0] + 12); } #if WASM_ENABLE_FAST_JIT != 0 else if (!strncmp(argv[0], "--jit-codecache-size=", 21)) { @@ -874,7 +874,7 @@ main(int argc, char *argv[]) } #if WASM_ENABLE_LOG != 0 - bh_log_set_verbose_level(log_verbose_level); + bh_log_set_verbose_level((uint32)log_verbose_level); #endif #if BH_HAS_DLFCN diff --git a/samples/linking/CMakeLists.txt b/samples/linking/CMakeLists.txt index 51225b0f9..4cd86fcf9 100644 --- a/samples/linking/CMakeLists.txt +++ b/samples/linking/CMakeLists.txt @@ -9,6 +9,9 @@ set(CMAKE_BUILD_TYPE Debug) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) find_package(WASISDK REQUIRED) +include(CTest) +enable_testing() + ################ runtime settings ################ string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) include(CheckPIESupported) @@ -30,6 +33,12 @@ set(WAMR_BUILD_TAIL_CALL 1) set(WAMR_BUILD_THREAD_MGR 0) set(WAMR_BUILD_LIB_WASI_THREADS 0) +## below two prevent valgrind from crashing +#TODO: there is a crash if turn it on +set(WAMR_DISABLE_HW_BOUND_CHECK 0) +set(WAMR_DISABLE_STACK_HW_BOUND_CHECK 1) +set(WAMR_DISABLE_WRITE_GS_BASE 1) + # vmlib set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) @@ -38,7 +47,8 @@ target_include_directories(vmlib INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include) target_link_libraries(vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl) ################ samples ################ -add_subdirectory(raw) +add_subdirectory(import-memory) +add_subdirectory(import-table) ################ wasm and/or aot ################ include(ExternalProject) diff --git a/samples/linking/import-memory/CMakeLists.txt b/samples/linking/import-memory/CMakeLists.txt new file mode 100644 index 000000000..3b1275b63 --- /dev/null +++ b/samples/linking/import-memory/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) +add_executable(import_memory main.c ${UNCOMMON_SHARED_SOURCE}) +target_link_libraries(import_memory PRIVATE vmlib) + +add_test(NAME Test_import_memory + COMMAND ./import-memory/import_memory + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/.. +) diff --git a/samples/linking/raw/main.c b/samples/linking/import-memory/main.c similarity index 91% rename from samples/linking/raw/main.c rename to samples/linking/import-memory/main.c index 41a5410ba..fceceeee8 100644 --- a/samples/linking/raw/main.c +++ b/samples/linking/import-memory/main.c @@ -44,10 +44,13 @@ main(int argc, char *argv_main[]) /* import type */ int32_t import_count = wasm_runtime_get_import_count(module); + if (import_count < 0) + goto unload_module; + wasm_import_t import_type = { 0 }; int32_t import_memory_index = -1; - for (int i = 0; i < import_count; i++) { - wasm_runtime_get_import_type(module, i, &import_type); + for (int32_t i = 0; i < import_count; i++) { + wasm_runtime_get_import_type(module, (uint32_t)i, &import_type); if (import_type.kind == WASM_IMPORT_EXPORT_KIND_MEMORY) { import_memory_index = i; break; @@ -76,6 +79,7 @@ main(int argc, char *argv_main[]) /* wasm instance */ InstantiationArgs inst_args = { + .default_stack_size = 65536, .imports = import_list, .import_count = 10, }; @@ -83,7 +87,9 @@ main(int argc, char *argv_main[]) module, &inst_args, error_buf, sizeof(error_buf)); if (!inst) { printf("Instantiate wasm file failed: %s\n", error_buf); - goto destroy_memory; + wasm_runtime_destroy_memory(module, memory); + memory = NULL; + goto unload_module; } /* export function */ @@ -94,7 +100,7 @@ main(int argc, char *argv_main[]) goto destroy_inst; } - wasm_exec_env_t exec_env = wasm_runtime_create_exec_env(inst, 8192); + wasm_exec_env_t exec_env = wasm_runtime_create_exec_env(inst, 65536); if (!exec_env) { printf("Create wasm execution environment failed.\n"); goto destroy_inst; @@ -112,8 +118,6 @@ destroy_exec_env: wasm_runtime_destroy_exec_env(exec_env); destroy_inst: wasm_runtime_deinstantiate(inst); -destroy_memory: - wasm_runtime_destroy_memory(module, memory); unload_module: wasm_runtime_unload(module); release_file_buffer: diff --git a/samples/linking/import-table/CMakeLists.txt b/samples/linking/import-table/CMakeLists.txt new file mode 100644 index 000000000..0e64bd482 --- /dev/null +++ b/samples/linking/import-table/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) +add_executable(import_table main.c ${UNCOMMON_SHARED_SOURCE}) +target_link_libraries(import_table PRIVATE vmlib) + +add_test(NAME Test_import_table + COMMAND ./import-table/import_table + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/.. +) \ No newline at end of file diff --git a/samples/linking/import-table/main.c b/samples/linking/import-table/main.c new file mode 100644 index 000000000..f81865ea2 --- /dev/null +++ b/samples/linking/import-table/main.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ +#include "wasm_export.h" +#include "bh_read_file.h" + +int +main(int argc, char *argv_main[]) +{ + int exit_code = EXIT_FAILURE; + + /* runtime */ + if (!wasm_runtime_init()) { + printf("Init runtime failed.\n"); + return EXIT_FAILURE; + } + + wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE); + + /* wasm module file */ + char *buffer; + uint32 buf_size; +#if WASM_ENABLE_AOT != 0 + printf("Loading AOT file...\n"); + buffer = bh_read_file_to_buffer("import_table.aot", &buf_size); +#else + printf("Loading WASM file...\n"); + buffer = bh_read_file_to_buffer("import_table.wasm", &buf_size); +#endif + if (!buffer) { + printf("Open wasm file failed.\n"); + goto destroy_runtime; + } + + /* wasm module */ + char error_buf[128]; + wasm_module_t module = wasm_runtime_load((uint8 *)buffer, buf_size, + error_buf, sizeof(error_buf)); + if (!module) { + printf("Load wasm file failed: %s\n", error_buf); + goto release_file_buffer; + } + + /* import type */ + int32_t import_count = wasm_runtime_get_import_count(module); + if (import_count < 0) + goto unload_module; + + wasm_import_t import_type = { 0 }; + int32_t import_table_index = -1; + for (int32_t i = 0; i < import_count; i++) { + wasm_runtime_get_import_type(module, (uint32_t)i, &import_type); + if (import_type.kind == WASM_IMPORT_EXPORT_KIND_TABLE) { + import_table_index = i; + break; + } + } + + if (import_table_index == -1) { + printf("No memory import found.\n"); + goto unload_module; + } + + /* host table */ + wasm_table_type_t table_type = import_type.u.table_type; + wasm_table_inst_t *table = wasm_runtime_create_table(module, table_type); + if (!table) { + printf("Create table failed.\n"); + goto unload_module; + } + + /* import list */ + WASMExternInstance import_list[10] = { 0 }; + import_list[import_table_index].module_name = "host"; + import_list[import_table_index].field_name = "__indirect_function_table"; + import_list[import_table_index].kind = WASM_IMPORT_EXPORT_KIND_TABLE; + import_list[import_table_index].u.table = table; + + /* wasm instance */ + InstantiationArgs inst_args = { + .imports = import_list, + .import_count = 10, + }; + wasm_module_inst_t inst = wasm_runtime_instantiate_ex( + module, &inst_args, error_buf, sizeof(error_buf)); + if (!inst) { + printf("Instantiate wasm file failed: %s\n", error_buf); + goto destroy_table; + } + + /* export function */ + if (!wasm_application_execute_main(inst, 0, NULL)) { + const char *exception = wasm_runtime_get_exception(inst); + printf("call wasm function main() failed. %s\n", exception); + goto destroy_inst; + } + + exit_code = EXIT_SUCCESS; + +destroy_inst: + wasm_runtime_deinstantiate(inst); +destroy_table: + wasm_runtime_destroy_table(module, table); +unload_module: + wasm_runtime_unload(module); +release_file_buffer: + wasm_runtime_free(buffer); +destroy_runtime: + wasm_runtime_destroy(); + + return exit_code; +} \ No newline at end of file diff --git a/samples/linking/raw/CMakeLists.txt b/samples/linking/raw/CMakeLists.txt deleted file mode 100644 index deee61a77..000000000 --- a/samples/linking/raw/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) -add_executable(raw main.c ${UNCOMMON_SHARED_SOURCE}) -target_link_libraries(raw PRIVATE vmlib) diff --git a/samples/linking/wasm/CMakeLists.txt b/samples/linking/wasm/CMakeLists.txt index 7fe8e401c..5f02735f1 100644 --- a/samples/linking/wasm/CMakeLists.txt +++ b/samples/linking/wasm/CMakeLists.txt @@ -22,6 +22,14 @@ target_link_options(import_memory set_target_properties(import_memory PROPERTIES SUFFIX .wasm) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_memory.wasm DESTINATION .) +add_executable(import_table import_table.c) +target_link_options(import_table + PRIVATE + LINKER:--import-table +) +set_target_properties(import_table PROPERTIES SUFFIX .wasm) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_table.wasm DESTINATION .) + if(WAMR_BUILD_AOT EQUAL 1) add_custom_target ( import_memory_aot @@ -31,5 +39,14 @@ if(WAMR_BUILD_AOT EQUAL 1) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_memory.aot DESTINATION .) + + add_custom_target( + import_table_aot + ALL + DEPENDS ${WAMRC_BIN} import_table + COMMAND ${WAMRC_BIN} -o import_table.aot import_table.wasm + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_table.aot DESTINATION .) endif() diff --git a/samples/linking/wasm/import_table.c b/samples/linking/wasm/import_table.c new file mode 100644 index 000000000..af7489150 --- /dev/null +++ b/samples/linking/wasm/import_table.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ +#include +#include +#include +#include +#include +#include + +int +add(int a, int b) +{ + return a + b; +} + +int +subtract(int a, int b) +{ + return a - b; +} + +int +main() +{ + int (*operation)(int, int); + + operation = add; + int result = operation(5, 3); + printf("Result of addition: %d\n", operation(5, 3)); + assert(result == 8 && "Addition failed"); + + operation = subtract; + result = operation(5, 3); + printf("Result of subtraction: %d\n", operation(5, 3)); + assert(result == 2 && "Subtraction failed"); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 97820eaad..72c733d75 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -1148,6 +1148,9 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = ' cmd.append("--format=object") elif output == 'ir': cmd.append("--format=llvmir-opt") + + if opts.multi_module: + cmd.append("--enable-multi-module") # disable llvm link time optimization as it might convert # code of tail call into code of dead loop, and stack overflow diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 70a8b687c..fbcbfe202 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -829,11 +829,19 @@ function build_wamrc() fi echo "Build wamrc for spec test under aot compile type" + + local EXTRA_COMPILE_FLAGS="" + EXTRA_COMPILE_FLAGS+=" -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + + if [[ ${ENABLE_DEBUG_VERSION} == 1 ]]; then + EXTRA_COMPILE_FLAGS+=" -DCMAKE_BUILD_TYPE=Debug" + fi + cd ${WAMR_DIR}/wamr-compiler \ && ./${BUILD_LLVM_SH} \ && if [ -d build ]; then rm -r build/*; else mkdir build; fi \ && cd build \ - && cmake .. -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE} \ + && cmake ${EXTRA_COMPILE_FLAGS} .. \ && make -j 4 } diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 3efe344e6..7af52a221 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -207,6 +207,8 @@ print_help() #endif printf(" --mllvm=