Explorar el Código

Enhance GC const initializer expression to support nested struct/array new (#3447)

Only support interpreter now, and fix some issues found in wasm loader.

This PR fixes issue #3410 and #3411.
Wenyong Huang hace 1 año
padre
commit
15d191943a

+ 2 - 2
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;

+ 116 - 35
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);

+ 189 - 71
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,