diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index bc8ff4c7..9d80c371 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -250,13 +250,13 @@ typedef union WASMValue { #endif /* end of WASM_VALUE_DEFINED */ typedef struct WASMStructNewInitValues { - uint8 type_idx; + uint32 type_idx; uint32 count; WASMValue fields[1]; } WASMStructNewInitValues; typedef struct WASMArrayNewInitValues { - uint8 type_idx; + uint32 type_idx; uint32 length; WASMValue elem_data[1]; } WASMArrayNewInitValues; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 54e7041a..cfd84654 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -501,6 +501,8 @@ push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type, error_buf, error_buf_size))) { goto fail; } + bh_memcpy_s(ctx->stack, (ctx->size + 4) * (uint32)sizeof(InitValue), + ctx->data, ctx->size * (uint32)sizeof(InitValue)); } ctx->size += 4; } @@ -523,6 +525,71 @@ fail: return false; } +#if WASM_ENABLE_GC != 0 +static void +destroy_init_expr_data_recursive(WASMModule *module, void *data) +{ + WASMStructNewInitValues *struct_init_values = + (WASMStructNewInitValues *)data; + WASMArrayNewInitValues *array_init_values = (WASMArrayNewInitValues *)data; + WASMType *wasm_type; + uint32 i; + + if (!data) + return; + + wasm_type = module->types[struct_init_values->type_idx]; + + /* The data can only be type of `WASMStructNewInitValues *` + or `WASMArrayNewInitValues *` */ + bh_assert(wasm_type->type_flag == WASM_TYPE_STRUCT + || wasm_type->type_flag == WASM_TYPE_ARRAY); + + if (wasm_type->type_flag == WASM_TYPE_STRUCT) { + WASMStructType *struct_type = (WASMStructType *)wasm_type; + WASMRefTypeMap *ref_type_map = struct_type->ref_type_maps; + WASMRefType *ref_type; + uint8 field_type; + + for (i = 0; i < struct_init_values->count; i++) { + field_type = struct_type->fields[i].field_type; + if (wasm_is_type_multi_byte_type(field_type)) + ref_type = ref_type_map->ref_type; + else + ref_type = NULL; + if (wasm_reftype_is_subtype_of(field_type, ref_type, + REF_TYPE_STRUCTREF, NULL, + module->types, module->type_count) + || wasm_reftype_is_subtype_of( + field_type, ref_type, REF_TYPE_ARRAYREF, NULL, + module->types, module->type_count)) { + destroy_init_expr_data_recursive( + module, struct_init_values->fields[i].data); + } + } + } + else if (wasm_type->type_flag == WASM_TYPE_ARRAY) { + WASMArrayType *array_type = (WASMArrayType *)wasm_type; + WASMRefType *elem_ref_type = array_type->elem_ref_type; + uint8 elem_type = array_type->elem_type; + + for (i = 0; i < array_init_values->length; i++) { + if (wasm_reftype_is_subtype_of(elem_type, elem_ref_type, + REF_TYPE_STRUCTREF, NULL, + module->types, module->type_count) + || wasm_reftype_is_subtype_of( + elem_type, elem_ref_type, REF_TYPE_ARRAYREF, NULL, + module->types, module->type_count)) { + destroy_init_expr_data_recursive( + module, array_init_values->elem_data[i].data); + } + } + } + + wasm_runtime_free(data); +} +#endif + static bool pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type, #if WASM_ENABLE_GC != 0 @@ -554,17 +621,6 @@ pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type, " but got other"); goto fail; } - - if ((ctx->sp != 0) && (cur_value->flag == WASM_OP_GC_PREFIX) - && (cur_value->gc_opcode != WASM_OP_REF_I31)) { - /* To reduce complexity, we don't allow initialize struct fields/array - * element with references, so struct/array must be at the bottom of the - * init value stack */ - set_error_buf( - error_buf, error_buf_size, - "struct or array as field is not supported in constant expr"); - goto fail; - } #endif if (p_flag) @@ -584,7 +640,7 @@ fail: && (cur_value->gc_opcode == WASM_OP_STRUCT_NEW || cur_value->gc_opcode == WASM_OP_ARRAY_NEW || cur_value->gc_opcode == WASM_OP_ARRAY_NEW_FIXED)) { - wasm_runtime_free(cur_value->value.data); + destroy_init_expr_data_recursive(ctx->module, cur_value->value.data); } return false; #endif @@ -601,7 +657,8 @@ destroy_const_expr_stack(ConstExprContext *ctx) && (ctx->stack[i].gc_opcode == WASM_OP_STRUCT_NEW || ctx->stack[i].gc_opcode == WASM_OP_ARRAY_NEW || ctx->stack[i].gc_opcode == WASM_OP_ARRAY_NEW_FIXED)) { - wasm_runtime_free(ctx->stack[i].value.data); + destroy_init_expr_data_recursive(ctx->module, + ctx->stack[i].value.data); } } #endif @@ -613,12 +670,12 @@ destroy_const_expr_stack(ConstExprContext *ctx) #if WASM_ENABLE_GC != 0 static void -destroy_init_expr(InitializerExpression *expr) +destroy_init_expr(WASMModule *module, InitializerExpression *expr) { if (expr->init_expr_type == INIT_EXPR_TYPE_STRUCT_NEW || expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW || expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) { - wasm_runtime_free(expr->u.data); + destroy_init_expr_data_recursive(module, expr->u.data); } } #endif /* end of WASM_ENABLE_GC != 0 */ @@ -941,6 +998,7 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end, error_buf, error_buf_size))) { goto fail; } + struct_init_values->type_idx = type_idx; struct_init_values->count = field_count; for (i = field_count; i > 0; i--) { @@ -963,7 +1021,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end, field_ref_type, NULL, &struct_init_values->fields[field_idx], error_buf, error_buf_size)) { - wasm_runtime_free(struct_init_values); + destroy_init_expr_data_recursive( + module, struct_init_values); goto fail; } } @@ -975,7 +1034,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end, &const_expr_ctx, flag, cur_ref_type.ref_type, &cur_ref_type, (uint8)opcode1, &cur_value, error_buf, error_buf_size)) { - wasm_runtime_free(struct_init_values); + destroy_init_expr_data_recursive( + module, struct_init_values); goto fail; } break; @@ -1059,7 +1119,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end, &const_expr_ctx, NULL, VALUE_TYPE_I32, NULL, NULL, &len_val, error_buf, error_buf_size)) { - wasm_runtime_free(array_init_values); + destroy_init_expr_data_recursive( + module, array_init_values); goto fail; } array_init_values->length = len_val.i32; @@ -1069,7 +1130,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end, elem_ref_type, NULL, &array_init_values->elem_data[0], error_buf, error_buf_size)) { - wasm_runtime_free(array_init_values); + destroy_init_expr_data_recursive( + module, array_init_values); goto fail; } @@ -1100,7 +1162,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end, &array_init_values ->elem_data[i - 1], error_buf, error_buf_size)) { - wasm_runtime_free(array_init_values); + destroy_init_expr_data_recursive( + module, array_init_values); goto fail; } } @@ -1133,7 +1196,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end, &cur_ref_type, (uint8)opcode1, &cur_value, error_buf, error_buf_size)) { if (array_init_values) { - wasm_runtime_free(array_init_values); + destroy_init_expr_data_recursive( + module, array_init_values); } goto fail; } @@ -6669,14 +6733,6 @@ wasm_loader_unload(WASMModule *module) } #endif - if (module->types) { - for (i = 0; i < module->type_count; i++) { - if (module->types[i]) - destroy_wasm_type(module->types[i]); - } - wasm_runtime_free(module->types); - } - if (module->imports) wasm_runtime_free(module->imports); @@ -6718,7 +6774,7 @@ wasm_loader_unload(WASMModule *module) if (module->tables) { #if WASM_ENABLE_GC != 0 for (i = 0; i < module->table_count; i++) { - destroy_init_expr(&module->tables[i].init_expr); + destroy_init_expr(module, &module->tables[i].init_expr); } #endif wasm_runtime_free(module->tables); @@ -6730,7 +6786,7 @@ wasm_loader_unload(WASMModule *module) if (module->globals) { #if WASM_ENABLE_GC != 0 for (i = 0; i < module->global_count; i++) { - destroy_init_expr(&module->globals[i].init_expr); + destroy_init_expr(module, &module->globals[i].init_expr); } #endif wasm_runtime_free(module->globals); @@ -6756,7 +6812,7 @@ wasm_loader_unload(WASMModule *module) uint32 j; for (j = 0; j < module->table_segments[i].value_count; j++) { destroy_init_expr( - &module->table_segments[i].init_values[j]); + module, &module->table_segments[i].init_values[j]); } #endif wasm_runtime_free(module->table_segments[i].init_values); @@ -6773,6 +6829,14 @@ wasm_loader_unload(WASMModule *module) wasm_runtime_free(module->data_segments); } + if (module->types) { + for (i = 0; i < module->type_count; i++) { + if (module->types[i]) + destroy_wasm_type(module->types[i]); + } + wasm_runtime_free(module->types); + } + if (module->const_str_list) { StringNode *node = module->const_str_list, *node_next; while (node) { @@ -11654,12 +11718,29 @@ re_scan: case WASM_OP_RETURN: { + WASMFuncType *func_type = func->func_type; int32 idx; uint8 ret_type; - for (idx = (int32)func->func_type->result_count - 1; idx >= 0; + +#if WASM_ENABLE_GC != 0 + uint32 j = func_type->ref_type_map_count - 1; +#endif + for (idx = (int32)func_type->result_count - 1; idx >= 0; idx--) { - ret_type = *(func->func_type->types - + func->func_type->param_count + idx); + ret_type = + *(func_type->types + func_type->param_count + idx); +#if WASM_ENABLE_GC != 0 + if (wasm_is_type_multi_byte_type(ret_type)) { + WASMRefType *ref_type = + func_type->ref_type_maps[j].ref_type; + bh_assert(func_type->ref_type_maps[j].index + == func_type->param_count + idx); + bh_memcpy_s(&wasm_ref_type, sizeof(WASMRefType), + ref_type, + wasm_reftype_struct_size(ref_type)); + j--; + } +#endif #if WASM_ENABLE_FAST_INTERP != 0 /* emit the offset after return opcode */ POP_OFFSET_TYPE(ret_type); diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index c9473a0d..50634377 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -866,6 +866,174 @@ check_global_init_expr(const WASMModule *module, uint32 global_index, return true; } +#if WASM_ENABLE_GC != 0 +/* Instantiate struct global variable recursively */ +static WASMStructObjectRef +instantiate_struct_global_recursive(WASMModule *module, + WASMModuleInstance *module_inst, + uint32 type_idx, uint8 flag, + WASMStructNewInitValues *init_values, + char *error_buf, uint32 error_buf_size) +{ + WASMRttType *rtt_type; + WASMStructObjectRef struct_obj; + WASMStructType *struct_type; + + struct_type = (WASMStructType *)module->types[type_idx]; + + if (!(rtt_type = wasm_rtt_type_new((WASMType *)struct_type, type_idx, + module->rtt_types, module->type_count, + &module->rtt_type_lock))) { + set_error_buf(error_buf, error_buf_size, "create rtt object failed"); + return NULL; + } + + if (!(struct_obj = wasm_struct_obj_new_internal( + module_inst->e->common.gc_heap_handle, rtt_type))) { + set_error_buf(error_buf, error_buf_size, "create struct object failed"); + return NULL; + } + + if (flag == INIT_EXPR_TYPE_STRUCT_NEW) { + uint32 field_idx; + WASMRefTypeMap *ref_type_map = struct_type->ref_type_maps; + + bh_assert(init_values->count == struct_type->field_count); + + for (field_idx = 0; field_idx < init_values->count; field_idx++) { + uint8 field_type = struct_type->fields[field_idx].field_type; + WASMRefType *field_ref_type = NULL; + if (wasm_is_type_multi_byte_type(field_type)) { + field_ref_type = ref_type_map->ref_type; + } + + if (wasm_reftype_is_subtype_of(field_type, field_ref_type, + REF_TYPE_STRUCTREF, NULL, + module->types, module->type_count) + || wasm_reftype_is_subtype_of(field_type, field_ref_type, + REF_TYPE_ARRAYREF, NULL, + module->types, module->type_count) + || wasm_reftype_is_subtype_of( + field_type, field_ref_type, REF_TYPE_FUNCREF, NULL, + module->types, module->type_count)) { + WASMType *wasm_type; + int32 heap_type = + ref_type_map->ref_type->ref_ht_common.heap_type; + WASMValue *wasm_value = &init_values->fields[field_idx]; + WASMValue field_value = { 0 }; + + bh_assert(heap_type >= 0); + wasm_type = module->types[heap_type]; + + bh_assert(wasm_type->type_flag == WASM_TYPE_STRUCT + && wasm_type->type_flag == WASM_TYPE_ARRAY + && wasm_type->type_flag == WASM_TYPE_FUNC); + + if (wasm_type->type_flag == WASM_TYPE_STRUCT) { + WASMStructNewInitValues *init_values1 = + (WASMStructNewInitValues *)wasm_value->data; + WASMStructObjectRef field = + instantiate_struct_global_recursive( + module, module_inst, heap_type, + init_values1 ? INIT_EXPR_TYPE_STRUCT_NEW + : INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT, + init_values1, error_buf, error_buf_size); + field_value.gc_obj = (WASMObjectRef)field; + wasm_struct_obj_set_field(struct_obj, field_idx, + &field_value); + } + else if (wasm_type->type_flag == WASM_TYPE_ARRAY) { + /* struct object's field is an array obj */ + set_error_buf(error_buf, error_buf_size, + "array as a field in struct object is " + "not supported in constant init expr"); + return NULL; + } + else if (wasm_type->type_flag == WASM_TYPE_FUNC) { + WASMFuncObjectRef func_obj = NULL; + /* UINT32_MAX indicates that it is a null reference */ + if (wasm_value->u32 != UINT32_MAX) { + if (!(func_obj = wasm_create_func_obj( + module_inst, wasm_value->u32, false, + error_buf, error_buf_size))) { + return NULL; + } + } + field_value.gc_obj = (WASMObjectRef)func_obj; + wasm_struct_obj_set_field(struct_obj, field_idx, + &field_value); + } + } + else { + wasm_struct_obj_set_field(struct_obj, field_idx, + &init_values->fields[field_idx]); + } + if (wasm_is_type_multi_byte_type(field_type)) { + ref_type_map++; + } + } + } + + return struct_obj; +} + +static WASMArrayObjectRef +instantiate_array_global_recursive(WASMModule *module, + WASMModuleInstance *module_inst, + uint32 type_idx, uint8 flag, uint32 len, + WASMValue *array_init_value, + WASMArrayNewInitValues *init_values, + char *error_buf, uint32 error_buf_size) +{ + WASMRttType *rtt_type; + WASMArrayObjectRef array_obj; + WASMArrayType *array_type; + + array_type = (WASMArrayType *)module->types[type_idx]; + + if (!(rtt_type = wasm_rtt_type_new((WASMType *)array_type, type_idx, + module->rtt_types, module->type_count, + &module->rtt_type_lock))) { + set_error_buf(error_buf, error_buf_size, "create rtt object failed"); + return NULL; + } + + if (!(array_obj = + wasm_array_obj_new_internal(module_inst->e->common.gc_heap_handle, + rtt_type, len, array_init_value))) { + set_error_buf(error_buf, error_buf_size, "create array object failed"); + return NULL; + } + + if (flag == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) { + uint32 elem_idx; + uint8 elem_type = array_type->elem_type; + WASMRefType *elem_ref_type = array_type->elem_ref_type; + + bh_assert(init_values); + + if (wasm_reftype_is_subtype_of(elem_type, elem_ref_type, + REF_TYPE_STRUCTREF, NULL, module->types, + module->type_count) + || wasm_reftype_is_subtype_of(elem_type, elem_ref_type, + REF_TYPE_ARRAYREF, NULL, + module->types, module->type_count) + || wasm_reftype_is_subtype_of(elem_type, elem_ref_type, + REF_TYPE_FUNCREF, NULL, module->types, + module->type_count)) { + /* TODO */ + } + + for (elem_idx = 0; elem_idx < len; elem_idx++) { + wasm_array_obj_set_elem(array_obj, elem_idx, + &init_values->elem_data[elem_idx]); + } + } + + return array_obj; +} +#endif + /** * Instantiate globals in a module. */ @@ -964,9 +1132,7 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, case INIT_EXPR_TYPE_STRUCT_NEW: case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT: { - WASMRttType *rtt_type; WASMStructObjectRef struct_obj; - WASMStructType *struct_type; WASMStructNewInitValues *init_values = NULL; uint32 type_idx; @@ -978,36 +1144,13 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, type_idx = init_expr->u.type_index; } - struct_type = (WASMStructType *)module->types[type_idx]; - - if (!(rtt_type = wasm_rtt_type_new( - (WASMType *)struct_type, type_idx, module->rtt_types, - module->type_count, &module->rtt_type_lock))) { - set_error_buf(error_buf, error_buf_size, - "create rtt object failed"); + struct_obj = instantiate_struct_global_recursive( + module, module_inst, type_idx, flag, init_values, error_buf, + error_buf_size); + if (!struct_obj) { goto fail; } - if (!(struct_obj = wasm_struct_obj_new_internal( - module_inst->e->common.gc_heap_handle, rtt_type))) { - set_error_buf(error_buf, error_buf_size, - "create struct object failed"); - goto fail; - } - - if (flag == INIT_EXPR_TYPE_STRUCT_NEW) { - uint32 field_idx; - - bh_assert(init_values->count == struct_type->field_count); - - for (field_idx = 0; field_idx < init_values->count; - field_idx++) { - wasm_struct_obj_set_field( - struct_obj, field_idx, - &init_values->fields[field_idx]); - } - } - global->initial_value.gc_obj = (void *)struct_obj; break; } @@ -1015,17 +1158,15 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT: case INIT_EXPR_TYPE_ARRAY_NEW_FIXED: { - WASMRttType *rtt_type; WASMArrayObjectRef array_obj; - WASMArrayType *array_type; WASMArrayNewInitValues *init_values = NULL; - WASMValue *arr_init_val = NULL, empty_val = { 0 }; + WASMValue *array_init_value = NULL, empty_value = { 0 }; uint32 type_idx, len; if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) { type_idx = init_expr->u.array_new_default.type_index; len = init_expr->u.array_new_default.length; - arr_init_val = &empty_val; + array_init_value = &empty_value; } else { init_values = (WASMArrayNewInitValues *)init_expr->u.data; @@ -1033,42 +1174,15 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, len = init_values->length; if (flag == INIT_EXPR_TYPE_ARRAY_NEW) { - arr_init_val = init_values->elem_data; + array_init_value = init_values->elem_data; } } - array_type = (WASMArrayType *)module->types[type_idx]; - - if (!(rtt_type = wasm_rtt_type_new( - (WASMType *)array_type, type_idx, module->rtt_types, - module->type_count, &module->rtt_type_lock))) { - set_error_buf(error_buf, error_buf_size, - "create rtt object failed"); - goto fail; - } - - if (!(array_obj = wasm_array_obj_new_internal( - module_inst->e->common.gc_heap_handle, rtt_type, len, - arr_init_val))) { - set_error_buf(error_buf, error_buf_size, - "create array object failed"); - goto fail; - } - - if (flag == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) { - uint32 elem_idx; - - bh_assert(init_values); - - for (elem_idx = 0; elem_idx < len; elem_idx++) { - wasm_array_obj_set_elem( - array_obj, elem_idx, - &init_values->elem_data[elem_idx]); - } - } + array_obj = instantiate_array_global_recursive( + module, module_inst, type_idx, flag, len, array_init_value, + init_values, error_buf, error_buf_size); global->initial_value.gc_obj = (void *)array_obj; - break; } case INIT_EXPR_TYPE_I31_NEW: @@ -1704,7 +1818,6 @@ wasm_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx, WASMModule *module = module_inst->module; WASMRttTypeRef rtt_type; WASMFuncObjectRef func_obj; - WASMFunctionInstance *func_inst; WASMFuncType *func_type; uint32 type_idx; @@ -1713,17 +1826,22 @@ wasm_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx, error_buf_size = sizeof(module_inst->cur_exception); } - if (func_idx >= module_inst->e->function_count) { + if (func_idx >= module->import_function_count + module->function_count) { set_error_buf_v(error_buf, error_buf_size, "unknown function %d", func_idx); return NULL; } - func_inst = &module_inst->e->functions[func_idx]; - func_type = func_inst->is_import_func ? func_inst->u.func_import->func_type - : func_inst->u.func->func_type; - type_idx = func_inst->is_import_func ? func_inst->u.func_import->type_idx - : func_inst->u.func->type_idx; + if (func_idx < module->import_function_count) { + func_type = module->import_functions[func_idx].u.function.func_type; + type_idx = module->import_functions[func_idx].u.function.type_idx; + } + else { + func_type = module->functions[func_idx - module->import_function_count] + ->func_type; + type_idx = module->functions[func_idx - module->import_function_count] + ->type_idx; + } if (!(rtt_type = wasm_rtt_type_new((WASMType *)func_type, type_idx, module->rtt_types, module->type_count,