Просмотр исходного кода

Sync up with the latest GC MVP spec proposal (#2836)

Xu Jun 2 лет назад
Родитель
Сommit
92176be7d6
34 измененных файлов с 3978 добавлено и 1261 удалено
  1. 1 1
      .github/workflows/compilation_on_android_ubuntu.yml
  2. 4 8
      build-scripts/config_common.cmake
  3. 0 4
      build-scripts/runtime_lib.cmake
  4. 6 3
      core/config.h
  5. 305 32
      core/iwasm/aot/aot_loader.c
  6. 361 44
      core/iwasm/aot/aot_runtime.c
  7. 12 21
      core/iwasm/common/gc/gc_common.c
  8. 64 24
      core/iwasm/common/gc/gc_object.c
  9. 8 0
      core/iwasm/common/gc/gc_object.h
  10. 9 4
      core/iwasm/common/gc/gc_type.c
  11. 27 10
      core/iwasm/common/gc/gc_type.h
  12. 39 4
      core/iwasm/common/wasm_application.c
  13. 2 2
      core/iwasm/common/wasm_runtime_common.c
  14. 27 17
      core/iwasm/compilation/aot.c
  15. 4 2
      core/iwasm/compilation/aot.h
  16. 43 29
      core/iwasm/compilation/aot_compiler.c
  17. 9 5
      core/iwasm/compilation/aot_compiler.h
  18. 338 35
      core/iwasm/compilation/aot_emit_aot_file.c
  19. 152 4
      core/iwasm/compilation/aot_emit_gc.c
  20. 4 2
      core/iwasm/compilation/aot_emit_gc.h
  21. 11 8
      core/iwasm/fast-jit/fe/jit_emit_table.c
  22. 20 13
      core/iwasm/include/gc_export.h
  23. 69 44
      core/iwasm/interpreter/wasm.h
  24. 129 76
      core/iwasm/interpreter/wasm_interp_classic.c
  25. 131 75
      core/iwasm/interpreter/wasm_interp_fast.c
  26. 767 246
      core/iwasm/interpreter/wasm_loader.c
  27. 364 145
      core/iwasm/interpreter/wasm_mini_loader.c
  28. 46 60
      core/iwasm/interpreter/wasm_opcode.h
  29. 411 106
      core/iwasm/interpreter/wasm_runtime.c
  30. 4 0
      core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c
  31. 1 1
      tests/wamr-test-suites/spec-test-script/all.py
  32. 606 230
      tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch
  33. 4 3
      tests/wamr-test-suites/test_wamr.sh
  34. 0 3
      wamr-compiler/CMakeLists.txt

+ 1 - 1
.github/workflows/compilation_on_android_ubuntu.yml

@@ -530,7 +530,7 @@ jobs:
 
       - name: Set-up Ocamlbuild
         if: matrix.test_option == '$GC_TEST_OPTIONS'
-        run: opam install ocamlbuild
+        run: opam install ocamlbuild dune
 
       - name: download and install wasi-sdk
         if: matrix.test_option == '$WASI_TEST_OPTIONS'

+ 4 - 8
build-scripts/config_common.cmake

@@ -142,7 +142,7 @@ elseif (WAMR_BUILD_SANITIZER STREQUAL "asan")
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fno-omit-frame-pointer -fsanitize=address -fno-sanitize-recover=all" )
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
   endif()
-elseif (WAMR_BUILD_SANITIZER STREQUAL "tsan") 
+elseif (WAMR_BUILD_SANITIZER STREQUAL "tsan")
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all" )
   set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread")
 elseif (NOT (WAMR_BUILD_SANITIZER STREQUAL "") )
@@ -337,10 +337,6 @@ if (WAMR_BUILD_GC EQUAL 1 AND WAMR_BUILD_GC_PERF_PROFILING EQUAL 1)
 else ()
   message ("     GC performance profiling disabled")
 endif ()
-if (WAMR_BUILD_GC_BINARYEN EQUAL 1)
-  add_definitions (-DWASM_ENABLE_GC_BINARYEN=1)
-  message ("     GC binaryen compatible mode on")
-endif ()
 if (WAMR_BUILD_STRINGREF EQUAL 1)
   message ("     Stringref enabled")
   if (NOT DEFINED WAMR_STRINGREF_IMPL_SOURCE)
@@ -351,9 +347,9 @@ if (WAMR_BUILD_STRINGREF EQUAL 1)
 endif ()
 if (WAMR_BUILD_PERF_PROFILING EQUAL 1 OR
     WAMR_BUILD_DUMP_CALL_STACK EQUAL 1 OR
-    WAMR_BUILD_GC EQUAL 1 OR WAMR_BUILD_GC_BINARYEN EQUAL 1)
-  # Enable AOT/JIT stack frame when perf-profiling, dump-call-stack,
-  # gc or gc-binaryen is enabled
+    WAMR_BUILD_GC EQUAL 1)
+  # Enable AOT/JIT stack frame when perf-profiling, dump-call-stack
+  # or GC is enabled
   if (WAMR_BUILD_AOT EQUAL 1)
     add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
   endif ()

+ 0 - 4
build-scripts/runtime_lib.cmake

@@ -82,10 +82,6 @@ if (WAMR_BUILD_STRINGREF EQUAL 1)
     set (WAMR_BUILD_GC 1)
 endif ()
 
-if (WAMR_BUILD_GC_BINARYEN EQUAL 1)
-    set (WAMR_BUILD_GC 1)
-endif ()
-
 if (WAMR_BUILD_GC EQUAL 1)
     include (${IWASM_DIR}/common/gc/iwasm_gc.cmake)
     # Enable the dependent feature if GC is enabled

+ 6 - 3
core/config.h

@@ -472,9 +472,12 @@
 #define WASM_ENABLE_GC 0
 #endif
 
-/* GC binaryen compatible mode */
-#ifndef WASM_ENABLE_GC_BINARYEN
-#define WASM_ENABLE_GC_BINARYEN 0
+#ifndef WASM_CONST_EXPR_STACK_SIZE
+#if WASM_ENABLE_GC != 0
+#define WASM_CONST_EXPR_STACK_SIZE 8
+#else
+#define WASM_CONST_EXPR_STACK_SIZE 4
+#endif
 #endif
 
 #ifndef WASM_ENABLE_STRINGREF

+ 305 - 32
core/iwasm/aot/aot_loader.c

@@ -1102,6 +1102,18 @@ fail:
     return false;
 }
 
+#if WASM_ENABLE_GC != 0
+static void
+destroy_init_expr(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);
+    }
+}
+#endif /* end of WASM_ENABLE_GC != 0 */
+
 static void
 destroy_import_tables(AOTImportTable *import_tables)
 {
@@ -1119,11 +1131,193 @@ destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
 {
     uint32 i;
     for (i = 0; i < count; i++)
-        if (data_list[i])
+        if (data_list[i]) {
+#if WASM_ENABLE_GC != 0
+            uint32 j;
+            for (j = 0; j < data_list[i]->value_count; j++) {
+                destroy_init_expr(&data_list[i]->init_values[j]);
+            }
+#endif
             wasm_runtime_free(data_list[i]);
+        }
     wasm_runtime_free(data_list);
 }
 
+#if WASM_ENABLE_GC != 0
+static bool
+load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
+               InitializerExpression *expr, char *error_buf,
+               uint32 error_buf_size)
+{
+    const uint8 *buf = *p_buf;
+    uint32 init_expr_type = 0;
+    bool free_if_fail = false;
+
+    buf = (uint8 *)align_ptr(buf, 4);
+
+    read_uint32(buf, buf_end, init_expr_type);
+
+    switch (init_expr_type) {
+        case INIT_EXPR_NONE:
+            break;
+        case INIT_EXPR_TYPE_I32_CONST:
+        case INIT_EXPR_TYPE_F32_CONST:
+            read_uint32(buf, buf_end, expr->u.i32);
+            break;
+        case INIT_EXPR_TYPE_I64_CONST:
+        case INIT_EXPR_TYPE_F64_CONST:
+            read_uint64(buf, buf_end, expr->u.i64);
+            break;
+        case INIT_EXPR_TYPE_V128_CONST:
+            read_byte_array(buf, buf_end, &expr->u.v128, sizeof(expr->u.v128));
+            break;
+        case INIT_EXPR_TYPE_GET_GLOBAL:
+            read_uint32(buf, buf_end, expr->u.global_index);
+            break;
+        case INIT_EXPR_TYPE_REFNULL_CONST:
+            read_uint32(buf, buf_end, expr->u.type_index);
+            break;
+        case INIT_EXPR_TYPE_FUNCREF_CONST:
+            read_uint32(buf, buf_end, expr->u.ref_index);
+            break;
+        case INIT_EXPR_TYPE_I31_NEW:
+            read_uint32(buf, buf_end, expr->u.i32);
+            break;
+        case INIT_EXPR_TYPE_STRUCT_NEW:
+        {
+            uint64 size;
+            uint32 type_idx, field_count;
+            AOTStructType *struct_type = NULL;
+            WASMStructNewInitValues *init_values = NULL;
+
+            read_uint32(buf, buf_end, type_idx);
+            read_uint32(buf, buf_end, field_count);
+
+            size = offsetof(WASMStructNewInitValues, fields)
+                   + sizeof(WASMValue) * (uint64)field_count;
+            if (!(init_values =
+                      loader_malloc(size, error_buf, error_buf_size))) {
+                return false;
+            }
+            free_if_fail = true;
+            expr->u.data = init_values;
+
+            if (type_idx >= module->type_count) {
+                set_error_buf(error_buf, error_buf_size,
+                              "unknown struct type.");
+                goto fail;
+            }
+
+            struct_type = (AOTStructType *)module->types[type_idx];
+
+            if (struct_type->field_count != field_count) {
+                set_error_buf(error_buf, error_buf_size,
+                              "invalid field count.");
+                goto fail;
+            }
+
+            if (field_count > 0) {
+                uint32 i;
+
+                for (i = 0; i < field_count; i++) {
+                    uint32 field_size =
+                        wasm_value_type_size(struct_type->fields[i].field_type);
+                    if (field_size <= sizeof(uint32))
+                        read_uint32(buf, buf_end, init_values->fields[i].u32);
+                    else if (field_size == sizeof(uint64))
+                        read_uint64(buf, buf_end, init_values->fields[i].u64);
+                    else if (field_size == sizeof(uint64) * 2)
+                        read_byte_array(buf, buf_end, &init_values->fields[i],
+                                        field_size);
+                    else {
+                        bh_assert(0);
+                    }
+                }
+            }
+
+            break;
+        }
+        case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
+            read_uint32(buf, buf_end, expr->u.type_index);
+            break;
+        case INIT_EXPR_TYPE_ARRAY_NEW:
+        case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
+        case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
+        {
+            uint32 type_idx, length;
+            AOTArrayType *array_type = NULL;
+            WASMArrayNewInitValues *init_values = NULL;
+
+            read_uint32(buf, buf_end, type_idx);
+            read_uint32(buf, buf_end, length);
+
+            if (type_idx >= module->type_count) {
+                set_error_buf(error_buf, error_buf_size, "unknown array type.");
+                goto fail;
+            }
+
+            array_type = (AOTArrayType *)module->types[type_idx];
+
+            if (init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
+                expr->u.array_new_default.type_index = type_idx;
+                expr->u.array_new_default.N = length;
+            }
+            else {
+
+                uint64 size = offsetof(WASMArrayNewInitValues, elem_data)
+                              + sizeof(WASMValue) * (uint64)length;
+                if (!(init_values =
+                          loader_malloc(size, error_buf, error_buf_size))) {
+                    return false;
+                }
+                free_if_fail = true;
+                expr->u.data = init_values;
+
+                init_values->type_idx = type_idx;
+                init_values->length = length;
+
+                if (length > 0) {
+                    uint32 i;
+                    uint32 elem_size =
+                        wasm_value_type_size(array_type->elem_type);
+
+                    for (i = 0; i < length; i++) {
+
+                        if (elem_size <= sizeof(uint32))
+                            read_uint32(buf, buf_end,
+                                        init_values->elem_data[i].u32);
+                        else if (elem_size == sizeof(uint64))
+                            read_uint64(buf, buf_end,
+                                        init_values->elem_data[i].u64);
+                        else if (elem_size == sizeof(uint64) * 2)
+                            read_byte_array(buf, buf_end,
+                                            &init_values->elem_data[i],
+                                            elem_size);
+                        else {
+                            bh_assert(0);
+                        }
+                    }
+                }
+            }
+            break;
+        }
+        default:
+            set_error_buf(error_buf, error_buf_size, "invalid init expr type.");
+            return false;
+    }
+
+    expr->init_expr_type = (uint8)init_expr_type;
+
+    *p_buf = buf;
+    return true;
+fail:
+    if (free_if_fail) {
+        wasm_runtime_free(expr->u.data);
+    }
+    return false;
+}
+#endif /* end of WASM_ENABLE_GC != 0 */
+
 static bool
 load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
                        AOTModule *module, char *error_buf,
@@ -1222,6 +1416,17 @@ load_table_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
                 return false;
             }
         }
+        if (!load_init_expr(&buf, buf_end, module, &table->init_expr, error_buf,
+                            error_buf_size))
+            return false;
+
+        if (table->init_expr.init_expr_type >= INIT_EXPR_TYPE_STRUCT_NEW
+            && table->init_expr.init_expr_type
+                   <= INIT_EXPR_TYPE_EXTERN_CONVERT_ANY) {
+            set_error_buf(error_buf, error_buf_size,
+                          "unsupported initializer expression for table");
+            return false;
+        }
 #endif
     }
 
@@ -1242,7 +1447,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
     WASMRefType reftype;
 #endif
     uint64 size;
-    uint32 i;
+    uint32 i, j;
 
     /* Allocate memory */
     size = sizeof(AOTTableInitData *) * (uint64)module->table_init_data_count;
@@ -1254,7 +1459,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
     /* Create each table data segment */
     for (i = 0; i < module->table_init_data_count; i++) {
         uint32 mode, elem_type;
-        uint32 table_index, init_expr_type, func_index_count;
+        uint32 table_index, init_expr_type, value_count;
         uint64 init_expr_value, size1;
 
         read_uint32(buf, buf_end, mode);
@@ -1276,10 +1481,10 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
             buf += 8;
         }
 
-        read_uint32(buf, buf_end, func_index_count);
+        read_uint32(buf, buf_end, value_count);
 
-        size1 = sizeof(uintptr_t) * (uint64)func_index_count;
-        size = offsetof(AOTTableInitData, func_indexes) + size1;
+        size1 = sizeof(InitializerExpression) * (uint64)value_count;
+        size = offsetof(AOTTableInitData, init_values) + size1;
         if (!(data_list[i] = loader_malloc(size, error_buf, error_buf_size))) {
             return false;
         }
@@ -1298,9 +1503,23 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
 #endif
         data_list[i]->offset.init_expr_type = (uint8)init_expr_type;
         data_list[i]->offset.u.i64 = (int64)init_expr_value;
-        data_list[i]->func_index_count = func_index_count;
-        read_byte_array(buf, buf_end, data_list[i]->func_indexes,
-                        (uint32)size1);
+        data_list[i]->value_count = value_count;
+        for (j = 0; j < data_list[i]->value_count; j++) {
+#if WASM_ENABLE_GC != 0
+            if (!load_init_expr(&buf, buf_end, module,
+                                &data_list[i]->init_values[j], error_buf,
+                                error_buf_size))
+                return false;
+#else
+            data_list[i]->init_values[j].init_expr_type =
+                INIT_EXPR_TYPE_FUNCREF_CONST;
+#if UINTPTR_MAX == UINT64_MAX
+            read_uint64(buf, buf_end, data_list[i]->init_values[j].u.ref_index);
+#else
+            read_uint32(buf, buf_end, data_list[i]->init_values[j].u.ref_index);
+#endif
+#endif /* end of WASM_ENABLE_GC != 0 */
+        }
     }
 
     *p_buf = buf;
@@ -1370,6 +1589,17 @@ destroy_types(AOTType **types, uint32 count)
 }
 
 #if WASM_ENABLE_GC != 0
+static void
+init_base_type(AOTType *base_type, uint16 type_flag, bool is_sub_final,
+               uint32 parent_type_idx, uint16 rec_count, uint16 rec_idx)
+{
+    base_type->type_flag = type_flag;
+    base_type->is_sub_final = is_sub_final;
+    base_type->parent_type_idx = parent_type_idx;
+    base_type->rec_count = rec_count;
+    base_type->rec_idx = rec_idx;
+}
+
 static bool
 load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
            char *error_buf, uint32 error_buf_size)
@@ -1379,7 +1609,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
     uint64 size;
     uint32 i, j;
     uint32 type_flag, param_cell_num, ret_cell_num;
-    uint16 param_count, result_count, ref_type_map_count;
+    uint16 param_count, result_count, ref_type_map_count, rec_count, rec_idx;
     bool is_sub_final;
     uint32 parent_type_idx;
     WASMRefType ref_type;
@@ -1401,6 +1631,8 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
         read_uint16(buf, buf_end, type_flag);
         read_uint16(buf, buf_end, is_sub_final);
         read_uint32(buf, buf_end, parent_type_idx);
+        read_uint16(buf, buf_end, rec_count);
+        read_uint16(buf, buf_end, rec_idx);
 
         if (type_flag == WASM_TYPE_FUNC) {
             AOTFuncType *func_type;
@@ -1422,9 +1654,8 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
 
             types[i] = (AOTType *)func_type;
 
-            func_type->base_type.type_flag = type_flag;
-            func_type->base_type.is_sub_final = is_sub_final;
-            func_type->base_type.parent_type_idx = parent_type_idx;
+            init_base_type((AOTType *)func_type, type_flag, is_sub_final,
+                           parent_type_idx, rec_count, rec_idx);
             func_type->param_count = param_count;
             func_type->result_count = result_count;
 
@@ -1524,7 +1755,8 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
             offset = (uint32)offsetof(WASMStructObject, field_data);
             types[i] = (AOTType *)struct_type;
 
-            struct_type->base_type.type_flag = type_flag;
+            init_base_type((AOTType *)struct_type, type_flag, is_sub_final,
+                           parent_type_idx, rec_count, rec_idx);
             struct_type->field_count = field_count;
             struct_type->ref_type_map_count = ref_type_map_count;
 
@@ -1609,7 +1841,8 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
 
             types[i] = (AOTType *)array_type;
 
-            array_type->base_type.type_flag = type_flag;
+            init_base_type((AOTType *)array_type, type_flag, is_sub_final,
+                           parent_type_idx, rec_count, rec_idx);
             read_uint16(buf, buf_end, array_type->elem_flags);
             read_uint8(buf, buf_end, array_type->elem_type);
             if (wasm_is_type_multi_byte_type(array_type->elem_type)) {
@@ -1633,23 +1866,40 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
             goto fail;
         }
 
-        if (parent_type_idx != (uint32)-1) { /* has parent */
-            AOTType *parent_type = module->types[parent_type_idx];
-            if (!wasm_type_is_subtype_of(module->types[i], parent_type,
-                                         module->types, i)) {
-                set_error_buf(error_buf, error_buf_size,
-                              "sub type does not match super type");
-                goto fail;
+        if ((rec_count == 0) || (rec_idx == rec_count - 1)) {
+            if (rec_count == 0) {
+                bh_assert(rec_idx == 0);
             }
 
-            module->types[i]->parent_type = parent_type;
-            module->types[i]->root_type = parent_type->root_type;
-            module->types[i]->inherit_depth = parent_type->inherit_depth + 1;
-        }
-        else {
-            module->types[i]->parent_type = NULL;
-            module->types[i]->root_type = module->types[i];
-            module->types[i]->inherit_depth = 0;
+            for (j = i - rec_idx; j <= i; j++) {
+                AOTType *cur_type = module->types[j];
+                parent_type_idx = cur_type->parent_type_idx;
+                if (parent_type_idx != (uint32)-1) { /* has parent */
+                    AOTType *parent_type = module->types[parent_type_idx];
+
+                    module->types[j]->parent_type = parent_type;
+                    module->types[j]->root_type = parent_type->root_type;
+                    module->types[j]->inherit_depth =
+                        parent_type->inherit_depth + 1;
+                }
+                else {
+                    module->types[j]->parent_type = NULL;
+                    module->types[j]->root_type = module->types[j];
+                    module->types[j]->inherit_depth = 0;
+                }
+            }
+
+            for (j = i - rec_idx; j <= i; j++) {
+                AOTType *cur_type = module->types[j];
+                parent_type_idx = cur_type->parent_type_idx;
+                if (parent_type_idx != (uint32)-1) { /* has parent */
+                    AOTType *parent_type = module->types[parent_type_idx];
+                    /* subtyping has been checked during compilation */
+                    bh_assert(wasm_type_is_subtype_of(
+                        module->types[j], parent_type, module->types, i));
+                    (void)parent_type;
+                }
+            }
         }
     }
 
@@ -1869,10 +2119,18 @@ load_globals(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
 
     /* Create each global */
     for (i = 0; i < module->global_count; i++) {
+#if WASM_ENABLE_GC == 0
         uint16 init_expr_type;
+#endif
 
         read_uint8(buf, buf_end, globals[i].type);
         read_uint8(buf, buf_end, globals[i].is_mutable);
+
+#if WASM_ENABLE_GC != 0
+        if (!load_init_expr(&buf, buf_end, module, &globals[i].init_expr,
+                            error_buf, error_buf_size))
+            return false;
+#else
         read_uint16(buf, buf_end, init_expr_type);
 
         if (init_expr_type != INIT_EXPR_TYPE_V128_CONST) {
@@ -1886,6 +2144,7 @@ load_globals(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
         }
 
         globals[i].init_expr.init_expr_type = (uint8)init_expr_type;
+#endif /* end of WASM_ENABLE_GC != 0 */
 
         globals[i].size = wasm_value_type_size(globals[i].type);
         globals[i].data_offset = data_offset;
@@ -3842,8 +4101,15 @@ aot_unload(AOTModule *module)
     if (module->import_tables)
         destroy_import_tables(module->import_tables);
 
-    if (module->tables)
+    if (module->tables) {
+#if WASM_ENABLE_GC != 0
+        uint32 i;
+        for (i = 0; i < module->table_count; i++) {
+            destroy_init_expr(&module->tables[i].init_expr);
+        }
+#endif
         destroy_tables(module->tables);
+    }
 
     if (module->table_init_data_list)
         destroy_table_init_data_list(module->table_init_data_list,
@@ -3855,8 +4121,15 @@ aot_unload(AOTModule *module)
     if (module->import_globals)
         destroy_import_globals(module->import_globals);
 
-    if (module->globals)
+    if (module->globals) {
+#if WASM_ENABLE_GC != 0
+        uint32 i;
+        for (i = 0; i < module->global_count; i++) {
+            destroy_init_expr(&module->globals[i].init_expr);
+        }
+#endif
         destroy_globals(module->globals);
+    }
 
     if (module->import_funcs)
         destroy_import_funcs(module->import_funcs);

+ 361 - 44
core/iwasm/aot/aot_runtime.c

@@ -157,10 +157,205 @@ init_global_data(uint8 *global_data, uint8 type, WASMValue *initial_value)
             break;
 #endif
         default:
+#if WASM_ENABLE_GC != 0
+            if ((type >= (uint8)REF_TYPE_ARRAYREF
+                 && type <= (uint8)REF_TYPE_NULLFUNCREF)
+                || (type >= (uint8)REF_TYPE_HT_NULLABLE
+                    && type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
+#if WASM_ENABLE_STRINGREF != 0
+                || (type >= (uint8)REF_TYPE_STRINGVIEWWTF8
+                    && type <= (uint8)REF_TYPE_STRINGREF)
+                || (type >= (uint8)REF_TYPE_STRINGVIEWITER
+                    && type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
+#endif
+            ) {
+                bh_memcpy_s(global_data, sizeof(wasm_obj_t),
+                            &initial_value->gc_obj, sizeof(wasm_obj_t));
+                break;
+            }
+#endif /* end of WASM_ENABLE_GC */
             bh_assert(0);
     }
 }
 
+#if WASM_ENABLE_GC != 0
+static bool
+assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
+                        InitializerExpression *init_expr, void *addr,
+                        char *error_buf, uint32 error_buf_size)
+{
+    uint8 flag = init_expr->init_expr_type;
+
+    bh_assert(flag >= INIT_EXPR_TYPE_GET_GLOBAL
+              && flag <= INIT_EXPR_TYPE_EXTERN_CONVERT_ANY);
+
+    switch (flag) {
+        case INIT_EXPR_TYPE_GET_GLOBAL:
+        {
+            if (!check_global_init_expr(module, init_expr->u.global_index,
+                                        error_buf, error_buf_size)) {
+                return false;
+            }
+            if (init_expr->u.global_index < module->import_global_count) {
+                PUT_REF_TO_ADDR(
+                    addr, module->import_globals[init_expr->u.global_index]
+                              .global_data_linked.gc_obj);
+            }
+            else {
+                uint32 global_idx =
+                    init_expr->u.global_index - module->import_global_count;
+                return assign_table_init_value(
+                    module_inst, module, &module->globals[global_idx].init_expr,
+                    addr, error_buf, error_buf_size);
+            }
+            break;
+        }
+        case INIT_EXPR_TYPE_REFNULL_CONST:
+        {
+            WASMObjectRef gc_obj = NULL_REF;
+            PUT_REF_TO_ADDR(addr, gc_obj);
+            break;
+        }
+        case INIT_EXPR_TYPE_FUNCREF_CONST:
+        {
+            WASMFuncObjectRef func_obj = NULL;
+            uint32 func_idx = init_expr->u.u32;
+
+            if (func_idx != UINT32_MAX) {
+                if (!(func_obj =
+                          aot_create_func_obj(module_inst, func_idx, false,
+                                              error_buf, error_buf_size))) {
+                    return false;
+                }
+            }
+
+            PUT_REF_TO_ADDR(addr, func_obj);
+            break;
+        }
+        case INIT_EXPR_TYPE_I31_NEW:
+        {
+            WASMI31ObjectRef i31_obj = wasm_i31_obj_new(init_expr->u.i32);
+            PUT_REF_TO_ADDR(addr, i31_obj);
+            break;
+        }
+        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;
+
+            if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
+                init_values = (WASMStructNewInitValues *)init_expr->u.data;
+                type_idx = init_values->type_idx;
+            }
+            else {
+                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");
+                return false;
+            }
+
+            if (!(struct_obj = wasm_struct_obj_new_internal(
+                      ((AOTModuleInstanceExtra *)module_inst->e)
+                          ->common.gc_heap_handle,
+                      rtt_type))) {
+                set_error_buf(error_buf, error_buf_size,
+                              "create struct object failed");
+                return false;
+            }
+
+            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]);
+                }
+            }
+
+            PUT_REF_TO_ADDR(addr, struct_obj);
+            break;
+        }
+        case INIT_EXPR_TYPE_ARRAY_NEW:
+        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 };
+            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.N;
+                arr_init_val = &empty_val;
+            }
+            else {
+                init_values = (WASMArrayNewInitValues *)init_expr->u.data;
+                type_idx = init_values->type_idx;
+                len = init_values->length;
+
+                if (flag == INIT_EXPR_TYPE_ARRAY_NEW) {
+                    arr_init_val = 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");
+                return false;
+            }
+
+            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");
+                return false;
+            }
+
+            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]);
+                }
+            }
+
+            PUT_REF_TO_ADDR(addr, array_obj);
+            break;
+        }
+        default:
+            set_error_buf(error_buf, error_buf_size, "invalid init expr type.");
+            return false;
+    }
+
+    return true;
+}
+#endif /* end of WASM_ENABLE_GC != 0 */
+
 static bool
 global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                    char *error_buf, uint32 error_buf_size)
@@ -182,10 +377,12 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 
     /* Initialize defined global data */
     for (i = 0; i < module->global_count; i++, global++) {
+        uint8 flag;
         bh_assert(global->data_offset
                   == (uint32)(p - module_inst->global_data));
         init_expr = &global->init_expr;
-        switch (init_expr->init_expr_type) {
+        flag = init_expr->init_expr_type;
+        switch (flag) {
             case INIT_EXPR_TYPE_GET_GLOBAL:
             {
                 if (!check_global_init_expr(module, init_expr->u.global_index,
@@ -250,12 +447,22 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                 PUT_REF_TO_ADDR(p, i31_obj);
                 break;
             }
-            case INIT_EXPR_TYPE_STRUCT_NEW_CANON_DEFAULT:
+            case INIT_EXPR_TYPE_STRUCT_NEW:
+            case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
             {
                 WASMRttType *rtt_type;
                 WASMStructObjectRef struct_obj;
                 WASMStructType *struct_type;
-                uint32 type_idx = init_expr->u.i32;
+                WASMStructNewInitValues *init_values = NULL;
+                uint32 type_idx;
+
+                if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
+                    init_values = (WASMStructNewInitValues *)init_expr->u.data;
+                    type_idx = init_values->type_idx;
+                }
+                else {
+                    type_idx = init_expr->u.type_index;
+                }
 
                 struct_type = (WASMStructType *)module->types[type_idx];
 
@@ -276,9 +483,81 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                     return false;
                 }
 
+                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]);
+                    }
+                }
+
                 PUT_REF_TO_ADDR(p, struct_obj);
                 break;
             }
+            case INIT_EXPR_TYPE_ARRAY_NEW:
+            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 };
+                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.N;
+                    arr_init_val = &empty_val;
+                }
+                else {
+                    init_values = (WASMArrayNewInitValues *)init_expr->u.data;
+                    type_idx = init_values->type_idx;
+                    len = init_values->length;
+
+                    if (flag == INIT_EXPR_TYPE_ARRAY_NEW) {
+                        arr_init_val = 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");
+                    return false;
+                }
+
+                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");
+                    return false;
+                }
+
+                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]);
+                    }
+                }
+
+                PUT_REF_TO_ADDR(p, array_obj);
+                break;
+            }
 #endif /* end of WASM_ENABLE_GC != 0 */
             default:
             {
@@ -357,6 +636,9 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 
     /* 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];
 
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
@@ -413,20 +695,20 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                           "out of bounds table access");
 #else
             set_error_buf(error_buf, error_buf_size,
-                          "elements segment does not fit");
+                          "type mismatch: elements segment does not fit");
 #endif
             return false;
         }
 
         /* base_offset + length(could be zero) */
-        length = table_seg->func_index_count;
+        length = table_seg->value_count;
         if (base_offset + length > tbl_inst->cur_size) {
 #if WASM_ENABLE_REF_TYPES != 0
             set_error_buf(error_buf, error_buf_size,
                           "out of bounds table access");
 #else
             set_error_buf(error_buf, error_buf_size,
-                          "elements segment does not fit");
+                          "type mismatch: elements segment does not fit");
 #endif
             return false;
         }
@@ -436,10 +718,10 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
          * will check the linked table inst owner in future
          */
 #if WASM_ENABLE_GC == 0
-        bh_memcpy_s(
-            tbl_inst->elems + base_offset,
-            (tbl_inst->max_size - base_offset) * sizeof(table_elem_type_t),
-            table_seg->func_indexes, length * sizeof(table_elem_type_t));
+        for (j = 0; j < length; j++) {
+            tbl_inst->elems[base_offset + j] =
+                table_seg->init_values[j].u.ref_index;
+        }
 #endif
     }
 
@@ -1409,6 +1691,34 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
 #endif
 
 #if WASM_ENABLE_GC != 0
+    for (i = 0; i < module_inst->table_count; i++) {
+        uint32 j;
+        AOTTable *table;
+        AOTTableInstance *table_inst;
+        table_elem_type_t *table_data;
+
+        table = &module->tables[i];
+        bh_assert(table);
+
+        if (table->init_expr.init_expr_type == INIT_EXPR_NONE) {
+            continue;
+        }
+
+        table_inst = module_inst->tables[i];
+        bh_assert(table_inst);
+
+        table_data = table_inst->elems;
+        bh_assert(table_data);
+
+        for (j = 0; j < table_inst->cur_size; j++) {
+            if (!assign_table_init_value(module_inst, module, &table->init_expr,
+                                         table_data + j, error_buf,
+                                         error_buf_size)) {
+                goto fail;
+            }
+        }
+    }
+
     /* Initialize the table data with table init data */
     for (i = 0;
          module_inst->table_count > 0 && i < module->table_init_data_count;
@@ -1439,7 +1749,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
                 table->elem_type, table->elem_ref_type.elem_ref_type,
                 module->types, module->type_count)) {
             set_error_buf(error_buf, error_buf_size,
-                          "elements segment does not fit");
+                          "type mismatch: elements segment does not fit");
             goto fail;
         }
 
@@ -1462,11 +1772,30 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         /* init vec(funcidx) or vec(expr) */
         if (table_init_data->offset.init_expr_type
             == INIT_EXPR_TYPE_GET_GLOBAL) {
+            uint32 data_offset;
             if (!check_global_init_expr(module,
                                         table_init_data->offset.u.global_index,
                                         error_buf, error_buf_size)) {
                 goto fail;
             }
+
+            if (table_init_data->offset.u.global_index
+                < module->import_global_count) {
+                data_offset =
+                    module
+                        ->import_globals[table_init_data->offset.u.global_index]
+                        .data_offset;
+            }
+            else {
+                data_offset =
+                    module
+                        ->globals[table_init_data->offset.u.global_index
+                                  - module->import_global_count]
+                        .data_offset;
+            }
+
+            table_init_data->offset.u.i32 =
+                *(uint32 *)(module_inst->global_data + data_offset);
         }
 
         /* check offset since length might negative */
@@ -1478,31 +1807,22 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
             goto fail;
         }
 
-        if ((uint32)table_init_data->offset.u.i32
-                + table_init_data->func_index_count
+        if ((uint32)table_init_data->offset.u.i32 + table_init_data->value_count
             > table->cur_size) {
             LOG_DEBUG("base_offset(%d) + length(%d) > table->cur_size(%d)",
                       table_init_data->offset.u.i32,
-                      table_init_data->func_index_count, table->cur_size);
+                      table_init_data->value_count, table->cur_size);
             set_error_buf(error_buf, error_buf_size,
                           "out of bounds table access");
             goto fail;
         }
 
-        for (j = 0; j < module->table_init_data_list[i]->func_index_count;
-             j++) {
-            WASMFuncObjectRef func_obj;
-            uint32 func_idx = table_init_data->func_indexes[j];
-            if (func_idx != UINT32_MAX) {
-                if (!(func_obj =
-                          aot_create_func_obj(module_inst, func_idx, false,
-                                              error_buf, error_buf_size))) {
-                    goto fail;
-                }
-                *(table_data + table_init_data->offset.u.i32 + j) = func_obj;
-            }
-            else {
-                *(table_data + table_init_data->offset.u.i32 + j) = NULL_REF;
+        for (j = 0; j < module->table_init_data_list[i]->value_count; j++) {
+            if (!assign_table_init_value(
+                    module_inst, module, &table_init_data->init_values[j],
+                    table_data + table_init_data->offset.u.i32 + j, error_buf,
+                    error_buf_size)) {
+                goto fail;
             }
         }
     }
@@ -2810,8 +3130,8 @@ aot_get_module_mem_consumption(const AOTModule *module,
         sizeof(AOTTableInitData *) * module->table_init_data_count;
     for (i = 0; i < module->table_init_data_count; i++) {
         AOTTableInitData *init_data = module->table_init_data_list[i];
-        size = offsetof(AOTTableInitData, func_indexes)
-               + sizeof(uint32) * init_data->func_index_count;
+        size = offsetof(AOTTableInitData, init_values)
+               + sizeof(InitializerExpression) * init_data->value_count;
         mem_conspn->table_segs_size += size;
     }
 
@@ -2925,11 +3245,11 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
     AOTTableInstance *tbl_inst;
     AOTTableInitData *tbl_seg;
     const AOTModule *module = (AOTModule *)module_inst->module;
-#if WASM_ENABLE_GC != 0
     table_elem_type_t *table_elems;
-    uintptr_t *func_indexes;
-    void *func_obj;
+    InitializerExpression *init_values;
     uint32 i;
+#if WASM_ENABLE_GC != 0
+    void *func_obj;
 #endif
 
     tbl_inst = module_inst->tables[tbl_idx];
@@ -2938,7 +3258,7 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
     tbl_seg = module->table_init_data_list[tbl_seg_idx];
     bh_assert(tbl_seg);
 
-    if (offset_len_out_of_bounds(src_offset, length, tbl_seg->func_index_count)
+    if (offset_len_out_of_bounds(src_offset, length, tbl_seg->value_count)
         || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
         aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
         return;
@@ -2960,14 +3280,15 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
         return;
     }
 
-#if WASM_ENABLE_GC != 0
     table_elems = tbl_inst->elems + dst_offset;
-    func_indexes = tbl_seg->func_indexes + src_offset;
+    init_values = tbl_seg->init_values + src_offset;
 
     for (i = 0; i < length; i++) {
+#if WASM_ENABLE_GC != 0
         /* UINT32_MAX indicates that it is a null ref */
-        if (func_indexes[i] != UINT32_MAX) {
-            if (!(func_obj = aot_create_func_obj(module_inst, func_indexes[i],
+        if (init_values[i].u.ref_index != UINT32_MAX) {
+            if (!(func_obj = aot_create_func_obj(module_inst,
+                                                 init_values[i].u.ref_index,
                                                  true, NULL, 0))) {
                 aot_set_exception_with_id(module_inst, EXCE_NULL_FUNC_OBJ);
                 return;
@@ -2977,14 +3298,10 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
         else {
             table_elems[i] = NULL_REF;
         }
-    }
 #else
-    bh_memcpy_s((uint8 *)tbl_inst + offsetof(AOTTableInstance, elems)
-                    + dst_offset * sizeof(table_elem_type_t),
-                (tbl_inst->cur_size - dst_offset) * sizeof(table_elem_type_t),
-                tbl_seg->func_indexes + src_offset,
-                length * sizeof(table_elem_type_t));
+        table_elems[i] = init_values[i].u.ref_index;
 #endif
+    }
 }
 
 void

+ 12 - 21
core/iwasm/common/gc/gc_common.c

@@ -19,25 +19,22 @@ wasm_ref_type_normalize(wasm_ref_type_t *ref_type)
     int32 heap_type = ref_type->heap_type;
 
     if (!((value_type >= VALUE_TYPE_I16 && value_type <= VALUE_TYPE_I32)
-          || (
+          || ((value_type >= (uint8)REF_TYPE_ARRAYREF
+               && value_type <= (uint8)REF_TYPE_NULLFUNCREF)
+              || (value_type >= (uint8)REF_TYPE_HT_NULLABLE
+                  && value_type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
 #if WASM_ENABLE_STRINGREF != 0
-              value_type >= VALUE_TYPE_STRINGVIEWITER
-#else
-              value_type >= VALUE_TYPE_NULLREF
+              || (value_type >= (uint8)REF_TYPE_STRINGVIEWWTF8
+                  && value_type <= (uint8)REF_TYPE_STRINGREF)
+              || (value_type >= (uint8)REF_TYPE_STRINGVIEWITER
+                  && value_type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
 #endif
-              && value_type <= VALUE_TYPE_FUNCREF))) {
+                  ))) {
         return false;
     }
     if (value_type == VALUE_TYPE_HT_NULLABLE_REF
         || value_type == VALUE_TYPE_HT_NON_NULLABLE_REF) {
-        if (heap_type < 0
-#if WASM_ENABLE_STRINGREF != 0
-            && (heap_type < HEAP_TYPE_STRINGVIEWITER
-                || heap_type > HEAP_TYPE_FUNC)
-#else
-            && (heap_type < HEAP_TYPE_NONE || heap_type > HEAP_TYPE_FUNC)
-#endif
-        ) {
+        if (heap_type < 0 && !wasm_is_valid_heap_type(heap_type)) {
             return false;
         }
     }
@@ -46,19 +43,13 @@ wasm_ref_type_normalize(wasm_ref_type_t *ref_type)
         ref_type->nullable = false;
     }
     else {
-        if (
-#if WASM_ENABLE_STRINGREF != 0
-            heap_type >= HEAP_TYPE_STRINGVIEWITER && heap_type <= HEAP_TYPE_FUNC
-#else
-            heap_type >= HEAP_TYPE_NONE && heap_type <= HEAP_TYPE_FUNC
-#endif
-        ) {
+        if (wasm_is_valid_heap_type(heap_type)) {
             ref_type->value_type =
 #if WASM_ENABLE_STRINGREF != 0
                 (uint8)(REF_TYPE_STRINGVIEWITER + heap_type
                         - HEAP_TYPE_STRINGVIEWITER);
 #else
-                (uint8)(REF_TYPE_NULLREF + heap_type - HEAP_TYPE_NONE);
+                (uint8)(REF_TYPE_ARRAYREF + heap_type - HEAP_TYPE_ARRAY);
 #endif
             ref_type->nullable = false;
             ref_type->heap_type = 0;

+ 64 - 24
core/iwasm/common/gc/gc_object.c

@@ -180,9 +180,9 @@ wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj,
     }
     else if (field_size == 2) {
         if (sign_extend)
-            value->i32 = (int32)(*(int8 *)field_data);
+            value->i32 = (int32)(*(int16 *)field_data);
         else
-            value->u32 = (uint32)(*(uint8 *)field_data);
+            value->u32 = (uint32)(*(uint16 *)field_data);
     }
     else {
         bh_assert(0);
@@ -190,10 +190,9 @@ wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj,
 }
 
 WASMArrayObjectRef
-wasm_array_obj_new(WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
-                   uint32 length, WASMValue *init_value)
+wasm_array_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type,
+                            uint32 length, WASMValue *init_value)
 {
-    void *heap_handle = get_gc_heap_handle(exec_env);
     WASMArrayObjectRef array_obj;
     WASMArrayType *array_type;
     uint64 total_size;
@@ -226,31 +225,43 @@ wasm_array_obj_new(WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
 
     array_obj->header = (WASMObjectHeader)rtt_type;
     array_obj->length = (length << 2) | elem_size_log;
-    for (i = 0; i < length; i++) {
-        if (wasm_is_type_reftype(array_type->elem_type)) {
-            uint32 *elem_addr =
-                (uint32 *)array_obj->elem_data + REF_CELL_NUM * i;
-            PUT_REF_TO_ADDR(elem_addr, init_value->gc_obj);
-        }
-        else if (array_type->elem_type == VALUE_TYPE_I32
-                 || array_type->elem_type == VALUE_TYPE_F32) {
-            ((int32 *)array_obj->elem_data)[i] = init_value->i32;
-        }
-        else if (array_type->elem_type == PACKED_TYPE_I8) {
-            ((int8 *)array_obj->elem_data)[i] = (int8)init_value->i32;
-        }
-        else if (array_type->elem_type == PACKED_TYPE_I16) {
-            ((int16 *)array_obj->elem_data)[i] = (int16)init_value->i32;
-        }
-        else {
-            uint32 *elem_addr = (uint32 *)array_obj->elem_data + 2 * i;
-            PUT_I64_TO_ADDR(elem_addr, init_value->i64);
+
+    if (init_value != NULL) {
+        for (i = 0; i < length; i++) {
+            if (wasm_is_type_reftype(array_type->elem_type)) {
+                uint32 *elem_addr =
+                    (uint32 *)array_obj->elem_data + REF_CELL_NUM * i;
+                PUT_REF_TO_ADDR(elem_addr, init_value->gc_obj);
+            }
+            else if (array_type->elem_type == VALUE_TYPE_I32
+                     || array_type->elem_type == VALUE_TYPE_F32) {
+                ((int32 *)array_obj->elem_data)[i] = init_value->i32;
+            }
+            else if (array_type->elem_type == PACKED_TYPE_I8) {
+                ((int8 *)array_obj->elem_data)[i] = (int8)init_value->i32;
+            }
+            else if (array_type->elem_type == PACKED_TYPE_I16) {
+                ((int16 *)array_obj->elem_data)[i] = (int16)init_value->i32;
+            }
+            else {
+                uint32 *elem_addr = (uint32 *)array_obj->elem_data + 2 * i;
+                PUT_I64_TO_ADDR(elem_addr, init_value->i64);
+            }
         }
     }
 
     return array_obj;
 }
 
+WASMArrayObjectRef
+wasm_array_obj_new(WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
+                   uint32 length, WASMValue *init_value)
+{
+    void *heap_handle = get_gc_heap_handle(exec_env);
+    return wasm_array_obj_new_internal(heap_handle, rtt_type, length,
+                                       init_value);
+}
+
 void
 wasm_array_obj_set_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
                         const WASMValue *value)
@@ -299,6 +310,35 @@ wasm_array_obj_get_elem(const WASMArrayObjectRef array_obj, uint32 elem_idx,
     }
 }
 
+void
+wasm_array_obj_fill(const WASMArrayObjectRef array_obj, uint32 elem_idx,
+                    uint32 len, WASMValue *value)
+{
+    uint32 i;
+    uint8 *elem_data = wasm_array_obj_elem_addr(array_obj, elem_idx);
+    uint32 elem_size = 1 << wasm_array_obj_elem_size_log(array_obj);
+
+    if (elem_size == 1) {
+        memset(elem_data, (int8)value->i32, len);
+        return;
+    }
+
+    for (i = 0; i < len; i++) {
+        switch (elem_size) {
+            case 2:
+                *(int16 *)elem_data = (int16)value->i32;
+                break;
+            case 4:
+                *(int32 *)elem_data = value->i32;
+                break;
+            case 8:
+                PUT_I64_TO_ADDR((uint32 *)elem_data, value->i64);
+                break;
+        }
+        elem_data += elem_size;
+    }
+}
+
 void
 wasm_array_obj_copy(WASMArrayObjectRef dst_obj, uint32 dst_idx,
                     WASMArrayObjectRef src_obj, uint32 src_idx, uint32 len)

+ 8 - 0
core/iwasm/common/gc/gc_object.h

@@ -157,6 +157,10 @@ void
 wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj,
                           uint32 field_idx, bool sign_extend, WASMValue *value);
 
+WASMArrayObjectRef
+wasm_array_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type,
+                            uint32 length, WASMValue *init_value);
+
 WASMArrayObjectRef
 wasm_array_obj_new(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
                    uint32 length, WASMValue *init_value);
@@ -169,6 +173,10 @@ void
 wasm_array_obj_get_elem(const WASMArrayObjectRef array_obj, uint32 elem_idx,
                         bool sign_extend, WASMValue *value);
 
+void
+wasm_array_obj_fill(const WASMArrayObjectRef array_obj, uint32 elem_idx,
+                    uint32 len, WASMValue *value);
+
 void
 wasm_array_obj_copy(WASMArrayObjectRef dst_obj, uint32 dst_idx,
                     WASMArrayObjectRef src_obj, uint32 src_idx, uint32 len);

+ 9 - 4
core/iwasm/common/gc/gc_type.c

@@ -616,12 +616,17 @@ wasm_reftype_size(uint8 type)
         return 4;
     else if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)
         return 8;
+    else if ((type >= (uint8)REF_TYPE_ARRAYREF
+              && type <= (uint8)REF_TYPE_NULLFUNCREF)
+             || (type >= (uint8)REF_TYPE_HT_NULLABLE
+                 && type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
 #if WASM_ENABLE_STRINGREF != 0
-    else if (type >= (uint8)REF_TYPE_STRINGVIEWITER
-             && type <= (uint8)REF_TYPE_FUNCREF)
-#else
-    else if (type >= (uint8)REF_TYPE_NULLREF && type <= (uint8)REF_TYPE_FUNCREF)
+             || (type >= (uint8)REF_TYPE_STRINGVIEWWTF8
+                 && type <= (uint8)REF_TYPE_STRINGREF)
+             || (type >= (uint8)REF_TYPE_STRINGVIEWITER
+                 && type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
 #endif
+    )
         return sizeof(uintptr_t);
     else if (type == PACKED_TYPE_I8)
         return 1;

+ 27 - 10
core/iwasm/common/gc/gc_type.h

@@ -120,13 +120,33 @@ wasm_type_is_subtype_of(const WASMType *type1, const WASMType *type2,
 inline static bool
 wasm_is_type_reftype(uint8 type)
 {
-    return (
+    return ((type >= (uint8)REF_TYPE_ARRAYREF
+             && type <= (uint8)REF_TYPE_NULLFUNCREF)
+            || (type >= (uint8)REF_TYPE_HT_NULLABLE
+                && type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
 #if WASM_ENABLE_STRINGREF != 0
-               type >= (uint8)REF_TYPE_STRINGVIEWITER
-#else
-               type >= (uint8)REF_TYPE_NULLREF
+            || (type >= (uint8)REF_TYPE_STRINGVIEWWTF8
+                && type <= (uint8)REF_TYPE_STRINGREF)
+            || (type >= (uint8)REF_TYPE_STRINGVIEWITER
+                && type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
 #endif
-               && type <= (uint8)REF_TYPE_FUNCREF)
+                )
+               ? true
+               : false;
+}
+
+/* Whether a negative value is a valid heap type */
+inline static bool
+wasm_is_valid_heap_type(int32 heap_type)
+{
+    return ((heap_type <= HEAP_TYPE_NOFUNC && heap_type >= HEAP_TYPE_ARRAY)
+#if WASM_ENABLE_STRINGREF != 0
+            || heap_type == HEAP_TYPE_STRINGREF
+            || heap_type == HEAP_TYPE_STRINGVIEWWTF8
+            || heap_type == HEAP_TYPE_STRINGVIEWWTF16
+            || heap_type == HEAP_TYPE_STRINGVIEWITER
+#endif
+            )
                ? true
                : false;
 }
@@ -248,14 +268,11 @@ wasm_is_refheaptype_typeidx(const RefHeapType_Common *ref_heap_type)
 inline static bool
 wasm_is_refheaptype_common(const RefHeapType_Common *ref_heap_type)
 {
-    return ((ref_heap_type->heap_type >= (int32)HEAP_TYPE_EQ
-             && ref_heap_type->heap_type <= (int32)HEAP_TYPE_FUNC)
+    return ((ref_heap_type->heap_type >= (int32)HEAP_TYPE_ARRAY
+             && ref_heap_type->heap_type <= (int32)HEAP_TYPE_NONE)
 #if WASM_ENABLE_STRINGREF != 0
             || (ref_heap_type->heap_type >= (int32)HEAP_TYPE_STRINGVIEWITER
                 && ref_heap_type->heap_type <= (int32)HEAP_TYPE_I31)
-#else
-            || (ref_heap_type->heap_type >= (int32)HEAP_TYPE_NONE
-                && ref_heap_type->heap_type <= (int32)HEAP_TYPE_I31)
 #endif
                 )
                ? true

+ 39 - 4
core/iwasm/common/wasm_application.c

@@ -548,6 +548,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
             {
 #if WASM_ENABLE_GC != 0
                 bool is_extern_ref = false;
+                bool is_anyref = false;
 
                 if (wasm_is_type_reftype(type->types[i])) {
                     if (strncasecmp(argv[i], "null", 4) == 0) {
@@ -558,15 +559,24 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
                     else if (type->types[i] == VALUE_TYPE_EXTERNREF) {
                         is_extern_ref = true;
                     }
+                    else if (type->types[i] == VALUE_TYPE_ANYREF) {
+                        is_anyref = true;
+                    }
 
                     if (wasm_is_type_multi_byte_type(
                             type->types[type->param_count + i])) {
                         WASMRefType *ref_type = ref_type_map->ref_type;
-                        if (wasm_is_refheaptype_common(&ref_type->ref_ht_common)
-                            && ref_type->ref_ht_common.heap_type
-                                   == HEAP_TYPE_EXTERN) {
-                            is_extern_ref = true;
+                        if (wasm_is_refheaptype_common(
+                                &ref_type->ref_ht_common)) {
+                            int32 heap_type = ref_type->ref_ht_common.heap_type;
+                            if (heap_type == HEAP_TYPE_EXTERN) {
+                                is_extern_ref = true;
+                            }
+                            else if (heap_type == HEAP_TYPE_ANY) {
+                                is_anyref = true;
+                            }
                         }
+
                         ref_type_map++;
                     }
 
@@ -591,6 +601,29 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
                         PUT_REF_TO_ADDR(argv1 + p, gc_obj);
                         p += REF_CELL_NUM;
                     }
+                    else if (is_anyref) {
+                        /* If a parameter type is (ref null? any) and its value
+                         * is not null, then we treat the value as host ptr */
+                        WASMAnyrefObjectRef gc_obj;
+                        void *host_obj =
+                            (void *)(uintptr_t)strtoull(argv[i], &endptr, 0);
+                        gc_obj = wasm_anyref_obj_new(exec_env, host_obj);
+                        if (!gc_obj) {
+                            wasm_runtime_set_exception(
+                                module_inst, "create anyref object failed");
+                            goto fail;
+                        }
+                        if (!(local_ref =
+                                  runtime_malloc(sizeof(WASMLocalObjectRef),
+                                                 module_inst, NULL, 0))) {
+                            goto fail;
+                        }
+                        wasm_runtime_push_local_object_ref(exec_env, local_ref);
+                        local_ref->val = (WASMObjectRef)gc_obj;
+                        num_local_ref_pushed++;
+                        PUT_REF_TO_ADDR(argv1 + p, gc_obj);
+                        p += REF_CELL_NUM;
+                    }
 
                     break;
                 }
@@ -765,6 +798,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
                     }
 #endif
                     else if (wasm_obj_is_externref_obj(gc_obj)) {
+#if WASM_ENABLE_SPEC == 0
                         WASMObjectRef obj = wasm_externref_obj_to_internal_obj(
                             (WASMExternrefObjectRef)gc_obj);
                         if (wasm_obj_is_anyref_obj(obj))
@@ -772,6 +806,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
                                       (uintptr_t)wasm_anyref_obj_get_value(
                                           (WASMAnyrefObjectRef)obj));
                         else
+#endif
                             os_printf("ref.extern");
                     }
                     else if (wasm_obj_is_i31_obj(gc_obj))

+ 2 - 2
core/iwasm/common/wasm_runtime_common.c

@@ -2500,7 +2500,7 @@ static const char *exception_msgs[] = {
     /* GC related exceptions */
     "null function object",           /* EXCE_NULL_FUNC_OBJ */
     "null structure object",          /* EXCE_NULL_STRUCT_OBJ */
-    "null array object",              /* EXCE_NULL_ARRAY_OBJ */
+    "null array reference",              /* EXCE_NULL_ARRAY_OBJ */
     "null i31 reference",             /* EXCE_NULL_I31_OBJ */
     "null reference",                 /* EXCE_NULL_REFERENCE */
     "create rtt type failed",         /* EXCE_FAILED_TO_CREATE_RTT_TYPE */
@@ -2508,7 +2508,7 @@ static const char *exception_msgs[] = {
     "create array object failed",     /* EXCE_FAILED_TO_CREATE_ARRAY_OBJ */
     "create externref object failed", /* EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ */
     "cast failure",                   /* EXCE_CAST_FAILURE */
-    "array index out of bounds",      /* EXCE_ARRAY_IDX_OOB */
+    "out of bounds array access",      /* EXCE_ARRAY_IDX_OOB */
     /* stringref related exceptions */
     "create string object failed",    /* EXCE_FAILED_TO_CREATE_STRING */
     "create stringref failed",        /* EXCE_FAILED_TO_CREATE_STRINGREF */

+ 27 - 17
core/iwasm/compilation/aot.c

@@ -114,9 +114,9 @@ aot_create_table_init_data_list(const WASMModule *module)
 
     /* Create each table data segment */
     for (i = 0; i < module->table_seg_count; i++) {
-        size = offsetof(AOTTableInitData, func_indexes)
-               + sizeof(uintptr_t)
-                     * (uint64)module->table_segments[i].function_count;
+        size = offsetof(AOTTableInitData, init_values)
+               + sizeof(InitializerExpression)
+                     * (uint64)module->table_segments[i].value_count;
         if (size >= UINT32_MAX
             || !(data_list[i] = wasm_runtime_malloc((uint32)size))) {
             aot_set_last_error("allocate memory failed.");
@@ -124,8 +124,7 @@ aot_create_table_init_data_list(const WASMModule *module)
         }
 
         data_list[i]->offset = module->table_segments[i].base_offset;
-        data_list[i]->func_index_count =
-            module->table_segments[i].function_count;
+        data_list[i]->value_count = module->table_segments[i].value_count;
         data_list[i]->mode = module->table_segments[i].mode;
         data_list[i]->elem_type = module->table_segments[i].elem_type;
         /* runtime control it */
@@ -133,16 +132,16 @@ aot_create_table_init_data_list(const WASMModule *module)
         bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr),
                     &module->table_segments[i].base_offset,
                     sizeof(AOTInitExpr));
-        data_list[i]->func_index_count =
-            module->table_segments[i].function_count;
+        data_list[i]->value_count = module->table_segments[i].value_count;
 #if WASM_ENABLE_GC != 0
         data_list[i]->elem_ref_type = module->table_segments[i].elem_ref_type;
 #endif
-        bh_memcpy_s(
-            data_list[i]->func_indexes,
-            sizeof(uintptr_t) * module->table_segments[i].function_count,
-            module->table_segments[i].func_indexes,
-            sizeof(uintptr_t) * module->table_segments[i].function_count);
+        bh_memcpy_s(data_list[i]->init_values,
+                    sizeof(InitializerExpression)
+                        * module->table_segments[i].value_count,
+                    module->table_segments[i].init_values,
+                    sizeof(InitializerExpression)
+                        * module->table_segments[i].value_count);
     }
 
     return data_list;
@@ -168,13 +167,18 @@ get_value_type_size(uint8 value_type, bool gc_enabled, uint32 *p_size_64bit,
              && (value_type == VALUE_TYPE_FUNCREF
                  || value_type == VALUE_TYPE_EXTERNREF))
         size_64bit = size_32bit = sizeof(int32);
-    else if (gc_enabled &&
+    else if (gc_enabled
+             && ((value_type >= (uint8)REF_TYPE_ARRAYREF
+                  && value_type <= (uint8)REF_TYPE_NULLFUNCREF)
+                 || (value_type >= (uint8)REF_TYPE_HT_NULLABLE
+                     && value_type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
 #if WASM_ENABLE_STRINGREF != 0
-             value_type >= (uint8)REF_TYPE_STRINGVIEWITER /* 0x61 */
-#else
-             value_type >= (uint8)REF_TYPE_NULLREF /* 0x65 */
+                 || (value_type >= (uint8)REF_TYPE_STRINGVIEWWTF8
+                     && value_type <= (uint8)REF_TYPE_STRINGREF)
+                 || (value_type >= (uint8)REF_TYPE_STRINGVIEWITER
+                     && value_type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
 #endif
-             && value_type <= (uint8)REF_TYPE_FUNCREF /* 0x70 */) {
+                     )) {
         size_64bit = sizeof(uint64);
         size_32bit = sizeof(uint32);
     }
@@ -627,6 +631,12 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
 #if WASM_ENABLE_GC != 0
                 comp_data->tables[j].elem_ref_type =
                     module->tables[j].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
             }
         }

+ 4 - 2
core/iwasm/compilation/aot.h

@@ -143,6 +143,8 @@ typedef struct AOTTable {
     uint32 table_max_size;
 #if WASM_ENABLE_GC != 0
     WASMRefType *elem_ref_type;
+    /* init expr for the whole table */
+    InitializerExpression init_expr;
 #endif
 } AOTTable;
 
@@ -162,9 +164,9 @@ typedef struct AOTTableInitData {
     /* Start address of init data */
     AOTInitExpr offset;
     /* Function index count */
-    uint32 func_index_count;
+    uint32 value_count;
     /* Function index array */
-    uintptr_t func_indexes[1];
+    InitializerExpression init_values[1];
 } AOTTableInitData;
 
 /**

+ 43 - 29
core/iwasm/compilation/aot_compiler.c

@@ -1401,12 +1401,12 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
                 opcode = (uint8)opcode1;
 
                 switch (opcode) {
-                    case WASM_OP_STRUCT_NEW_CANON:
-                    case WASM_OP_STRUCT_NEW_CANON_DEFAULT:
+                    case WASM_OP_STRUCT_NEW:
+                    case WASM_OP_STRUCT_NEW_DEFAULT:
                         read_leb_uint32(frame_ip, frame_ip_end, type_index);
                         if (!aot_compile_op_struct_new(
                                 comp_ctx, func_ctx, type_index,
-                                opcode == WASM_OP_STRUCT_NEW_CANON_DEFAULT,
+                                opcode == WASM_OP_STRUCT_NEW_DEFAULT,
                                 frame_ip_org))
                             return false;
                         break;
@@ -1430,23 +1430,23 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
                             return false;
                         break;
 
-                    case WASM_OP_ARRAY_NEW_CANON:
-                    case WASM_OP_ARRAY_NEW_CANON_DEFAULT:
-                    case WASM_OP_ARRAY_NEW_CANON_FIXED:
+                    case WASM_OP_ARRAY_NEW:
+                    case WASM_OP_ARRAY_NEW_DEFAULT:
+                    case WASM_OP_ARRAY_NEW_FIXED:
                         read_leb_uint32(frame_ip, frame_ip_end, type_index);
-                        if (opcode == WASM_OP_ARRAY_NEW_CANON_FIXED)
+                        if (opcode == WASM_OP_ARRAY_NEW_FIXED)
                             read_leb_uint32(frame_ip, frame_ip_end, array_len);
                         else
                             array_len = 0;
                         if (!aot_compile_op_array_new(
                                 comp_ctx, func_ctx, type_index,
-                                opcode == WASM_OP_ARRAY_NEW_CANON_DEFAULT,
-                                opcode == WASM_OP_ARRAY_NEW_CANON_FIXED,
-                                array_len, frame_ip_org))
+                                opcode == WASM_OP_ARRAY_NEW_DEFAULT,
+                                opcode == WASM_OP_ARRAY_NEW_FIXED, array_len,
+                                frame_ip_org))
                             return false;
                         break;
 
-                    case WASM_OP_ARRAY_NEW_CANON_DATA:
+                    case WASM_OP_ARRAY_NEW_DATA:
                         read_leb_uint32(frame_ip, frame_ip_end, type_index);
                         read_leb_uint32(frame_ip, frame_ip_end, data_seg_idx);
                         if (!aot_compile_op_array_new_data(
@@ -1455,7 +1455,7 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
                             return false;
                         break;
 
-                    case WASM_OP_ARRAY_NEW_CANON_ELEM:
+                    case WASM_OP_ARRAY_NEW_ELEM:
                         /* TODO */
                         aot_set_last_error("unsupported opcode");
                         return false;
@@ -1477,7 +1477,13 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
                             return false;
                         break;
 
-#if WASM_ENABLE_GC_BINARYEN != 0
+                    case WASM_OP_ARRAY_FILL:
+                        read_leb_uint32(frame_ip, frame_ip_end, type_index);
+                        if (!aot_compile_op_array_fill(comp_ctx, func_ctx,
+                                                       type_index))
+                            return false;
+                        break;
+
                     case WASM_OP_ARRAY_COPY:
                     {
                         uint32 src_type_index;
@@ -1489,14 +1495,13 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
                             return false;
                         break;
                     }
-#endif
 
                     case WASM_OP_ARRAY_LEN:
                         if (!aot_compile_op_array_len(comp_ctx, func_ctx))
                             return false;
                         break;
 
-                    case WASM_OP_I31_NEW:
+                    case WASM_OP_REF_I31:
                         if (!aot_compile_op_i31_new(comp_ctx, func_ctx))
                             return false;
                         break;
@@ -1539,34 +1544,43 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
 
                     case WASM_OP_BR_ON_CAST:
                     case WASM_OP_BR_ON_CAST_FAIL:
-                    case WASM_OP_BR_ON_CAST_NULLABLE:
-                    case WASM_OP_BR_ON_CAST_FAIL_NULLABLE:
                     {
-                        int32 heap_type;
+                        uint8 castflags;
+                        int32 heap_type, dst_heap_type;
 
+                        CHECK_BUF(frame_ip, frame_ip_end, 1);
+                        castflags = *frame_ip++;
                         read_leb_uint32(frame_ip, frame_ip_end, br_depth);
                         read_leb_int32(frame_ip, frame_ip_end, heap_type);
-
+                        read_leb_int32(frame_ip, frame_ip_end, dst_heap_type);
+
+                        /*
+                         * castflags should be 0~3:
+                         *  0: (non-null, non-null)
+                         *  1: (null, non-null)
+                         *  2: (non-null, null)
+                         *  3: (null, null)
+                         * The nullability of source type has been checked in
+                         * wasm loader, here we just need the dst nullability
+                         */
                         if (!aot_compile_op_br_on_cast(
-                                comp_ctx, func_ctx, heap_type,
-                                opcode == WASM_OP_BR_ON_CAST_NULLABLE
-                                    || opcode
-                                           == WASM_OP_BR_ON_CAST_FAIL_NULLABLE,
-                                opcode == WASM_OP_BR_ON_CAST_FAIL
-                                    || opcode
-                                           == WASM_OP_BR_ON_CAST_FAIL_NULLABLE,
-                                br_depth, frame_ip_org, &frame_ip))
+                                comp_ctx, func_ctx, dst_heap_type,
+                                castflags & 0x02,
+                                opcode == WASM_OP_BR_ON_CAST_FAIL, br_depth,
+                                frame_ip_org, &frame_ip))
                             return false;
+
+                        (void)heap_type;
                         break;
                     }
 
-                    case WASM_OP_EXTERN_INTERNALIZE:
+                    case WASM_OP_ANY_CONVERT_EXTERN:
                         if (!aot_compile_op_extern_internalize(comp_ctx,
                                                                func_ctx))
                             return false;
                         break;
 
-                    case WASM_OP_EXTERN_EXTERNALIZE:
+                    case WASM_OP_EXTERN_CONVERT_ANY:
                         if (!aot_compile_op_extern_externalize(
                                 comp_ctx, func_ctx, frame_ip_org))
                             return false;

+ 9 - 5
core/iwasm/compilation/aot_compiler.h

@@ -88,13 +88,17 @@ typedef enum FloatArithmetic {
 static inline bool
 aot_is_type_gc_reftype(uint8 type)
 {
-    return (
+    return ((type >= (uint8)REF_TYPE_ARRAYREF
+             && type <= (uint8)REF_TYPE_NULLFUNCREF)
+            || (type >= (uint8)REF_TYPE_HT_NULLABLE
+                && type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
 #if WASM_ENABLE_STRINGREF != 0
-               type >= (uint8)REF_TYPE_STRINGVIEWITER
-#else
-               type >= (uint8)REF_TYPE_NULLREF
+            || (type >= (uint8)REF_TYPE_STRINGVIEWWTF8
+                && type <= (uint8)REF_TYPE_STRINGREF)
+            || (type >= (uint8)REF_TYPE_STRINGVIEWITER
+                && type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
 #endif
-               && type <= (uint8)REF_TYPE_FUNCREF)
+                )
                ? true
                : false;
 }

+ 338 - 35
core/iwasm/compilation/aot_emit_aot_file.c

@@ -263,10 +263,130 @@ get_mem_info_size(AOTCompData *comp_data)
                                          comp_data->mem_init_data_count);
 }
 
+#if WASM_ENABLE_GC != 0
+static uint32
+get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
+                   InitializerExpression *expr)
+{
+    /* init_expr_type */
+    uint32 size = sizeof(uint32);
+    WASMModule *module = comp_data->wasm_module;
+
+    /* + init value size */
+    switch (expr->init_expr_type) {
+        case INIT_EXPR_NONE:
+            /* no init value, used in table initializer */
+            break;
+        case INIT_EXPR_TYPE_I32_CONST:
+        case INIT_EXPR_TYPE_F32_CONST:
+        case INIT_EXPR_TYPE_GET_GLOBAL:
+        case INIT_EXPR_TYPE_FUNCREF_CONST:
+        case INIT_EXPR_TYPE_I31_NEW:
+            size += sizeof(uint32);
+            break;
+        case INIT_EXPR_TYPE_I64_CONST:
+        case INIT_EXPR_TYPE_F64_CONST:
+            size += sizeof(uint64);
+            break;
+        case INIT_EXPR_TYPE_V128_CONST:
+            size += sizeof(uint64) * 2;
+            break;
+        case INIT_EXPR_TYPE_REFNULL_CONST:
+            /* type_index */
+            size += sizeof(uint32);
+            break;
+        case INIT_EXPR_TYPE_STRUCT_NEW:
+        {
+            uint32 i;
+            WASMStructNewInitValues *struct_new_init_values =
+                (WASMStructNewInitValues *)expr->u.data;
+
+            /* type_index + field_count + fields */
+            size += sizeof(uint32) + sizeof(uint32);
+
+            bh_assert(struct_new_init_values->type_idx < module->type_count);
+
+            for (i = 0; i < struct_new_init_values->count; i++) {
+                WASMStructType *struct_type =
+                    (WASMStructType *)
+                        module->types[struct_new_init_values->type_idx];
+                bh_assert(struct_type);
+                bh_assert(struct_type->field_count
+                          == struct_new_init_values->count);
+
+                size += wasm_value_type_size_internal(
+                    struct_type->fields[i].field_type, comp_ctx->pointer_size);
+            }
+            break;
+        }
+        case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
+            /* type_index */
+            size += sizeof(uint32);
+            break;
+        case INIT_EXPR_TYPE_ARRAY_NEW:
+            /* type_index + len + elem */
+            size += sizeof(uint32) * 2 + sizeof(WASMValue);
+            break;
+        case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
+            /* type_index + len */
+            size += sizeof(uint32) * 2;
+            break;
+        case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
+        {
+            WASMArrayNewInitValues *array_new_init_values =
+                (WASMArrayNewInitValues *)expr->u.data;
+            WASMArrayType *array_type = NULL;
+
+            bh_assert(array_type);
+            bh_assert(array_new_init_values->type_idx < module->type_count);
+
+            array_type =
+                (WASMArrayType *)module->types[array_new_init_values->type_idx];
+
+            /* type_index + len + elems */
+            size += sizeof(uint32) * 2
+                    + array_new_init_values->length
+                          * wasm_value_type_size_internal(
+                              array_type->elem_type, comp_ctx->pointer_size);
+            break;
+        }
+        default:
+            bh_assert(0);
+    }
+
+    return size;
+}
+#endif /* end of WASM_ENABLE_GC != 0 */
+
 static uint32
 get_table_init_data_size(AOTCompContext *comp_ctx,
                          AOTTableInitData *table_init_data)
 {
+#if WASM_ENABLE_GC != 0
+    if (comp_ctx->enable_gc) {
+        uint32 size, i;
+
+        /*
+         * mode (4 bytes), elem_type (4 bytes)
+         *
+         * table_index(4 bytes) + init expr type (4 bytes) + init expr value (8
+         * bytes) + sizeof(WASMRefType)
+         * + value count (4 bytes) + init_values
+         */
+        size = (uint32)(sizeof(uint32) * 2 + sizeof(uint32) + sizeof(uint32)
+                        + sizeof(uint64) + sizeof(uint32))
+               /* Size of WasmRefType - inner padding (ref type + nullable +
+                  heap_type) */
+               + 8;
+
+        for (i = 0; i < table_init_data->value_count; i++) {
+            size += get_init_expr_size(comp_ctx, comp_ctx->comp_data,
+                                       &table_init_data->init_values[i]);
+        }
+
+        return size;
+    }
+#endif
     /*
      * mode (4 bytes), elem_type (4 bytes)
      *
@@ -276,8 +396,7 @@ get_table_init_data_size(AOTCompContext *comp_ctx,
      */
     return (uint32)(sizeof(uint32) * 2 + sizeof(uint32) + sizeof(uint32)
                     + sizeof(uint64) + sizeof(uint32)
-                    + comp_ctx->pointer_size
-                          * table_init_data->func_index_count)
+                    + comp_ctx->pointer_size * table_init_data->value_count)
            /* Size of WasmRefType - inner padding (ref type + nullable +
               heap_type) */
            + 8;
@@ -357,6 +476,7 @@ get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data)
      * |             | U32 table_init_size
      * |             | U32 table_max_size
      * |             | U32 elem_ref_type.heap_type (for GC only)
+     * |             | N   init_expr (for GC only)
      * ------------------------------
      */
     uint32 size = 0, i;
@@ -365,8 +485,13 @@ get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data)
     for (i = 0; i < comp_data->table_count; i++) {
         size += sizeof(uint32) * 3;
 #if WASM_ENABLE_GC != 0
-        if (comp_ctx->enable_gc && comp_data->tables[i].elem_ref_type)
-            size += sizeof(uint32);
+        if (comp_ctx->enable_gc) {
+            if (comp_data->tables[i].elem_ref_type) {
+                size += sizeof(uint32);
+            }
+            size += get_init_expr_size(comp_ctx, comp_data,
+                                       &comp_data->tables[i].init_expr);
+        }
 #endif
     }
     return size;
@@ -407,7 +532,8 @@ get_table_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 static uint32
 get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
 {
-    /* type flag + is_sub_final + parent_type_idx + param count + result count
+    /* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + param
+     * count + result count
      * + ref_type_map_count + types + context of ref_type_map */
     if (comp_ctx->enable_gc) {
         uint32 size = 0;
@@ -418,6 +544,10 @@ get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
         size += sizeof(uint16);
         /* parent_type_idx */
         size += sizeof(func_type->base_type.parent_type_idx);
+        /* rec_count */
+        size += sizeof(func_type->base_type.rec_count);
+        /* rec_idx */
+        size += sizeof(func_type->base_type.rec_idx);
         /* param count */
         size += sizeof(func_type->param_count);
         /* result count */
@@ -445,7 +575,8 @@ static uint32
 get_struct_type_size(AOTCompContext *comp_ctx, AOTStructType *struct_type)
 {
     uint32 size = 0;
-    /* type flag + is_sub_final + parent_type_idx + field count + fields */
+    /* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + field
+     * count + fields */
 
     /* type flag */
     size += sizeof(struct_type->base_type.type_flag);
@@ -453,6 +584,10 @@ get_struct_type_size(AOTCompContext *comp_ctx, AOTStructType *struct_type)
     size += sizeof(uint16);
     /* parent_type_idx */
     size += sizeof(struct_type->base_type.parent_type_idx);
+    /* rec_count */
+    size += sizeof(struct_type->base_type.rec_count);
+    /* rec_idx */
+    size += sizeof(struct_type->base_type.rec_idx);
     /* field count */
     size += sizeof(struct_type->field_count);
     /* field types */
@@ -469,8 +604,8 @@ static uint32
 get_array_type_size(AOTCompContext *comp_ctx, AOTArrayType *array_type)
 {
     uint32 size = 0;
-    /* type flag + is_sub_final + parent_type_idx + elem_flags +
-       elem_type + elem_ref_type */
+    /* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx +
+       elem_flags + elem_type + elem_ref_type */
 
     /* type flag */
     size += sizeof(array_type->base_type.type_flag);
@@ -478,6 +613,10 @@ get_array_type_size(AOTCompContext *comp_ctx, AOTArrayType *array_type)
     size += sizeof(uint16);
     /* parent_type_idx (u32) */
     size += sizeof(array_type->base_type.parent_type_idx);
+    /* rec_count */
+    size += sizeof(array_type->base_type.rec_count);
+    /* rec_idx */
+    size += sizeof(array_type->base_type.rec_idx);
     /* elem_flags (u16) */
     size += sizeof(array_type->elem_flags);
     /* elem_type (u8) */
@@ -577,37 +716,48 @@ get_import_global_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 }
 
 static uint32
-get_global_size(AOTGlobal *global)
+get_global_size(AOTCompContext *comp_ctx, AOTGlobal *global)
 {
+#if WASM_ENABLE_GC != 0
+    if (comp_ctx->enable_gc) {
+        /* type (1 byte) + is_mutable (1 byte) + padding (2 bytes)
+                + init expr value (include init expr type) */
+        return sizeof(uint8) * 2 + sizeof(uint8) * 2
+               + get_init_expr_size(comp_ctx, comp_ctx->comp_data,
+                                    &global->init_expr);
+    }
+#endif
     if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
         /* type (1 byte) + is_mutable (1 byte)
-           + init expr type (2 byes) + init expr value (8 byes) */
+        + init expr type (2 bytes) + init expr value (8 bytes) */
         return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64);
     else
         /* type (1 byte) + is_mutable (1 byte)
-           + init expr type (2 byes) + v128 value (16 byes) */
+           + init expr type (2 bytes) + v128 value (16 bytes) */
         return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64) * 2;
 }
 
 static uint32
-get_globals_size(AOTGlobal *globals, uint32 global_count)
+get_globals_size(AOTCompContext *comp_ctx, AOTGlobal *globals,
+                 uint32 global_count)
 {
     AOTGlobal *global = globals;
     uint32 size = 0, i;
 
     for (i = 0; i < global_count; i++, global++) {
         size = align_uint(size, 4);
-        size += get_global_size(global);
+        size += get_global_size(comp_ctx, global);
     }
     return size;
 }
 
 static uint32
-get_global_info_size(AOTCompData *comp_data)
+get_global_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 {
     /* global count + globals */
     return (uint32)sizeof(uint32)
-           + get_globals_size(comp_data->globals, comp_data->global_count);
+           + get_globals_size(comp_ctx, comp_data->globals,
+                              comp_data->global_count);
 }
 
 static uint32
@@ -691,7 +841,7 @@ get_init_data_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
     size += get_import_global_info_size(comp_ctx, comp_data);
 
     size = align_uint(size, 4);
-    size += get_global_info_size(comp_data);
+    size += get_global_info_size(comp_ctx, comp_data);
 
     size = align_uint(size, 4);
     size += get_import_func_info_size(comp_ctx, comp_data);
@@ -1653,6 +1803,125 @@ aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     return true;
 }
 
+#if WASM_ENABLE_GC != 0
+static bool
+aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                   AOTCompContext *comp_ctx, InitializerExpression *expr)
+{
+    uint32 offset = *p_offset;
+    WASMModule *module = comp_ctx->comp_data->wasm_module;
+
+    *p_offset = offset = align_uint(offset, 4);
+
+    EMIT_U32(expr->init_expr_type);
+    switch (expr->init_expr_type) {
+        case INIT_EXPR_NONE:
+            break;
+        case INIT_EXPR_TYPE_I32_CONST:
+        case INIT_EXPR_TYPE_F32_CONST:
+            EMIT_U32(expr->u.i32);
+            break;
+        case INIT_EXPR_TYPE_I64_CONST:
+        case INIT_EXPR_TYPE_F64_CONST:
+            EMIT_U64(expr->u.i64);
+            break;
+        case INIT_EXPR_TYPE_V128_CONST:
+            EMIT_V128(expr->u.v128);
+            break;
+        case INIT_EXPR_TYPE_GET_GLOBAL:
+            EMIT_U32(expr->u.global_index);
+            break;
+        case INIT_EXPR_TYPE_REFNULL_CONST:
+            EMIT_U32(expr->u.type_index);
+            break;
+        case INIT_EXPR_TYPE_FUNCREF_CONST:
+            EMIT_U32(expr->u.ref_index);
+            break;
+        case INIT_EXPR_TYPE_I31_NEW:
+            EMIT_U32(expr->u.i32);
+            break;
+        case INIT_EXPR_TYPE_STRUCT_NEW:
+        {
+            uint32 i;
+            WASMStructNewInitValues *init_values =
+                (WASMStructNewInitValues *)expr->u.data;
+            WASMStructType *struct_type = NULL;
+
+            EMIT_U32(init_values->type_idx);
+            EMIT_U32(init_values->count);
+
+            bh_assert(init_values->type_idx < module->type_count);
+
+            struct_type =
+                (WASMStructType *)module->types[init_values->type_idx];
+
+            bh_assert(struct_type);
+            bh_assert(struct_type->field_count == init_values->count);
+
+            for (i = 0; i < init_values->count; i++) {
+                uint32 field_size = wasm_value_type_size_internal(
+                    struct_type->fields[i].field_type, comp_ctx->pointer_size);
+                if (field_size <= sizeof(uint32))
+                    EMIT_U32(init_values->fields[i].u32);
+                else if (field_size == sizeof(uint64))
+                    EMIT_U64(init_values->fields[i].u64);
+                else if (field_size == sizeof(uint64) * 2)
+                    EMIT_V128(init_values->fields[i].v128);
+                else {
+                    bh_assert(0);
+                }
+            }
+
+            break;
+        }
+        case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
+            EMIT_U32(expr->u.type_index);
+            break;
+        case INIT_EXPR_TYPE_ARRAY_NEW:
+        case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
+        case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
+        {
+            uint32 i;
+            WASMArrayNewInitValues *init_values =
+                (WASMArrayNewInitValues *)expr->u.data;
+            WASMArrayType *array_type = NULL;
+
+            EMIT_U32(init_values->type_idx);
+            EMIT_U32(init_values->length);
+
+            bh_assert(init_values->type_idx < module->type_count);
+
+            array_type = (WASMArrayType *)module->types[init_values->type_idx];
+
+            bh_assert(array_type);
+
+            if (expr->init_expr_type != INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
+                uint32 field_size = wasm_value_type_size_internal(
+                    array_type->elem_type, comp_ctx->pointer_size);
+                for (i = 0; i < init_values->length; i++) {
+                    if (field_size <= sizeof(uint32))
+                        EMIT_U32(init_values->elem_data[i].u32);
+                    else if (field_size == sizeof(uint64))
+                        EMIT_U64(init_values->elem_data[i].u64);
+                    else if (field_size == sizeof(uint64) * 2)
+                        EMIT_V128(init_values->elem_data[i].v128);
+                    else {
+                        bh_assert(0);
+                    }
+                }
+            }
+            break;
+        }
+        default:
+            aot_set_last_error("invalid init expr type.");
+            return false;
+    }
+
+    *p_offset = offset;
+    return true;
+}
+#endif /* end of WASM_ENABLE_GC != 0 */
+
 static bool
 aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                     AOTCompContext *comp_ctx, AOTCompData *comp_data,
@@ -1717,11 +1986,17 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
         EMIT_U32(comp_data->tables[i].table_init_size);
         EMIT_U32(comp_data->tables[i].table_max_size);
 #if WASM_ENABLE_GC != 0
-        if (comp_ctx->enable_gc && comp_data->tables[i].elem_ref_type) {
-            bh_assert(
-                wasm_is_type_multi_byte_type(comp_data->tables[i].elem_type));
-            EMIT_U32(
-                comp_data->tables[i].elem_ref_type->ref_ht_common.heap_type);
+        if (comp_ctx->enable_gc) {
+            if (comp_data->tables[i].elem_ref_type) {
+                bh_assert(wasm_is_type_multi_byte_type(
+                    comp_data->tables[i].elem_type));
+                EMIT_U32(comp_data->tables[i]
+                             .elem_ref_type->ref_ht_common.heap_type);
+            }
+            if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
+                                    &comp_data->tables[i].init_expr)) {
+                return false;
+            }
         }
 #endif
     }
@@ -1749,14 +2024,27 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
             EMIT_U16(0);
             EMIT_U32(0);
         }
-        EMIT_U32(init_datas[i]->func_index_count);
-        for (j = 0; j < init_datas[i]->func_index_count; j++) {
-
-            if (comp_ctx->pointer_size == 4) {
-                EMIT_U32(init_datas[i]->func_indexes[j]);
+        EMIT_U32(init_datas[i]->value_count);
+        for (j = 0; j < init_datas[i]->value_count; j++) {
+#if WASM_ENABLE_GC != 0
+            if (comp_ctx->enable_gc) {
+                if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
+                                        &init_datas[i]->init_values[j]))
+                    return false;
             }
-            else {
-                EMIT_U64(init_datas[i]->func_indexes[j]);
+            else
+#endif
+            {
+                bh_assert(init_datas[i]->init_values[j].init_expr_type
+                              == INIT_EXPR_TYPE_REFNULL_CONST
+                          || init_datas[i]->init_values[j].init_expr_type
+                                 == INIT_EXPR_TYPE_FUNCREF_CONST);
+                if (comp_ctx->pointer_size == 4) {
+                    EMIT_U32(init_datas[i]->init_values[j].u.ref_index);
+                }
+                else {
+                    EMIT_U64(init_datas[i]->init_values[j].u.ref_index);
+                }
             }
         }
     }
@@ -1817,6 +2105,9 @@ aot_emit_type_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
             EMIT_U16(types[i]->is_sub_final);
             EMIT_U32(types[i]->parent_type_idx);
 
+            EMIT_U16(types[i]->rec_count);
+            EMIT_U16(types[i]->rec_idx);
+
             /* Emit WASM_TYPE_FUNC */
             if (types[i]->type_flag == WASM_TYPE_FUNC) {
                 AOTFuncType *func_type = (AOTFuncType *)types[i];
@@ -1939,7 +2230,8 @@ aot_emit_import_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
 
 static bool
 aot_emit_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
-                     AOTCompData *comp_data, AOTObjectData *obj_data)
+                     AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                     AOTObjectData *obj_data)
 {
     uint32 offset = *p_offset, i;
     AOTGlobal *global = comp_data->globals;
@@ -1952,14 +2244,24 @@ aot_emit_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
         offset = align_uint(offset, 4);
         EMIT_U8(global->type);
         EMIT_U8(global->is_mutable);
-        EMIT_U16(global->init_expr.init_expr_type);
-        if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
-            EMIT_U64(global->init_expr.u.i64);
+#if WASM_ENABLE_GC != 0
+        if (comp_ctx->enable_gc) {
+            if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
+                                    &global->init_expr))
+                return false;
+        }
         else
-            EMIT_V128(global->init_expr.u.v128);
+#endif /* end of WASM_ENABLE_GC != 0 */
+        {
+            EMIT_U16(global->init_expr.init_expr_type);
+            if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
+                EMIT_U64(global->init_expr.u.i64);
+            else
+                EMIT_V128(global->init_expr.u.v128);
+        }
     }
 
-    if (offset - *p_offset != get_global_info_size(comp_data)) {
+    if (offset - *p_offset != get_global_info_size(comp_ctx, comp_data)) {
         aot_set_last_error("emit global info failed.");
         return false;
     }
@@ -2075,7 +2377,8 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                                obj_data)
         || !aot_emit_import_global_info(buf, buf_end, &offset, comp_ctx,
                                         comp_data, obj_data)
-        || !aot_emit_global_info(buf, buf_end, &offset, comp_data, obj_data)
+        || !aot_emit_global_info(buf, buf_end, &offset, comp_ctx, comp_data,
+                                 obj_data)
         || !aot_emit_import_func_info(buf, buf_end, &offset, comp_ctx,
                                       comp_data, obj_data))
         return false;

+ 152 - 4
core/iwasm/compilation/aot_emit_gc.c

@@ -4,6 +4,7 @@
  */
 
 #include "aot_emit_gc.h"
+#include "aot_compiler.h"
 #include "aot_emit_exception.h"
 
 #if WASM_ENABLE_GC != 0
@@ -570,7 +571,7 @@ aot_compile_op_struct_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     SET_BUILDER_POS(check_struct_obj_succ);
 
-    /* For WASM_OP_STRUCT_NEW_CANON, init filed with poped value */
+    /* For WASM_OP_STRUCT_NEW, init filed with poped value */
     if (!init_with_default
         && !struct_new_canon_init_fields(comp_ctx, func_ctx, type_index,
                                          struct_obj)) {
@@ -1152,7 +1153,7 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     else
         array_length = I32_CONST(array_len);
 
-    /* For WASM_OP_ARRAY_NEW_CANON */
+    /* For WASM_OP_ARRAY_NEW */
     if (!fixed_size && !init_with_default) {
         if (wasm_is_type_reftype(array_elem_type)) {
             POP_GC_REF(array_elem);
@@ -1456,7 +1457,155 @@ fail:
     return false;
 }
 
-#if WASM_ENABLE_GC_BINARYEN != 0
+bool
+aot_compile_op_array_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                          uint32 type_index)
+{
+    LLVMValueRef len, array_obj, fill_value = NULL, offset, array_len, cmp[2],
+                                 boundary, loop_counter_addr, loop_counter_val;
+    LLVMBasicBlockRef check_obj_succ, len_gt_zero, len_le_zero, inner_else;
+    LLVMBasicBlockRef fill_loop_header, fill_loop_body;
+    WASMArrayType *compile_time_array_type =
+        (WASMArrayType *)comp_ctx->comp_data->types[type_index];
+    uint8 array_elem_type = compile_time_array_type->elem_type;
+
+    POP_I32(len);
+    /* Get LLVM type based on array_elem_type */
+    if (wasm_is_type_reftype(array_elem_type)) {
+        POP_GC_REF(fill_value);
+    }
+    else if (array_elem_type == VALUE_TYPE_I32
+             || array_elem_type == PACKED_TYPE_I8
+             || array_elem_type == PACKED_TYPE_I16) {
+        POP_I32(fill_value);
+    }
+    else if (array_elem_type == VALUE_TYPE_I64) {
+        POP_I64(fill_value);
+    }
+    else if (array_elem_type == VALUE_TYPE_F32) {
+        POP_F32(fill_value);
+    }
+    else if (array_elem_type == VALUE_TYPE_F64) {
+        POP_F64(fill_value);
+    }
+    else {
+        bh_assert(0);
+    }
+
+    POP_I32(offset);
+    POP_GC_REF(array_obj);
+
+    ADD_BASIC_BLOCK(check_obj_succ, "check array objs succ");
+    MOVE_BLOCK_AFTER_CURR(check_obj_succ);
+
+    BUILD_ISNULL(array_obj, cmp[0], "cmp_obj");
+
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_ARRAY_OBJ, true,
+                            cmp[0], check_obj_succ))
+        goto fail;
+
+    /* Create if block */
+    ADD_BASIC_BLOCK(len_gt_zero, "len_gt_zero");
+    MOVE_BLOCK_AFTER_CURR(len_gt_zero);
+
+    /* Create inner else block */
+    ADD_BASIC_BLOCK(inner_else, "inner_else");
+    MOVE_BLOCK_AFTER(inner_else, len_gt_zero);
+
+    /* Create fill_loop_header block */
+    ADD_BASIC_BLOCK(fill_loop_header, "fill_loop_header");
+    MOVE_BLOCK_AFTER(fill_loop_header, len_gt_zero);
+
+    /* Create fill_loop_body block */
+    ADD_BASIC_BLOCK(fill_loop_body, "fill_loop_body");
+    MOVE_BLOCK_AFTER(fill_loop_body, len_gt_zero);
+
+    /* Create else(end) block */
+    ADD_BASIC_BLOCK(len_le_zero, "len_le_zero");
+    MOVE_BLOCK_AFTER(len_le_zero, len_gt_zero);
+
+    BUILD_ICMP(LLVMIntSGT, len, I32_ZERO, cmp[0], "cmp_len");
+    BUILD_COND_BR(cmp[0], len_gt_zero, len_le_zero);
+
+    /* Move builder to len > 0 block */
+    SET_BUILDER_POS(len_gt_zero);
+    /* dst_offset > UINT32_MAX - len */
+    if (!(boundary = LLVMBuildAdd(comp_ctx->builder, offset, len, ""))) {
+        aot_set_last_error("llvm build failed.");
+        goto fail;
+    }
+    BUILD_ICMP(LLVMIntUGT, boundary, I32_CONST(UINT32_MAX), cmp[0],
+               "boundary_check1");
+    /* dst_offset + len > wasm_array_obj_length(dst_obj) */
+    if (!aot_array_obj_length(comp_ctx, array_obj, &array_len))
+        goto fail;
+    BUILD_ICMP(LLVMIntUGT, boundary, array_len, cmp[1], "boundary_check2");
+
+    if (!(cmp[0] = LLVMBuildOr(comp_ctx->builder, cmp[0], cmp[1], ""))) {
+        aot_set_last_error("llvm build failed.");
+        goto fail;
+    }
+
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_IDX_OOB, true,
+                            cmp[0], inner_else))
+        goto fail;
+
+    if (!(loop_counter_addr = LLVMBuildAlloca(comp_ctx->builder, I32_TYPE,
+                                              "fill_loop_counter"))) {
+        aot_set_last_error("llvm build alloc failed.");
+        goto fail;
+    }
+
+    if (!is_target_x86(comp_ctx)) {
+        LLVMSetAlignment(loop_counter_addr, 4);
+    }
+
+    if (!LLVMBuildStore(comp_ctx->builder, offset, loop_counter_addr)) {
+        aot_set_last_error("llvm build store failed.");
+        goto fail;
+    }
+
+    BUILD_BR(fill_loop_header);
+    SET_BUILDER_POS(fill_loop_header);
+
+    if (!(loop_counter_val =
+              LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, loop_counter_addr,
+                             "fill_loop_counter"))) {
+        aot_set_last_error("llvm build load failed.");
+        goto fail;
+    }
+
+    BUILD_ICMP(LLVMIntULT, loop_counter_val, boundary, cmp[0],
+               "cmp_loop_counter");
+    BUILD_COND_BR(cmp[0], fill_loop_body, len_le_zero);
+
+    SET_BUILDER_POS(fill_loop_body);
+
+    if (!aot_array_obj_set_elem(comp_ctx, func_ctx, array_obj, loop_counter_val,
+                                fill_value, array_elem_type))
+        goto fail;
+
+    if (!(loop_counter_val = LLVMBuildAdd(comp_ctx->builder, loop_counter_val,
+                                          I32_ONE, "fill_loop_counter"))) {
+        aot_set_last_error("llvm build add failed.");
+        goto fail;
+    }
+
+    if (!LLVMBuildStore(comp_ctx->builder, loop_counter_val,
+                        loop_counter_addr)) {
+        aot_set_last_error("llvm build store failed.");
+        goto fail;
+    }
+
+    BUILD_BR(fill_loop_header);
+
+    SET_BUILDER_POS(len_le_zero);
+
+    return true;
+fail:
+    return false;
+}
+
 static bool
 aot_call_wasm_array_obj_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                              LLVMValueRef dst_obj, LLVMValueRef dst_offset,
@@ -1586,7 +1735,6 @@ aot_compile_op_array_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 fail:
     return false;
 }
-#endif /* end of WASM_ENABLE_GC_BINARYEN != 0 */
 
 bool
 aot_compile_op_array_len(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)

+ 4 - 2
core/iwasm/compilation/aot_emit_gc.h

@@ -79,11 +79,13 @@ bool
 aot_compile_op_array_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 type_index);
 
-#if WASM_ENABLE_GC_BINARYEN != 0
+bool
+aot_compile_op_array_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                          uint32 type_index);
+
 bool
 aot_compile_op_array_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                           uint32 type_index, uint32 src_type_index);
-#endif
 
 bool
 aot_compile_op_array_len(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);

+ 11 - 8
core/iwasm/fast-jit/fe/jit_emit_table.c

@@ -96,10 +96,11 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
     WASMTableInstance *tbl;
     uint32 tbl_sz;
     WASMTableSeg *elem;
-    uint32 elem_len;
+    uint32 elem_len, i;
+    table_elem_type_t *addr;
 
     elem = inst->module->table_segments + elem_idx;
-    elem_len = elem->function_count;
+    elem_len = elem->value_count;
     if (offset_len_out_of_bounds(src_offset, len, elem_len))
         goto out_of_bounds;
 
@@ -114,12 +115,14 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
     if (bh_bitmap_get_bit(inst->e->common.elem_dropped, elem_idx))
         goto out_of_bounds;
 
-    bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
-                    + dst_offset * sizeof(table_elem_type_t),
-                (uint32)((tbl_sz - dst_offset) * sizeof(table_elem_type_t)),
-                elem->func_indexes + src_offset,
-                (uint32)(len * sizeof(table_elem_type_t)));
-
+    addr =
+        (table_elem_type_t *)((uint8 *)tbl + offsetof(WASMTableInstance, elems)
+                              + dst_offset * sizeof(table_elem_type_t));
+    for (i = 0; i < len; i++) {
+        addr[i] =
+            (table_elem_type_t)(uintptr_t)elem->init_values[src_offset + i]
+                .u.ref_index;
+    }
     return 0;
 out_of_bounds:
     wasm_set_exception(inst, "out of bounds table access");

+ 20 - 13
core/iwasm/include/gc_export.h

@@ -20,22 +20,24 @@ typedef enum wasm_value_type_enum {
     VALUE_TYPE_F32 = 0x7D,
     VALUE_TYPE_F64 = 0x7C,
     VALUE_TYPE_V128 = 0x7B,
-    VALUE_TYPE_I8 = 0x7A,
-    VALUE_TYPE_I16 = 0x79,
+    /* GC Types */
+    VALUE_TYPE_I8 = 0x78,
+    VALUE_TYPE_I16 = 0x77,
+    VALUE_TYPE_NULLFUNCREF = 0x73,
+    VALUE_TYPE_NULLEXTERNREF = 0x72,
+    VALUE_TYPE_NULLREF = 0x71,
     VALUE_TYPE_FUNCREF = 0x70,
     VALUE_TYPE_EXTERNREF = 0x6F,
     VALUE_TYPE_ANYREF = 0x6E,
     VALUE_TYPE_EQREF = 0x6D,
-    VALUE_TYPE_HT_NULLABLE_REF = 0x6C,
-    VALUE_TYPE_HT_NON_NULLABLE_REF = 0x6B,
-    VALUE_TYPE_I31REF = 0x6A,
-    VALUE_TYPE_NULLFUNCREF = 0x69,
-    VALUE_TYPE_NULLEXTERNREF = 0x68,
-    VALUE_TYPE_STRUCTREF = 0x67,
-    VALUE_TYPE_ARRAYREF = 0x66,
-    VALUE_TYPE_NULLREF = 0x65,
-    VALUE_TYPE_STRINGREF = 0X64,
-    VALUE_TYPE_STRINGVIEWWTF8 = 0x63,
+    VALUE_TYPE_I31REF = 0x6C,
+    VALUE_TYPE_STRUCTREF = 0x6B,
+    VALUE_TYPE_ARRAYREF = 0x6A,
+    VALUE_TYPE_HT_NON_NULLABLE_REF = 0x64,
+    VALUE_TYPE_HT_NULLABLE_REF = 0x63,
+    /* Stringref Types */
+    VALUE_TYPE_STRINGREF = 0X67,
+    VALUE_TYPE_STRINGVIEWWTF8 = 0x66,
     VALUE_TYPE_STRINGVIEWWTF16 = 0x62,
     VALUE_TYPE_STRINGVIEWITER = 0x61
 } wasm_value_type_enum;
@@ -84,7 +86,12 @@ typedef union WASMValue {
     struct {
         uint32_t type_index;
         uint32_t N;
-    } array_new_canon_fixed;
+    } array_new_default;
+    /* pointer to a memory space holding more data, current usage:
+     *  struct.new init value: WASMStructNewInitValues *
+     *  array.new init value: WASMArrayNewInitValues *
+     */
+    void *data;
 } WASMValue;
 #endif /* end of WASM_VALUE_DEFINED */
 

+ 69 - 44
core/iwasm/interpreter/wasm.h

@@ -28,40 +28,40 @@ extern "C" {
 #define VALUE_TYPE_VOID 0x40
 
 /* Packed Types */
-#define PACKED_TYPE_I8 0x7A
-#define PACKED_TYPE_I16 0x79
+#define PACKED_TYPE_I8 0x78
+#define PACKED_TYPE_I16 0x77
 
 /* Reference Types */
-#define REF_TYPE_FUNCREF VALUE_TYPE_FUNCREF
-#define REF_TYPE_EXTERNREF VALUE_TYPE_EXTERNREF
+#define REF_TYPE_NULLFUNCREF 0x73
+#define REF_TYPE_NULLEXTERNREF 0x72
+#define REF_TYPE_NULLREF 0x71
+#define REF_TYPE_FUNCREF VALUE_TYPE_FUNCREF     /* 0x70 */
+#define REF_TYPE_EXTERNREF VALUE_TYPE_EXTERNREF /* 0x6F */
 #define REF_TYPE_ANYREF 0x6E
 #define REF_TYPE_EQREF 0x6D
-#define REF_TYPE_HT_NULLABLE 0x6C
-#define REF_TYPE_HT_NON_NULLABLE 0x6B
-#define REF_TYPE_I31REF 0x6A
-#define REF_TYPE_NULLFUNCREF 0x69
-#define REF_TYPE_NULLEXTERNREF 0x68
-#define REF_TYPE_STRUCTREF 0x67
-#define REF_TYPE_ARRAYREF 0x66
-#define REF_TYPE_NULLREF 0x65
-#define REF_TYPE_STRINGREF VALUE_TYPE_STRINGREF
-#define REF_TYPE_STRINGVIEWWTF8 VALUE_TYPE_STRINGVIEWWTF8
-#define REF_TYPE_STRINGVIEWWTF16 VALUE_TYPE_STRINGVIEWWTF16
-#define REF_TYPE_STRINGVIEWITER VALUE_TYPE_STRINGVIEWITER
+#define REF_TYPE_I31REF 0x6C
+#define REF_TYPE_STRUCTREF 0x6B
+#define REF_TYPE_ARRAYREF 0x6A
+#define REF_TYPE_HT_NON_NULLABLE 0x64
+#define REF_TYPE_HT_NULLABLE 0x63
+#define REF_TYPE_STRINGREF VALUE_TYPE_STRINGREF             /* 0x67 */
+#define REF_TYPE_STRINGVIEWWTF8 VALUE_TYPE_STRINGVIEWWTF8   /* 0x66 */
+#define REF_TYPE_STRINGVIEWWTF16 VALUE_TYPE_STRINGVIEWWTF16 /* 0x62 */
+#define REF_TYPE_STRINGVIEWITER VALUE_TYPE_STRINGVIEWITER   /* 0x61 */
 
 /* Heap Types */
+#define HEAP_TYPE_NOFUNC (-0x0D)
+#define HEAP_TYPE_NOEXTERN (-0x0E)
+#define HEAP_TYPE_NONE (-0x0F)
 #define HEAP_TYPE_FUNC (-0x10)
 #define HEAP_TYPE_EXTERN (-0x11)
 #define HEAP_TYPE_ANY (-0x12)
 #define HEAP_TYPE_EQ (-0x13)
-#define HEAP_TYPE_I31 (-0x16)
-#define HEAP_TYPE_NOFUNC (-0x17)
-#define HEAP_TYPE_NOEXTERN (-0x18)
-#define HEAP_TYPE_STRUCT (-0x19)
-#define HEAP_TYPE_ARRAY (-0x1A)
-#define HEAP_TYPE_NONE (-0x1B)
-#define HEAP_TYPE_STRINGREF (-0x1C)
-#define HEAP_TYPE_STRINGVIEWWTF8 (-0x1D)
+#define HEAP_TYPE_I31 (-0x14)
+#define HEAP_TYPE_STRUCT (-0x15)
+#define HEAP_TYPE_ARRAY (-0x16)
+#define HEAP_TYPE_STRINGREF (-0x19)
+#define HEAP_TYPE_STRINGVIEWWTF8 (-0x1A)
 #define HEAP_TYPE_STRINGVIEWWTF16 (-0x1E)
 #define HEAP_TYPE_STRINGVIEWITER (-0x1F)
 
@@ -70,8 +70,8 @@ extern "C" {
 #define DEFINED_TYPE_STRUCT 0x5F
 #define DEFINED_TYPE_ARRAY 0x5E
 #define DEFINED_TYPE_SUB 0x50
-#define DEFINED_TYPE_REC 0x4F
-#define DEFINED_TYPE_SUB_FINAL 0x4E
+#define DEFINED_TYPE_SUB_FINAL 0x4F
+#define DEFINED_TYPE_REC 0x4E
 
 /* Used by AOT */
 #define VALUE_TYPE_I1 0x41
@@ -102,6 +102,7 @@ typedef void *table_elem_type_t;
 #define REF_CELL_NUM ((uint32)sizeof(uintptr_t) / sizeof(uint32))
 #endif
 
+#define INIT_EXPR_NONE 0x00
 #define INIT_EXPR_TYPE_I32_CONST 0x41
 #define INIT_EXPR_TYPE_I64_CONST 0x42
 #define INIT_EXPR_TYPE_F32_CONST 0x43
@@ -110,17 +111,14 @@ typedef void *table_elem_type_t;
 #define INIT_EXPR_TYPE_GET_GLOBAL 0x23
 #define INIT_EXPR_TYPE_REFNULL_CONST 0xD0
 #define INIT_EXPR_TYPE_FUNCREF_CONST 0xD2
-#define INIT_EXPR_TYPE_STRUCT_NEW_CANON 0xD3
-#define INIT_EXPR_TYPE_STRUCT_NEW_CANON_DEFAULT 0xD4
-#define INIT_EXPR_TYPE_ARRAY_NEW_CANON 0xD5
-#define INIT_EXPR_TYPE_ARRAY_NEW_CANON_DEFAULT 0xD6
-#define INIT_EXPR_TYPE_ARRAY_NEW_CANON_FIXED 0xD7
+#define INIT_EXPR_TYPE_STRUCT_NEW 0xD3
+#define INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT 0xD4
+#define INIT_EXPR_TYPE_ARRAY_NEW 0xD5
+#define INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT 0xD6
+#define INIT_EXPR_TYPE_ARRAY_NEW_FIXED 0xD7
 #define INIT_EXPR_TYPE_I31_NEW 0xD8
-#define INIT_EXPR_TYPE_EXTERN_INTERNALIZE 0xD9
-#define INIT_EXPR_TYPE_EXTERN_EXTERNALIZE 0xDA
-
-/* TODO: const initial expression of struct/array new */
-#define INIT_EXPR_TYPE_ERROR 0xff
+#define INIT_EXPR_TYPE_ANY_CONVERT_EXTERN 0xD9
+#define INIT_EXPR_TYPE_EXTERN_CONVERT_ANY 0xDA
 
 #define WASM_MAGIC_NUMBER 0x6d736100
 #define WASM_CURRENT_VERSION 1
@@ -174,6 +172,10 @@ typedef void *table_elem_type_t;
 #define WASM_TYPE_STRINGVIEWITER 6
 #endif
 
+/* In WasmGC, a table can start with [0x40 0x00] to indicate it has an
+ * initializer */
+#define TABLE_INIT_EXPR_FLAG 0x40
+
 typedef struct WASMModule WASMModule;
 typedef struct WASMFunction WASMFunction;
 typedef struct WASMGlobal WASMGlobal;
@@ -205,11 +207,23 @@ typedef union WASMValue {
     struct {
         uint32 type_index;
         uint32 N;
-    } array_new_canon_fixed;
+    } array_new_default;
 #endif
 } WASMValue;
 #endif /* end of WASM_VALUE_DEFINED */
 
+typedef struct WASMStructNewInitValues {
+    uint8 type_idx;
+    uint32 count;
+    WASMValue fields[1];
+} WASMStructNewInitValues;
+
+typedef struct WASMArrayNewInitValues {
+    uint8 type_idx;
+    uint32 length;
+    WASMValue elem_data[1];
+} WASMArrayNewInitValues;
+
 typedef struct InitializerExpression {
     /* type of INIT_EXPR_TYPE_XXX, which is an instruction of
        constant expression */
@@ -295,6 +309,11 @@ typedef struct WASMType {
     /* The parent type */
     struct WASMType *parent_type;
     uint32 parent_type_idx;
+
+    /* number of internal types in the current rec group, if the type is not in
+     * a recursive group, rec_count = 0 */
+    uint16 rec_count;
+    uint16 rec_idx;
 } WASMType, *WASMTypePtr;
 #endif /* end of WASM_ENABLE_GC */
 
@@ -430,6 +449,8 @@ typedef struct WASMTable {
     uint32 max_size;
 #if WASM_ENABLE_GC != 0
     WASMRefType *elem_ref_type;
+    /* init expr for the whole table */
+    InitializerExpression init_expr;
 #endif
 } WASMTable;
 
@@ -630,8 +651,8 @@ typedef struct WASMTableSeg {
     /* optional, only for active */
     uint32 table_index;
     InitializerExpression base_offset;
-    uint32 function_count;
-    uintptr_t *func_indexes;
+    uint32 value_count;
+    InitializerExpression *init_values;
 } WASMTableSeg;
 
 typedef struct WASMDataSeg {
@@ -1054,13 +1075,17 @@ wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size)
              || value_type == VALUE_TYPE_EXTERNREF)
         return sizeof(uint32);
 #elif WASM_ENABLE_GC != 0
-    else if (
+    else if ((value_type >= (uint8)REF_TYPE_ARRAYREF               /* 0x6A */
+              && value_type <= (uint8)REF_TYPE_NULLFUNCREF)        /* 0x73 */
+             || (value_type >= (uint8)REF_TYPE_HT_NULLABLE         /* 0x63 */
+                 && value_type <= (uint8)REF_TYPE_HT_NON_NULLABLE) /* 0x64 */
 #if WASM_ENABLE_STRINGREF != 0
-        value_type >= (uint8)REF_TYPE_STRINGVIEWITER /* 0x61 */
-#else
-        value_type >= (uint8)REF_TYPE_NULLREF /* 0x65 */
+             || (value_type >= (uint8)REF_TYPE_STRINGVIEWWTF8      /* 0x66 */
+                 && value_type <= (uint8)REF_TYPE_STRINGREF)       /* 0x67 */
+             || (value_type >= (uint8)REF_TYPE_STRINGVIEWITER      /* 0x61 */
+                 && value_type <= (uint8)REF_TYPE_STRINGVIEWWTF16) /* 0x62 */
 #endif
-        && value_type <= (uint8)REF_TYPE_FUNCREF /* 0x70 */)
+    )
         return pointer_size;
 #endif
     else {

+ 129 - 76
core/iwasm/interpreter/wasm_interp_classic.c

@@ -2065,8 +2065,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 opcode = (uint8)opcode1;
 
                 switch (opcode) {
-                    case WASM_OP_STRUCT_NEW_CANON:
-                    case WASM_OP_STRUCT_NEW_CANON_DEFAULT:
+                    case WASM_OP_STRUCT_NEW:
+                    case WASM_OP_STRUCT_NEW_DEFAULT:
                     {
                         WASMModule *wasm_module = module->module;
                         WASMStructType *struct_type;
@@ -2095,7 +2095,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                         }
 
-                        if (opcode == WASM_OP_STRUCT_NEW_CANON) {
+                        if (opcode == WASM_OP_STRUCT_NEW) {
                             WASMStructFieldType *fields = struct_type->fields;
                             int32 field_count = (int32)struct_type->field_count;
                             int32 field_idx;
@@ -2205,9 +2205,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         HANDLE_OP_END();
                     }
 
-                    case WASM_OP_ARRAY_NEW_CANON:
-                    case WASM_OP_ARRAY_NEW_CANON_DEFAULT:
-                    case WASM_OP_ARRAY_NEW_CANON_FIXED:
+                    case WASM_OP_ARRAY_NEW:
+                    case WASM_OP_ARRAY_NEW_DEFAULT:
+                    case WASM_OP_ARRAY_NEW_FIXED:
                     {
                         WASMModule *wasm_module = module->module;
                         WASMArrayType *array_type;
@@ -2229,12 +2229,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                         }
 
-                        if (opcode != WASM_OP_ARRAY_NEW_CANON_FIXED)
+                        if (opcode != WASM_OP_ARRAY_NEW_FIXED)
                             array_len = POP_I32();
                         else
                             read_leb_uint32(frame_ip, frame_ip_end, array_len);
 
-                        if (opcode == WASM_OP_ARRAY_NEW_CANON) {
+                        if (opcode == WASM_OP_ARRAY_NEW) {
                             if (wasm_is_type_reftype(array_type->elem_type)) {
                                 array_elem.gc_obj = POP_REF();
                             }
@@ -2259,7 +2259,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                         }
 
-                        if (opcode == WASM_OP_ARRAY_NEW_CANON_FIXED) {
+                        if (opcode == WASM_OP_ARRAY_NEW_FIXED) {
                             for (i = 0; i < array_len; i++) {
                                 if (wasm_is_type_reftype(
                                         array_type->elem_type)) {
@@ -2285,7 +2285,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         PUSH_REF(array_obj);
                         HANDLE_OP_END();
                     }
-                    case WASM_OP_ARRAY_NEW_CANON_DATA:
+                    case WASM_OP_ARRAY_NEW_DATA:
                     {
                         WASMModule *wasm_module = module->module;
                         WASMArrayType *array_type;
@@ -2363,7 +2363,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         PUSH_REF(array_obj);
                         HANDLE_OP_END();
                     }
-                    case WASM_OP_ARRAY_NEW_CANON_ELEM:
+                    case WASM_OP_ARRAY_NEW_ELEM:
                     {
                         /* TODO */
                         wasm_set_exception(module, "unsupported opcode");
@@ -2385,12 +2385,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         array_obj = POP_REF();
 
                         if (!array_obj) {
-                            wasm_set_exception(module, "null array object");
+                            wasm_set_exception(module, "null array reference");
                             goto got_exception;
                         }
                         if (elem_idx >= wasm_array_obj_length(array_obj)) {
                             wasm_set_exception(module,
-                                               "array index out of bounds");
+                                               "out of bounds array access");
                             goto got_exception;
                         }
 
@@ -2440,12 +2440,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         array_obj = POP_REF();
 
                         if (!array_obj) {
-                            wasm_set_exception(module, "null array object");
+                            wasm_set_exception(module, "null array reference");
                             goto got_exception;
                         }
                         if (elem_idx >= wasm_array_obj_length(array_obj)) {
                             wasm_set_exception(module,
-                                               "array index out of bounds");
+                                               "out of bounds array access");
                             goto got_exception;
                         }
 
@@ -2453,7 +2453,64 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                                 &array_elem);
                         HANDLE_OP_END();
                     }
-#if WASM_ENABLE_GC_BINARYEN != 0
+                    case WASM_OP_ARRAY_LEN:
+                    {
+                        uint32 array_len;
+
+                        array_obj = POP_REF();
+                        if (!array_obj) {
+                            wasm_set_exception(module, "null array reference");
+                            goto got_exception;
+                        }
+                        array_len = wasm_array_obj_length(array_obj);
+                        PUSH_I32(array_len);
+                        HANDLE_OP_END();
+                    }
+                    case WASM_OP_ARRAY_FILL:
+                    {
+                        WASMArrayType *array_type;
+                        WASMValue fill_value = { 0 };
+                        uint32 start_offset, len;
+                        read_leb_uint32(frame_ip, frame_ip_end, type_index);
+
+                        array_type =
+                            (WASMArrayType *)module->module->types[type_index];
+
+                        len = POP_I32();
+                        if (wasm_is_type_reftype(array_type->elem_type)) {
+                            fill_value.gc_obj = POP_REF();
+                        }
+                        else if (array_type->elem_type == VALUE_TYPE_I32
+                                 || array_type->elem_type == VALUE_TYPE_F32
+                                 || array_type->elem_type == PACKED_TYPE_I8
+                                 || array_type->elem_type == PACKED_TYPE_I16) {
+                            fill_value.i32 = POP_I32();
+                        }
+                        else {
+                            fill_value.i64 = POP_I64();
+                        }
+                        start_offset = POP_I32();
+                        array_obj = POP_REF();
+
+                        if (!array_obj) {
+                            wasm_set_exception(module, "null array reference");
+                            goto got_exception;
+                        }
+
+                        if (len > 0) {
+                            if ((uint64)start_offset + len
+                                >= wasm_array_obj_length(array_obj)) {
+                                wasm_set_exception(
+                                    module, "out of bounds array access");
+                                goto got_exception;
+                            }
+
+                            wasm_array_obj_fill(array_obj, start_offset, len,
+                                                &fill_value);
+                        }
+
+                        HANDLE_OP_END();
+                    }
                     case WASM_OP_ARRAY_COPY:
                     {
                         uint32 dst_offset, src_offset, len, src_type_index;
@@ -2469,7 +2526,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         dst_obj = POP_REF();
 
                         if (!src_obj || !dst_obj) {
-                            wasm_set_exception(module, "null array object");
+                            wasm_set_exception(module, "null array reference");
                             goto got_exception;
                         }
 
@@ -2480,8 +2537,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                 || (src_offset > UINT32_MAX - len)
                                 || (src_offset + len
                                     > wasm_array_obj_length(src_obj))) {
-                                wasm_set_exception(module,
-                                                   "array index out of bounds");
+                                wasm_set_exception(
+                                    module, "out of bounds array access");
                                 goto got_exception;
                             }
 
@@ -2492,22 +2549,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         (void)src_type_index;
                         HANDLE_OP_END();
                     }
-#endif
-                    case WASM_OP_ARRAY_LEN:
-                    {
-                        uint32 array_len;
-
-                        array_obj = POP_REF();
-                        if (!array_obj) {
-                            wasm_set_exception(module, "null array object");
-                            goto got_exception;
-                        }
-                        array_len = wasm_array_obj_length(array_obj);
-                        PUSH_I32(array_len);
-                        HANDLE_OP_END();
-                    }
 
-                    case WASM_OP_I31_NEW:
+                    case WASM_OP_REF_I31:
                     {
                         uint32 i31_val;
 
@@ -2595,52 +2638,65 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                     case WASM_OP_BR_ON_CAST:
                     case WASM_OP_BR_ON_CAST_FAIL:
-                    case WASM_OP_BR_ON_CAST_NULLABLE:
-                    case WASM_OP_BR_ON_CAST_FAIL_NULLABLE:
                     {
-                        int32 heap_type;
+                        int32 heap_type, heap_type_dst;
+                        uint8 castflags;
 
 #if WASM_ENABLE_THREAD_MGR != 0
                         CHECK_SUSPEND_FLAGS();
 #endif
+                        castflags = *frame_ip++;
                         read_leb_uint32(frame_ip, frame_ip_end, depth);
                         read_leb_int32(frame_ip, frame_ip_end, heap_type);
+                        read_leb_int32(frame_ip, frame_ip_end, heap_type_dst);
 
                         gc_obj = GET_REF_FROM_ADDR(frame_sp - REF_CELL_NUM);
                         if (!gc_obj) {
-                            if (opcode == WASM_OP_BR_ON_CAST_NULLABLE
-                                || opcode == WASM_OP_BR_ON_CAST_FAIL)
+                            /*
+                             * castflags should be 0~3:
+                             *  0: (non-null, non-null)
+                             *  1: (null, non-null)
+                             *  2: (non-null, null)
+                             *  3: (null, null)
+                             */
+                            if (
+                                /* op is BR_ON_CAST and dst reftype is nullable
+                                 */
+                                ((opcode1 == WASM_OP_BR_ON_CAST)
+                                 && ((castflags == 2) || (castflags == 3)))
+                                /* op is BR_ON_CAST_FAIL and dst reftype is
+                                   non-nullable */
+                                || ((opcode1 == WASM_OP_BR_ON_CAST_FAIL)
+                                    && ((castflags == 0) || (castflags == 1))))
                                 goto label_pop_csp_n;
                         }
                         else {
                             bool castable = false;
 
-                            if (heap_type >= 0) {
+                            if (heap_type_dst >= 0) {
                                 WASMModule *wasm_module = module->module;
                                 castable = wasm_obj_is_instance_of(
-                                    gc_obj, (uint32)heap_type,
+                                    gc_obj, (uint32)heap_type_dst,
                                     wasm_module->types,
                                     wasm_module->type_count);
                             }
                             else {
                                 castable =
-                                    wasm_obj_is_type_of(gc_obj, heap_type);
+                                    wasm_obj_is_type_of(gc_obj, heap_type_dst);
                             }
 
-                            if ((castable
-                                 && (opcode == WASM_OP_BR_ON_CAST
-                                     || opcode == WASM_OP_BR_ON_CAST_NULLABLE))
+                            if ((castable && (opcode == WASM_OP_BR_ON_CAST))
                                 || (!castable
-                                    && (opcode == WASM_OP_BR_ON_CAST_FAIL
-                                        || opcode
-                                               == WASM_OP_BR_ON_CAST_FAIL_NULLABLE))) {
+                                    && (opcode == WASM_OP_BR_ON_CAST_FAIL))) {
                                 goto label_pop_csp_n;
                             }
                         }
+
+                        (void)heap_type;
                         HANDLE_OP_END();
                     }
 
-                    case WASM_OP_EXTERN_INTERNALIZE:
+                    case WASM_OP_ANY_CONVERT_EXTERN:
                     {
                         externref_obj = POP_REF();
                         if (externref_obj == NULL_REF)
@@ -2652,7 +2708,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         }
                         HANDLE_OP_END();
                     }
-                    case WASM_OP_EXTERN_EXTERNALIZE:
+                    case WASM_OP_EXTERN_CONVERT_ANY:
                     {
                         gc_obj = POP_REF();
                         if (gc_obj == NULL_REF)
@@ -3262,7 +3318,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                         if (start > end || end > array_len) {
                             wasm_set_exception(module,
-                                               "array index out of bounds");
+                                               "out of bounds array access");
                             goto got_exception;
                         }
 
@@ -3338,7 +3394,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                         if (start > array_len) {
                             wasm_set_exception(module,
-                                               "array index out of bounds");
+                                               "out of bounds array access");
                             goto got_exception;
                         }
 
@@ -5045,10 +5101,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         uint32 tbl_idx, elem_idx;
                         uint32 n, s, d;
                         WASMTableInstance *tbl_inst;
-#if WASM_ENABLE_GC != 0
-                        void **table_elems;
-                        uintptr_t *func_indexes;
-#endif
+                        table_elem_type_t *table_elems;
+                        InitializerExpression *init_values;
 
                         read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
                         bh_assert(elem_idx < module->module->table_seg_count);
@@ -5065,7 +5119,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (offset_len_out_of_bounds(
                                 s, n,
                                 module->module->table_segments[elem_idx]
-                                    .function_count)
+                                    .value_count)
                             || offset_len_out_of_bounds(d, n,
                                                         tbl_inst->cur_size)) {
                             wasm_set_exception(module,
@@ -5092,28 +5146,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                         }
 
-#if WASM_ENABLE_GC == 0
-                        bh_memcpy_s((uint8 *)tbl_inst
-                                        + offsetof(WASMTableInstance, elems)
-                                        + d * sizeof(table_elem_type_t),
-                                    (uint32)((tbl_inst->cur_size - d)
-                                             * sizeof(table_elem_type_t)),
-                                    module->module->table_segments[elem_idx]
-                                            .func_indexes
-                                        + s,
-                                    (uint32)(n * sizeof(table_elem_type_t)));
-#else
-                        SYNC_ALL_TO_FRAME();
                         table_elems = tbl_inst->elems + d;
-                        func_indexes = module->module->table_segments[elem_idx]
-                                           .func_indexes
-                                       + s;
+                        init_values =
+                            module->module->table_segments[elem_idx].init_values
+                            + s;
+#if WASM_ENABLE_GC != 0
+                        SYNC_ALL_TO_FRAME();
+#endif
                         for (i = 0; i < n; i++) {
                             /* UINT32_MAX indicates that it is an null ref */
-                            if (func_indexes[i] != UINT32_MAX) {
+                            bh_assert(init_values[i].init_expr_type
+                                          == INIT_EXPR_TYPE_REFNULL_CONST
+                                      || init_values[i].init_expr_type
+                                             == INIT_EXPR_TYPE_FUNCREF_CONST);
+#if WASM_ENABLE_GC == 0
+                            table_elems[i] =
+                                (table_elem_type_t)init_values[i].u.ref_index;
+#else
+                            if (init_values[i].u.ref_index != UINT32_MAX) {
                                 if (!(func_obj = wasm_create_func_obj(
-                                          module, func_indexes[i], true, NULL,
-                                          0))) {
+                                          module, init_values[i].u.ref_index,
+                                          true, NULL, 0))) {
                                     goto got_exception;
                                 }
                                 table_elems[i] = func_obj;
@@ -5121,8 +5174,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             else {
                                 table_elems[i] = NULL_REF;
                             }
-                        }
 #endif
+                        }
                         break;
                     }
                     case WASM_OP_ELEM_DROP:

+ 131 - 75
core/iwasm/interpreter/wasm_interp_fast.c

@@ -1996,8 +1996,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 GET_OPCODE();
 
                 switch (opcode) {
-                    case WASM_OP_STRUCT_NEW_CANON:
-                    case WASM_OP_STRUCT_NEW_CANON_DEFAULT:
+                    case WASM_OP_STRUCT_NEW:
+                    case WASM_OP_STRUCT_NEW_DEFAULT:
                     {
                         WASMModule *wasm_module = module->module;
                         WASMStructType *struct_type;
@@ -2026,7 +2026,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                         }
 
-                        if (opcode == WASM_OP_STRUCT_NEW_CANON) {
+                        if (opcode == WASM_OP_STRUCT_NEW) {
                             WASMStructFieldType *fields = struct_type->fields;
                             int32 field_count = (int32)struct_type->field_count;
                             int32 field_idx;
@@ -2136,9 +2136,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                                   &field_value);
                         HANDLE_OP_END();
                     }
-                    case WASM_OP_ARRAY_NEW_CANON:
-                    case WASM_OP_ARRAY_NEW_CANON_DEFAULT:
-                    case WASM_OP_ARRAY_NEW_CANON_FIXED:
+                    case WASM_OP_ARRAY_NEW:
+                    case WASM_OP_ARRAY_NEW_DEFAULT:
+                    case WASM_OP_ARRAY_NEW_FIXED:
                     {
                         WASMModule *wasm_module = module->module;
                         WASMArrayType *array_type;
@@ -2160,12 +2160,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                         }
 
-                        if (opcode != WASM_OP_ARRAY_NEW_CANON_FIXED)
+                        if (opcode != WASM_OP_ARRAY_NEW_FIXED)
                             array_len = POP_I32();
                         else
                             array_len = read_uint32(frame_ip);
 
-                        if (opcode == WASM_OP_ARRAY_NEW_CANON) {
+                        if (opcode == WASM_OP_ARRAY_NEW) {
                             if (wasm_is_type_reftype(array_type->elem_type)) {
                                 array_elem.gc_obj = POP_REF();
                             }
@@ -2190,7 +2190,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                         }
 
-                        if (opcode == WASM_OP_ARRAY_NEW_CANON_FIXED) {
+                        if (opcode == WASM_OP_ARRAY_NEW_FIXED) {
                             for (i = 0; i < array_len; i++) {
                                 if (wasm_is_type_reftype(
                                         array_type->elem_type)) {
@@ -2216,7 +2216,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         PUSH_REF(array_obj);
                         HANDLE_OP_END();
                     }
-                    case WASM_OP_ARRAY_NEW_CANON_DATA:
+                    case WASM_OP_ARRAY_NEW_DATA:
                     {
                         WASMModule *wasm_module = module->module;
                         WASMArrayType *array_type;
@@ -2294,7 +2294,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         PUSH_REF(array_obj);
                         HANDLE_OP_END();
                     }
-                    case WASM_OP_ARRAY_NEW_CANON_ELEM:
+                    case WASM_OP_ARRAY_NEW_ELEM:
                     {
                         /* TODO */
                         wasm_set_exception(module, "unsupported opcode");
@@ -2316,12 +2316,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         array_obj = POP_REF();
 
                         if (!array_obj) {
-                            wasm_set_exception(module, "null array object");
+                            wasm_set_exception(module, "null array reference");
                             goto got_exception;
                         }
                         if (elem_idx >= wasm_array_obj_length(array_obj)) {
                             wasm_set_exception(module,
-                                               "array index out of bounds");
+                                               "out of bounds array access");
                             goto got_exception;
                         }
 
@@ -2371,12 +2371,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         array_obj = POP_REF();
 
                         if (!array_obj) {
-                            wasm_set_exception(module, "null array object");
+                            wasm_set_exception(module, "null array reference");
                             goto got_exception;
                         }
                         if (elem_idx >= wasm_array_obj_length(array_obj)) {
                             wasm_set_exception(module,
-                                               "array index out of bounds");
+                                               "out of bounds array access");
                             goto got_exception;
                         }
 
@@ -2384,7 +2384,64 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                                 &array_elem);
                         HANDLE_OP_END();
                     }
-#if WASM_ENABLE_GC_BINARYEN != 0
+                    case WASM_OP_ARRAY_LEN:
+                    {
+                        uint32 array_len;
+                        array_obj = POP_REF();
+                        if (!array_obj) {
+                            wasm_set_exception(module, "null array reference");
+                            goto got_exception;
+                        }
+                        array_len = wasm_array_obj_length(array_obj);
+                        PUSH_I32(array_len);
+                        HANDLE_OP_END();
+                    }
+                    case WASM_OP_ARRAY_FILL:
+                    {
+                        WASMArrayType *array_type;
+                        WASMValue fill_value = { 0 };
+                        uint32 start_offset, len;
+
+                        type_idx = read_uint32(frame_ip);
+
+                        array_type =
+                            (WASMArrayType *)module->module->types[type_idx];
+
+                        len = POP_I32();
+                        if (wasm_is_type_reftype(array_type->elem_type)) {
+                            fill_value.gc_obj = POP_REF();
+                        }
+                        else if (array_type->elem_type == VALUE_TYPE_I32
+                                 || array_type->elem_type == VALUE_TYPE_F32
+                                 || array_type->elem_type == PACKED_TYPE_I8
+                                 || array_type->elem_type == PACKED_TYPE_I16) {
+                            fill_value.i32 = POP_I32();
+                        }
+                        else {
+                            fill_value.i64 = POP_I64();
+                        }
+                        start_offset = POP_I32();
+                        array_obj = POP_REF();
+
+                        if (!array_obj) {
+                            wasm_set_exception(module, "null array reference");
+                            goto got_exception;
+                        }
+
+                        if (len > 0) {
+                            if ((uint64)start_offset + len
+                                >= wasm_array_obj_length(array_obj)) {
+                                wasm_set_exception(
+                                    module, "out of bounds array access");
+                                goto got_exception;
+                            }
+
+                            wasm_array_obj_fill(array_obj, start_offset, len,
+                                                &fill_value);
+                        }
+
+                        HANDLE_OP_END();
+                    }
                     case WASM_OP_ARRAY_COPY:
                     {
                         uint32 dst_offset, src_offset, len, src_type_index;
@@ -2400,7 +2457,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         dst_obj = POP_REF();
 
                         if (!src_obj || !dst_obj) {
-                            wasm_set_exception(module, "null array object");
+                            wasm_set_exception(module, "null array reference");
                             goto got_exception;
                         }
 
@@ -2411,8 +2468,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                 || (src_offset > UINT32_MAX - len)
                                 || (src_offset + len
                                     > wasm_array_obj_length(src_obj))) {
-                                wasm_set_exception(module,
-                                                   "array index out of bounds");
+                                wasm_set_exception(
+                                    module, "out of bounds array access");
                                 goto got_exception;
                             }
 
@@ -2423,21 +2480,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         (void)src_type_index;
                         HANDLE_OP_END();
                     }
-#endif
-                    case WASM_OP_ARRAY_LEN:
-                    {
-                        uint32 array_len;
-                        array_obj = POP_REF();
-                        if (!array_obj) {
-                            wasm_set_exception(module, "null array object");
-                            goto got_exception;
-                        }
-                        array_len = wasm_array_obj_length(array_obj);
-                        PUSH_I32(array_len);
-                        HANDLE_OP_END();
-                    }
 
-                    case WASM_OP_I31_NEW:
+                    case WASM_OP_REF_I31:
                     {
                         uint32 i31_val;
 
@@ -2525,17 +2569,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     }
 
                     case WASM_OP_BR_ON_CAST:
-                    case WASM_OP_BR_ON_CAST_NULLABLE:
                     case WASM_OP_BR_ON_CAST_FAIL:
-                    case WASM_OP_BR_ON_CAST_FAIL_NULLABLE:
                     {
-                        int32 heap_type;
+                        int32 heap_type, heap_type_dst;
+                        uint8 castflags;
                         uint16 opnd_off_br;
 
 #if WASM_ENABLE_THREAD_MGR != 0
                         CHECK_SUSPEND_FLAGS();
 #endif
+                        castflags = *frame_ip++;
                         heap_type = (int32)read_uint32(frame_ip);
+                        heap_type_dst = (int32)read_uint32(frame_ip);
 
                         opnd_off = GET_OFFSET();
                         opnd_off_br = GET_OFFSET();
@@ -2543,8 +2588,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         PUT_REF_TO_ADDR(frame_lp + opnd_off_br, gc_obj);
 
                         if (!gc_obj) {
-                            if (opcode == WASM_OP_BR_ON_CAST_NULLABLE
-                                || opcode == WASM_OP_BR_ON_CAST_FAIL) {
+                            /*
+                             * castflags should be 0~3:
+                             *  0: (non-null, non-null)
+                             *  1: (null, non-null)
+                             *  2: (non-null, null)
+                             *  3: (null, null)
+                             */
+                            if (
+                                /* op is BR_ON_CAST and dst reftype is nullable
+                                 */
+                                ((opcode == WASM_OP_BR_ON_CAST)
+                                 && ((castflags == 2) || (castflags == 3)))
+                                /* op is BR_ON_CAST_FAIL and dst reftype is
+                                   non-nullable */
+                                || ((opcode == WASM_OP_BR_ON_CAST_FAIL)
+                                    && ((castflags == 0)
+                                        || (castflags == 1)))) {
                                 CLEAR_FRAME_REF(opnd_off);
                                 if (!wasm_is_reftype_i31ref(heap_type)) {
                                     SET_FRAME_REF(opnd_off_br);
@@ -2555,25 +2615,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         else {
                             bool castable = false;
 
-                            if (heap_type >= 0) {
+                            if (heap_type_dst >= 0) {
                                 WASMModule *wasm_module = module->module;
                                 castable = wasm_obj_is_instance_of(
-                                    gc_obj, (uint32)heap_type,
+                                    gc_obj, (uint32)heap_type_dst,
                                     wasm_module->types,
                                     wasm_module->type_count);
                             }
                             else {
                                 castable =
-                                    wasm_obj_is_type_of(gc_obj, heap_type);
+                                    wasm_obj_is_type_of(gc_obj, heap_type_dst);
                             }
 
-                            if ((castable
-                                 && (opcode == WASM_OP_BR_ON_CAST
-                                     || opcode == WASM_OP_BR_ON_CAST_NULLABLE))
+                            if ((castable && (opcode == WASM_OP_BR_ON_CAST))
                                 || (!castable
-                                    && (opcode == WASM_OP_BR_ON_CAST_FAIL
-                                        || opcode
-                                               == WASM_OP_BR_ON_CAST_FAIL_NULLABLE))) {
+                                    && (opcode == WASM_OP_BR_ON_CAST_FAIL))) {
                                 CLEAR_FRAME_REF(opnd_off);
                                 if (!wasm_is_reftype_i31ref(heap_type)) {
                                     SET_FRAME_REF(opnd_off_br);
@@ -2582,10 +2638,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             }
                         }
                         SKIP_BR_INFO();
+
+                        (void)heap_type_dst;
                         HANDLE_OP_END();
                     }
 
-                    case WASM_OP_EXTERN_INTERNALIZE:
+                    case WASM_OP_ANY_CONVERT_EXTERN:
                     {
                         externref_obj = POP_REF();
                         if (externref_obj == NULL_REF)
@@ -2597,7 +2655,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         }
                         HANDLE_OP_END();
                     }
-                    case WASM_OP_EXTERN_EXTERNALIZE:
+                    case WASM_OP_EXTERN_CONVERT_ANY:
                     {
                         gc_obj = POP_REF();
                         if (gc_obj == NULL_REF)
@@ -3203,7 +3261,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                         if (start > end || end > array_len) {
                             wasm_set_exception(module,
-                                               "array index out of bounds");
+                                               "out of bounds array access");
                             goto got_exception;
                         }
 
@@ -3279,7 +3337,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                         if (start > array_len) {
                             wasm_set_exception(module,
-                                               "array index out of bounds");
+                                               "out of bounds array access");
                             goto got_exception;
                         }
 
@@ -4977,11 +5035,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         uint32 tbl_idx, elem_idx;
                         uint32 n, s, d;
                         WASMTableInstance *tbl_inst;
-#if WASM_ENABLE_GC != 0
-                        void **table_elems;
-                        uintptr_t *func_indexes;
+                        table_elem_type_t *table_elems;
+                        InitializerExpression *init_values;
                         uint64 i;
-#endif
 
                         elem_idx = read_uint32(frame_ip);
                         bh_assert(elem_idx < module->module->table_seg_count);
@@ -4998,7 +5054,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (offset_len_out_of_bounds(
                                 s, n,
                                 module->module->table_segments[elem_idx]
-                                    .function_count)
+                                    .value_count)
                             || offset_len_out_of_bounds(d, n,
                                                         tbl_inst->cur_size)) {
                             wasm_set_exception(module,
@@ -5025,28 +5081,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                         }
 
-#if WASM_ENABLE_GC == 0
-                        bh_memcpy_s((uint8 *)tbl_inst
-                                        + offsetof(WASMTableInstance, elems)
-                                        + d * sizeof(table_elem_type_t),
-                                    (uint32)((tbl_inst->cur_size - d)
-                                             * sizeof(table_elem_type_t)),
-                                    module->module->table_segments[elem_idx]
-                                            .func_indexes
-                                        + s,
-                                    (uint32)(n * sizeof(table_elem_type_t)));
-#else
-                        SYNC_ALL_TO_FRAME();
                         table_elems = tbl_inst->elems + d;
-                        func_indexes = module->module->table_segments[elem_idx]
-                                           .func_indexes
-                                       + s;
+                        init_values =
+                            module->module->table_segments[elem_idx].init_values
+                            + s;
+#if WASM_ENABLE_GC != 0
+                        SYNC_ALL_TO_FRAME();
+#endif
                         for (i = 0; i < n; i++) {
                             /* UINT32_MAX indicates that it is an null ref */
-                            if (func_indexes[i] != UINT32_MAX) {
+                            bh_assert(init_values[i].init_expr_type
+                                          == INIT_EXPR_TYPE_REFNULL_CONST
+                                      || init_values[i].init_expr_type
+                                             == INIT_EXPR_TYPE_FUNCREF_CONST);
+#if WASM_ENABLE_GC == 0
+                            table_elems[i] =
+                                (table_elem_type_t)init_values[i].u.ref_index;
+#else
+                            if (init_values[i].u.ref_index != UINT32_MAX) {
                                 if (!(func_obj = wasm_create_func_obj(
-                                          module, func_indexes[i], true, NULL,
-                                          0))) {
+                                          module, init_values[i].u.ref_index,
+                                          true, NULL, 0))) {
                                     goto got_exception;
                                 }
                                 table_elems[i] = func_obj;
@@ -5054,8 +5109,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             else {
                                 table_elems[i] = NULL_REF;
                             }
-                        }
 #endif
+                        }
+
                         break;
                     }
                     case WASM_OP_ELEM_DROP:

Разница между файлами не показана из-за своего большого размера
+ 767 - 246
core/iwasm/interpreter/wasm_loader.c


+ 364 - 145
core/iwasm/interpreter/wasm_mini_loader.c

@@ -194,6 +194,29 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
     return mem;
 }
 
+static void *
+memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
+               uint32 error_buf_size)
+{
+    uint8 *mem_new;
+    bh_assert(size_new > size_old);
+    if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
+        bh_memcpy_s(mem_new, size_new, mem_old, size_old);
+        memset(mem_new + size_old, 0, size_new - size_old);
+        wasm_runtime_free(mem_old);
+    }
+    return mem_new;
+}
+
+#define MEM_REALLOC(mem, size_old, size_new)                               \
+    do {                                                                   \
+        void *mem_new = memory_realloc(mem, size_old, size_new, error_buf, \
+                                       error_buf_size);                    \
+        if (!mem_new)                                                      \
+            goto fail;                                                     \
+        mem = mem_new;                                                     \
+    } while (0)
+
 static char *
 const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
                       bool is_load_from_file_buf, char *error_buf,
@@ -271,80 +294,256 @@ destroy_wasm_type(WASMFuncType *type)
 }
 
 static bool
-load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
+check_function_index(const WASMModule *module, uint32 function_index,
+                     char *error_buf, uint32 error_buf_size)
+{
+    return (function_index
+            < module->import_function_count + module->function_count);
+}
+
+typedef struct InitValue {
+    uint8 type;
+    uint8 flag;
+    WASMValue value;
+} InitValue;
+
+typedef struct ConstExprContext {
+    uint32 sp;
+    uint32 size;
+    WASMModule *module;
+    InitValue *stack;
+    InitValue data[WASM_CONST_EXPR_STACK_SIZE];
+} ConstExprContext;
+
+static void
+init_const_expr_stack(ConstExprContext *ctx, WASMModule *module)
+{
+    ctx->sp = 0;
+    ctx->module = module;
+    ctx->stack = ctx->data;
+    ctx->size = WASM_CONST_EXPR_STACK_SIZE;
+}
+
+static bool
+push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
+                      WASMValue *value, char *error_buf, uint32 error_buf_size)
+{
+    InitValue *cur_value;
+
+    if (ctx->sp >= ctx->size) {
+        if (ctx->stack != ctx->data) {
+            MEM_REALLOC(ctx->stack, ctx->size * sizeof(InitValue),
+                        (ctx->size + 4) * sizeof(InitValue));
+        }
+        else {
+            if (!(ctx->stack =
+                      loader_malloc((ctx->size + 4) * (uint64)sizeof(InitValue),
+                                    error_buf, error_buf_size))) {
+                return false;
+            }
+        }
+        ctx->size += 4;
+    }
+
+    cur_value = &ctx->stack[ctx->sp++];
+    cur_value->type = type;
+    cur_value->flag = flag;
+    cur_value->value = *value;
+
+    return true;
+fail:
+    return false;
+}
+
+static bool
+pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
+                     WASMValue *p_value, char *error_buf, uint32 error_buf_size)
+{
+    InitValue *cur_value;
+
+    if (ctx->sp == 0) {
+        return false;
+    }
+
+    cur_value = &ctx->stack[--ctx->sp];
+
+    if (cur_value->type != type) {
+        return false;
+    }
+
+    if (p_flag)
+        *p_flag = cur_value->flag;
+    if (p_value)
+        *p_value = cur_value->value;
+
+    return true;
+}
+
+static void
+destroy_const_expr_stack(ConstExprContext *ctx)
+{
+    if (ctx->stack != ctx->data) {
+        wasm_runtime_free(ctx->stack);
+    }
+}
+
+static bool
+load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
                InitializerExpression *init_expr, uint8 type, char *error_buf,
                uint32 error_buf_size)
 {
     const uint8 *p = *p_buf, *p_end = buf_end;
-    uint8 flag, end_byte, *p_float;
+    uint8 flag, *p_float;
     uint32 i;
+    ConstExprContext const_expr_ctx = { 0 };
+    WASMValue cur_value = { 0 };
+
+    init_const_expr_stack(&const_expr_ctx, module);
 
     CHECK_BUF(p, p_end, 1);
-    init_expr->init_expr_type = read_uint8(p);
-    flag = init_expr->init_expr_type;
-
-    switch (flag) {
-        /* i32.const */
-        case INIT_EXPR_TYPE_I32_CONST:
-            bh_assert(type == VALUE_TYPE_I32);
-            read_leb_int32(p, p_end, init_expr->u.i32);
-            break;
-        /* i64.const */
-        case INIT_EXPR_TYPE_I64_CONST:
-            bh_assert(type == VALUE_TYPE_I64);
-            read_leb_int64(p, p_end, init_expr->u.i64);
-            break;
-        /* f32.const */
-        case INIT_EXPR_TYPE_F32_CONST:
-            bh_assert(type == VALUE_TYPE_F32);
-            CHECK_BUF(p, p_end, 4);
-            p_float = (uint8 *)&init_expr->u.f32;
-            for (i = 0; i < sizeof(float32); i++)
-                *p_float++ = *p++;
-            break;
-        /* f64.const */
-        case INIT_EXPR_TYPE_F64_CONST:
-            bh_assert(type == VALUE_TYPE_F64);
-            CHECK_BUF(p, p_end, 8);
-            p_float = (uint8 *)&init_expr->u.f64;
-            for (i = 0; i < sizeof(float64); i++)
-                *p_float++ = *p++;
-            break;
+    flag = read_uint8(p);
+
+    while (flag != WASM_OP_END) {
+        switch (flag) {
+            /* i32.const */
+            case INIT_EXPR_TYPE_I32_CONST:
+                read_leb_int32(p, p_end, cur_value.i32);
+
+                if (!push_const_expr_stack(&const_expr_ctx, flag,
+                                           VALUE_TYPE_I32, &cur_value,
+                                           error_buf, error_buf_size)) {
+                    bh_assert(0);
+                }
+                break;
+            /* i64.const */
+            case INIT_EXPR_TYPE_I64_CONST:
+                read_leb_int64(p, p_end, cur_value.i64);
+
+                if (!push_const_expr_stack(&const_expr_ctx, flag,
+                                           VALUE_TYPE_I64, &cur_value,
+                                           error_buf, error_buf_size)) {
+                    bh_assert(0);
+                }
+                break;
+            /* f32.const */
+            case INIT_EXPR_TYPE_F32_CONST:
+                CHECK_BUF(p, p_end, 4);
+                p_float = (uint8 *)&cur_value.f32;
+                for (i = 0; i < sizeof(float32); i++)
+                    *p_float++ = *p++;
+
+                if (!push_const_expr_stack(&const_expr_ctx, flag,
+                                           VALUE_TYPE_F32, &cur_value,
+                                           error_buf, error_buf_size)) {
+                    bh_assert(0);
+                }
+                break;
+            /* f64.const */
+            case INIT_EXPR_TYPE_F64_CONST:
+                CHECK_BUF(p, p_end, 8);
+                p_float = (uint8 *)&cur_value.f64;
+                for (i = 0; i < sizeof(float64); i++)
+                    *p_float++ = *p++;
+
+                if (!push_const_expr_stack(&const_expr_ctx, flag,
+                                           VALUE_TYPE_F64, &cur_value,
+                                           error_buf, error_buf_size)) {
+                    bh_assert(0);
+                }
+                break;
+
 #if WASM_ENABLE_REF_TYPES != 0
-        case INIT_EXPR_TYPE_FUNCREF_CONST:
-        {
-            bh_assert(type == VALUE_TYPE_FUNCREF);
-            read_leb_uint32(p, p_end, init_expr->u.ref_index);
-            break;
-        }
-        case INIT_EXPR_TYPE_REFNULL_CONST:
-        {
-            uint8 reftype;
+            /* ref.func */
+            case INIT_EXPR_TYPE_FUNCREF_CONST:
+            {
+                uint32 func_idx;
+                read_leb_uint32(p, p_end, func_idx);
+                cur_value.ref_index = func_idx;
+                if (!check_function_index(module, func_idx, error_buf,
+                                          error_buf_size)) {
+                    bh_assert(0);
+                }
 
-            CHECK_BUF(p, p_end, 1);
-            reftype = read_uint8(p);
+                if (!push_const_expr_stack(&const_expr_ctx, flag,
+                                           VALUE_TYPE_FUNCREF, &cur_value,
+                                           error_buf, error_buf_size)) {
+                    bh_assert(0);
+                }
+                break;
+            }
 
-            bh_assert(type == reftype);
+            /* ref.null */
+            case INIT_EXPR_TYPE_REFNULL_CONST:
+            {
+                uint8 type1;
 
-            init_expr->u.ref_index = NULL_REF;
-            (void)reftype;
-            break;
+                CHECK_BUF(p, p_end, 1);
+                type1 = read_uint8(p);
+
+                cur_value.ref_index = UINT32_MAX;
+                if (!push_const_expr_stack(&const_expr_ctx, flag, type1,
+                                           &cur_value, error_buf,
+                                           error_buf_size)) {
+                    bh_assert(0);
+                }
+                break;
+            }
+#endif /* end of WASM_ENABLE_REF_TYPES != 0 */
+
+            /* get_global */
+            case INIT_EXPR_TYPE_GET_GLOBAL:
+            {
+                uint32 global_idx;
+                uint8 global_type;
+
+                read_leb_uint32(p, p_end, cur_value.global_index);
+                global_idx = cur_value.global_index;
+
+                bh_assert(global_idx < module->import_global_count);
+                bh_assert(
+                    !module->import_globals[global_idx].u.global.is_mutable);
+
+                if (global_idx < module->import_global_count) {
+                    global_type =
+                        module->import_globals[global_idx].u.global.type;
+                }
+                else {
+                    global_type =
+                        module
+                            ->globals[global_idx - module->import_global_count]
+                            .type;
+                }
+
+                if (!push_const_expr_stack(&const_expr_ctx, flag, global_type,
+                                           &cur_value, error_buf,
+                                           error_buf_size))
+                    bh_assert(0);
+
+                break;
+            }
+            default:
+            {
+                bh_assert(0);
+            }
         }
-#endif /* WASM_ENABLE_REF_TYPES != 0 */
-        /* get_global */
-        case INIT_EXPR_TYPE_GET_GLOBAL:
-            read_leb_uint32(p, p_end, init_expr->u.global_index);
-            break;
-        default:
-            bh_assert(0);
-            break;
+
+        CHECK_BUF(p, p_end, 1);
+        flag = read_uint8(p);
     }
-    CHECK_BUF(p, p_end, 1);
-    end_byte = read_uint8(p);
-    bh_assert(end_byte == 0x0b);
-    *p_buf = p;
 
-    (void)end_byte;
+    /* There should be only one value left on the init value stack */
+    if (!pop_const_expr_stack(&const_expr_ctx, &flag, type, &cur_value,
+                              error_buf, error_buf_size)) {
+        bh_assert(0);
+    }
+
+    bh_assert(const_expr_ctx.sp == 0);
+
+    init_expr->init_expr_type = flag;
+    init_expr->u = cur_value;
+
+    *p_buf = p;
+    destroy_const_expr_stack(&const_expr_ctx);
     return true;
 }
 
@@ -1062,14 +1261,6 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
     return true;
 }
 
-static bool
-check_function_index(const WASMModule *module, uint32 function_index,
-                     char *error_buf, uint32 error_buf_size)
-{
-    return (function_index
-            < module->import_function_count + module->function_count);
-}
-
 static bool
 load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                    char *error_buf, uint32 error_buf_size)
@@ -1148,8 +1339,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
     read_leb_uint32(p, p_end, global_count);
 
+    module->global_count = 0;
     if (global_count) {
-        module->global_count = global_count;
         total_size = sizeof(WASMGlobal) * (uint64)global_count;
         if (!(module->globals =
                   loader_malloc(total_size, error_buf, error_buf_size))) {
@@ -1166,8 +1357,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
             global->is_mutable = mutable ? true : false;
 
             /* initialize expression */
-            if (!load_init_expr(&p, p_end, &(global->init_expr), global->type,
-                                error_buf, error_buf_size))
+            if (!load_init_expr(module, &p, p_end, &(global->init_expr),
+                                global->type, error_buf, error_buf_size))
                 return false;
 
             if (INIT_EXPR_TYPE_GET_GLOBAL == global->init_expr.init_expr_type) {
@@ -1187,7 +1378,10 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                           < module->import_function_count
                                 + module->function_count);
             }
+
+            module->global_count++;
         }
+        bh_assert(module->global_count == global_count);
     }
 
     bh_assert(p == p_end);
@@ -1338,51 +1532,77 @@ load_elem_type(const uint8 **p_buf, const uint8 *buf_end, uint32 *p_elem_type,
 static bool
 load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end,
                     WASMModule *module, WASMTableSeg *table_segment,
-                    bool use_init_expr, char *error_buf, uint32 error_buf_size)
+                    char *error_buf, uint32 error_buf_size)
 {
     const uint8 *p = *p_buf, *p_end = buf_end;
     uint32 function_count, function_index = 0, i;
     uint64 total_size;
 
     read_leb_uint32(p, p_end, function_count);
-    table_segment->function_count = function_count;
-    total_size = sizeof(uintptr_t) * (uint64)function_count;
+    table_segment->value_count = function_count;
+    total_size = sizeof(InitializerExpression) * (uint64)function_count;
     if (total_size > 0
-        && !(table_segment->func_indexes = (uintptr_t *)loader_malloc(
-                 total_size, error_buf, error_buf_size))) {
+        && !(table_segment->init_values =
+                 (InitializerExpression *)loader_malloc(total_size, error_buf,
+                                                        error_buf_size))) {
         return false;
     }
 
     for (i = 0; i < function_count; i++) {
-        InitializerExpression init_expr = { 0 };
+        InitializerExpression *init_expr = &table_segment->init_values[i];
 
-#if WASM_ENABLE_REF_TYPES != 0
-        if (!use_init_expr) {
-            read_leb_uint32(p, p_end, function_index);
+        read_leb_uint32(p, p_end, function_index);
+        if (!check_function_index(module, function_index, error_buf,
+                                  error_buf_size)) {
+            return false;
         }
-        else {
-            if (!load_init_expr(&p, p_end, &init_expr, table_segment->elem_type,
-                                error_buf, error_buf_size))
-                return false;
 
-            function_index = init_expr.u.ref_index;
-        }
-#else
-        read_leb_uint32(p, p_end, function_index);
-#endif
+        init_expr->init_expr_type = INIT_EXPR_TYPE_FUNCREF_CONST;
+        init_expr->u.ref_index = function_index;
+    }
+
+    *p_buf = p;
+    return true;
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+static bool
+load_init_expr_vec(const uint8 **p_buf, const uint8 *buf_end,
+                   WASMModule *module, WASMTableSeg *table_segment,
+                   char *error_buf, uint32 error_buf_size)
+{
+    const uint8 *p = *p_buf, *p_end = buf_end;
+    uint32 ref_count, i;
+    uint64 total_size;
 
-        /* since we are using -1 to indicate ref.null */
-        if (init_expr.init_expr_type != INIT_EXPR_TYPE_REFNULL_CONST
-            && !check_function_index(module, function_index, error_buf,
-                                     error_buf_size)) {
+    read_leb_uint32(p, p_end, ref_count);
+    table_segment->value_count = ref_count;
+    total_size = sizeof(InitializerExpression) * (uint64)ref_count;
+    if (total_size > 0
+        && !(table_segment->init_values =
+                 (InitializerExpression *)loader_malloc(total_size, error_buf,
+                                                        error_buf_size))) {
+        return false;
+    }
+
+    for (i = 0; i < ref_count; i++) {
+        InitializerExpression *init_expr = &table_segment->init_values[i];
+
+        if (!load_init_expr(module, &p, p_end, init_expr,
+                            table_segment->elem_type, error_buf,
+                            error_buf_size))
             return false;
-        }
-        table_segment->func_indexes[i] = function_index;
+
+        bh_assert(
+            (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL)
+            || (init_expr->init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST)
+            || (init_expr->init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST));
     }
 
     *p_buf = p;
     return true;
 }
+#endif /* end of WASM_ENABLE_REF_TYPES != 0 */
 
 static bool
 load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
@@ -1423,16 +1643,25 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
                                            error_buf, error_buf_size))
                         return false;
 
-                    if (!load_init_expr(&p, p_end, &table_segment->base_offset,
-                                        VALUE_TYPE_I32, error_buf,
-                                        error_buf_size))
+                    if (!load_init_expr(
+                            module, &p, p_end, &table_segment->base_offset,
+                            VALUE_TYPE_I32, error_buf, error_buf_size))
                         return false;
 
-                    if (!load_func_index_vec(&p, p_end, module, table_segment,
-                                             table_segment->mode == 0 ? false
-                                                                      : true,
-                                             error_buf, error_buf_size))
-                        return false;
+                    if (table_segment->mode == 0) {
+                        /* vec(funcidx) */
+                        if (!load_func_index_vec(&p, p_end, module,
+                                                 table_segment, error_buf,
+                                                 error_buf_size))
+                            return false;
+                    }
+                    else {
+                        /* vec(expr) */
+                        if (!load_init_expr_vec(&p, p_end, module,
+                                                table_segment, error_buf,
+                                                error_buf_size))
+                            return false;
+                    }
                     break;
                 /* elemkind + passive/declarative */
                 case 1:
@@ -1440,8 +1669,9 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
                     if (!load_elem_type(&p, p_end, &table_segment->elem_type,
                                         true, error_buf, error_buf_size))
                         return false;
+                    /* vec(funcidx) */
                     if (!load_func_index_vec(&p, p_end, module, table_segment,
-                                             false, error_buf, error_buf_size))
+                                             error_buf, error_buf_size))
                         return false;
                     break;
                 /* elemkind/elemtype + table_idx + active */
@@ -1451,27 +1681,37 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
                                           &table_segment->table_index,
                                           error_buf, error_buf_size))
                         return false;
-                    if (!load_init_expr(&p, p_end, &table_segment->base_offset,
-                                        VALUE_TYPE_I32, error_buf,
-                                        error_buf_size))
+                    if (!load_init_expr(
+                            module, &p, p_end, &table_segment->base_offset,
+                            VALUE_TYPE_I32, error_buf, error_buf_size))
                         return false;
                     if (!load_elem_type(&p, p_end, &table_segment->elem_type,
                                         table_segment->mode == 2 ? true : false,
                                         error_buf, error_buf_size))
                         return false;
-                    if (!load_func_index_vec(&p, p_end, module, table_segment,
-                                             table_segment->mode == 2 ? false
-                                                                      : true,
-                                             error_buf, error_buf_size))
-                        return false;
+                    if (table_segment->mode == 2) {
+                        /* vec(funcidx) */
+                        if (!load_func_index_vec(&p, p_end, module,
+                                                 table_segment, error_buf,
+                                                 error_buf_size))
+                            return false;
+                    }
+                    else {
+                        /* vec(expr) */
+                        if (!load_init_expr_vec(&p, p_end, module,
+                                                table_segment, error_buf,
+                                                error_buf_size))
+                            return false;
+                    }
                     break;
                 case 5:
                 case 7:
                     if (!load_elem_type(&p, p_end, &table_segment->elem_type,
                                         false, error_buf, error_buf_size))
                         return false;
-                    if (!load_func_index_vec(&p, p_end, module, table_segment,
-                                             true, error_buf, error_buf_size))
+                    /* vec(expr) */
+                    if (!load_init_expr_vec(&p, p_end, module, table_segment,
+                                            error_buf, error_buf_size))
                         return false;
                     break;
                 default:
@@ -1486,10 +1726,10 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
                                   &table_segment->table_index, error_buf,
                                   error_buf_size))
                 return false;
-            if (!load_init_expr(&p, p_end, &table_segment->base_offset,
+            if (!load_init_expr(module, &p, p_end, &table_segment->base_offset,
                                 VALUE_TYPE_I32, error_buf, error_buf_size))
                 return false;
-            if (!load_func_index_vec(&p, p_end, module, table_segment, false,
+            if (!load_func_index_vec(&p, p_end, module, table_segment,
                                      error_buf, error_buf_size))
                 return false;
 #endif /* WASM_ENABLE_REF_TYPES != 0 */
@@ -1566,8 +1806,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
 #if WASM_ENABLE_BULK_MEMORY != 0
             if (!is_passive)
 #endif
-                if (!load_init_expr(&p, p_end, &init_expr, VALUE_TYPE_I32,
-                                    error_buf, error_buf_size))
+                if (!load_init_expr(module, &p, p_end, &init_expr,
+                                    VALUE_TYPE_I32, error_buf, error_buf_size))
                     return false;
 
             read_leb_uint32(p, p_end, data_seg_len);
@@ -3043,8 +3283,8 @@ wasm_loader_unload(WASMModule *module)
 
     if (module->table_segments) {
         for (i = 0; i < module->table_seg_count; i++) {
-            if (module->table_segments[i].func_indexes)
-                wasm_runtime_free(module->table_segments[i].func_indexes);
+            if (module->table_segments[i].init_values)
+                wasm_runtime_free(module->table_segments[i].init_values);
         }
         wasm_runtime_free(module->table_segments);
     }
@@ -3662,29 +3902,6 @@ typedef struct Const {
     uint8 value_type;
 } Const;
 
-static void *
-memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
-               uint32 error_buf_size)
-{
-    uint8 *mem_new;
-    bh_assert(size_new > size_old);
-    if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
-        bh_memcpy_s(mem_new, size_new, mem_old, size_old);
-        memset(mem_new + size_old, 0, size_new - size_old);
-        wasm_runtime_free(mem_old);
-    }
-    return mem_new;
-}
-
-#define MEM_REALLOC(mem, size_old, size_new)                               \
-    do {                                                                   \
-        void *mem_new = memory_realloc(mem, size_old, size_new, error_buf, \
-                                       error_buf_size);                    \
-        if (!mem_new)                                                      \
-            goto fail;                                                     \
-        mem = mem_new;                                                     \
-    } while (0)
-
 #define CHECK_CSP_PUSH()                                                  \
     do {                                                                  \
         if (ctx->frame_csp >= ctx->frame_csp_boundary) {                  \
@@ -5775,6 +5992,7 @@ re_scan:
                     (void)block_ret_types;
                     (void)block_ret_count;
                     (void)block_param_types;
+                    (void)block_param_count;
                 }
 
                 POP_CSP();
@@ -6391,8 +6609,9 @@ re_scan:
                     for (i = 0; i < module->table_seg_count; i++, table_seg++) {
                         if (table_seg->elem_type == VALUE_TYPE_FUNCREF
                             && wasm_elem_is_declarative(table_seg->mode)) {
-                            for (j = 0; j < table_seg->function_count; j++) {
-                                if (table_seg->func_indexes[j] == func_idx) {
+                            for (j = 0; j < table_seg->value_count; j++) {
+                                if (table_seg->init_values[j].u.ref_index
+                                    == func_idx) {
                                     func_declared = true;
                                     break;
                                 }

+ 46 - 60
core/iwasm/interpreter/wasm_opcode.h

@@ -262,9 +262,9 @@ typedef enum WASMOpcode {
     WASM_OP_REF_NULL = 0xd0,        /* ref.null */
     WASM_OP_REF_IS_NULL = 0xd1,     /* ref.is_null */
     WASM_OP_REF_FUNC = 0xd2,        /* ref.func */
-    WASM_OP_REF_AS_NON_NULL = 0xd3, /* ref.as_non_null */
-    WASM_OP_BR_ON_NULL = 0xd4,      /* br_on_null */
-    WASM_OP_REF_EQ = 0xd5,          /* ref.eq */
+    WASM_OP_REF_EQ = 0xd3,          /* ref.eq */
+    WASM_OP_REF_AS_NON_NULL = 0xd4, /* ref.as_non_null */
+    WASM_OP_BR_ON_NULL = 0xd5,      /* br_on_null */
     WASM_OP_BR_ON_NON_NULL = 0xd6,  /* br_on_non_null */
 
     EXT_OP_BLOCK = 0xd7,          /* block with blocktype */
@@ -284,60 +284,46 @@ typedef enum WASMOpcode {
 } WASMOpcode;
 
 typedef enum WASMGCEXTOpcode {
-#if WASM_ENABLE_GC_BINARYEN != 0
-    WASM_OP_STRUCT_NEW_CANON = 0x07,         /* struct.new_canon */
-    WASM_OP_STRUCT_NEW_CANON_DEFAULT = 0x08, /* struct.new_canon_default */
-#else
-    WASM_OP_STRUCT_NEW_CANON = 0x01,         /* struct.new_canon */
-    WASM_OP_STRUCT_NEW_CANON_DEFAULT = 0x02, /* struct.new_canon_default */
-#endif
-    WASM_OP_STRUCT_GET = 0x03,   /* struct.get */
-    WASM_OP_STRUCT_GET_S = 0x04, /* struct.get_s */
-    WASM_OP_STRUCT_GET_U = 0x05, /* struct.get_u */
-    WASM_OP_STRUCT_SET = 0x06,   /* struct.set */
-
-#if WASM_ENABLE_GC_BINARYEN != 0
-    WASM_OP_ARRAY_NEW_CANON = 0x1b,         /* array.new_canon */
-    WASM_OP_ARRAY_NEW_CANON_DEFAULT = 0x1c, /* array.new_canon_default */
-#else
-    WASM_OP_ARRAY_NEW_CANON = 0x11,          /* array.new_canon */
-    WASM_OP_ARRAY_NEW_CANON_DEFAULT = 0x12,  /* array.new_canon_default */
-#endif
-    WASM_OP_ARRAY_GET = 0x13,   /* array.get */
-    WASM_OP_ARRAY_GET_S = 0x14, /* array.get_s */
-    WASM_OP_ARRAY_GET_U = 0x15, /* array.get_u */
-    WASM_OP_ARRAY_SET = 0x16,   /* array.set */
-
-#if WASM_ENABLE_GC_BINARYEN != 0
-    WASM_OP_ARRAY_COPY = 0x18,            /* array.copy */
-    WASM_OP_ARRAY_LEN = 0x19,             /* array.len */
-    WASM_OP_ARRAY_NEW_CANON_FIXED = 0x1a, /* array.new_canon_fixed */
-    WASM_OP_ARRAY_NEW_CANON_DATA = 0x1d,  /* array.new_canon_data */
-    WASM_OP_ARRAY_NEW_CANON_ELEM = 0x1f,  /* array.new_canon_elem */
-#else
-    WASM_OP_ARRAY_LEN = 0x17,                /* array.len */
-    WASM_OP_ARRAY_NEW_CANON_FIXED = 0x19,    /* array.new_canon_fixed */
-    WASM_OP_ARRAY_NEW_CANON_DATA = 0x1b,     /* array.new_canon_data */
-    WASM_OP_ARRAY_NEW_CANON_ELEM = 0x1c,     /* array.new_canon_elem */
-#endif
-
-    WASM_OP_I31_NEW = 0x20,   /* i31.new */
-    WASM_OP_I31_GET_S = 0x21, /* i31.get_s */
-    WASM_OP_I31_GET_U = 0x22, /* i31.get_u */
-
-    WASM_OP_REF_TEST = 0x40,        /* ref.test */
-    WASM_OP_REF_CAST = 0x41,        /* ref.cast */
-    WASM_OP_BR_ON_CAST = 0x42,      /* br_on_cast */
-    WASM_OP_BR_ON_CAST_FAIL = 0x43, /* br_on_cast_fail */
-
-    WASM_OP_REF_TEST_NULLABLE = 0x48,        /* ref.test_nullable */
-    WASM_OP_REF_CAST_NULLABLE = 0x49,        /* ref.cast_nullable */
-    WASM_OP_BR_ON_CAST_NULLABLE = 0x4a,      /* br_on_cast_nullable */
-    WASM_OP_BR_ON_CAST_FAIL_NULLABLE = 0x4b, /* br_on_cast_fail_nullable */
-
-    WASM_OP_EXTERN_INTERNALIZE = 0x70, /* extern.internalize */
-    WASM_OP_EXTERN_EXTERNALIZE = 0x71, /* extern.externalize */
-
+    WASM_OP_STRUCT_NEW = 0x00,         /* struct.new */
+    WASM_OP_STRUCT_NEW_DEFAULT = 0x01, /* struct.new_default */
+    WASM_OP_STRUCT_GET = 0x02,         /* struct.get */
+    WASM_OP_STRUCT_GET_S = 0x03,       /* struct.get_s */
+    WASM_OP_STRUCT_GET_U = 0x04,       /* struct.get_u */
+    WASM_OP_STRUCT_SET = 0x05,         /* struct.set */
+
+    WASM_OP_ARRAY_NEW = 0x06,         /* array.new */
+    WASM_OP_ARRAY_NEW_DEFAULT = 0x07, /* array.new_default */
+    WASM_OP_ARRAY_NEW_FIXED = 0x08,   /* array.new_fixed */
+    WASM_OP_ARRAY_NEW_DATA = 0x09,    /* array.new_data */
+    WASM_OP_ARRAY_NEW_ELEM = 0x0A,    /* array.new_elem */
+    WASM_OP_ARRAY_GET = 0x0B,         /* array.get */
+    WASM_OP_ARRAY_GET_S = 0x0C,       /* array.get_s */
+    WASM_OP_ARRAY_GET_U = 0x0D,       /* array.get_u */
+    WASM_OP_ARRAY_SET = 0x0E,         /* array.set */
+    WASM_OP_ARRAY_LEN = 0x0F,         /* array.len */
+    WASM_OP_ARRAY_FILL = 0x10,        /* array.fill */
+    WASM_OP_ARRAY_COPY = 0x11,        /* array.copy */
+    WASM_OP_ARRAY_INIT_DATA = 0x12,
+    /* array.init_data */ /* TODO */
+    WASM_OP_ARRAY_INIT_ELEM = 0x13,
+    /* array.init_elem */ /* TODO */
+
+    WASM_OP_REF_TEST = 0x14,          /* ref.test */
+    WASM_OP_REF_TEST_NULLABLE = 0x15, /* ref.test_nullable */
+    WASM_OP_REF_CAST = 0x16,          /* ref.cast */
+    WASM_OP_REF_CAST_NULLABLE = 0x17, /* ref.cast_nullable */
+
+    WASM_OP_BR_ON_CAST = 0x18,      /* br_on_cast */
+    WASM_OP_BR_ON_CAST_FAIL = 0x19, /* br_on_cast_fail */
+
+    WASM_OP_ANY_CONVERT_EXTERN = 0x1A, /* any.convert_extern */
+    WASM_OP_EXTERN_CONVERT_ANY = 0x1B, /* extern.covert_any */
+
+    WASM_OP_REF_I31 = 0x1C,   /* ref.i31 */
+    WASM_OP_I31_GET_S = 0x1D, /* i31.get_s */
+    WASM_OP_I31_GET_U = 0x1E, /* i31.get_u */
+
+    /* stringref related opcoded */
     WASM_OP_STRING_NEW_UTF8 = 0x80,          /* string.new_utf8 */
     WASM_OP_STRING_NEW_WTF16 = 0x81,         /* string.new_wtf16 */
     WASM_OP_STRING_CONST = 0x82,             /* string.const */
@@ -1012,9 +998,9 @@ typedef enum WASMAtomicEXTOpcode {
         HANDLE_OPCODE(WASM_OP_REF_NULL),             /* 0xd0 */ \
         HANDLE_OPCODE(WASM_OP_REF_IS_NULL),          /* 0xd1 */ \
         HANDLE_OPCODE(WASM_OP_REF_FUNC),             /* 0xd2 */ \
-        HANDLE_OPCODE(WASM_OP_REF_AS_NON_NULL),      /* 0xd3 */ \
-        HANDLE_OPCODE(WASM_OP_BR_ON_NULL),           /* 0xd4 */ \
-        HANDLE_OPCODE(WASM_OP_REF_EQ),               /* 0xd5 */ \
+        HANDLE_OPCODE(WASM_OP_REF_EQ),               /* 0xd3 */ \
+        HANDLE_OPCODE(WASM_OP_REF_AS_NON_NULL),      /* 0xd4 */ \
+        HANDLE_OPCODE(WASM_OP_BR_ON_NULL),           /* 0xd5 */ \
         HANDLE_OPCODE(WASM_OP_BR_ON_NON_NULL),       /* 0xd6 */ \
         HANDLE_OPCODE(EXT_OP_BLOCK),                 /* 0xd7 */ \
         HANDLE_OPCODE(EXT_OP_LOOP),                  /* 0xd8 */ \

+ 411 - 106
core/iwasm/interpreter/wasm_runtime.c

@@ -4,6 +4,7 @@
  */
 
 #include "wasm_runtime.h"
+#include "wasm.h"
 #include "wasm_loader.h"
 #include "wasm_interp.h"
 #include "bh_common.h"
@@ -876,6 +877,7 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
     /* instantiate globals from global section */
     for (i = 0; i < module->global_count; i++) {
         InitializerExpression *init_expr = &(module->globals[i].init_expr);
+        uint8 flag = init_expr->init_expr_type;
 
         global->type = module->globals[i].type;
         global->is_mutable = module->globals[i].is_mutable;
@@ -888,59 +890,144 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
         global->ref_type = module->globals[i].ref_type;
 #endif
 
-        if (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
-            if (!check_global_init_expr(module, init_expr->u.global_index,
-                                        error_buf, error_buf_size)) {
-                goto fail;
-            }
+        switch (flag) {
+            case INIT_EXPR_TYPE_GET_GLOBAL:
+            {
+                if (!check_global_init_expr(module, init_expr->u.global_index,
+                                            error_buf, error_buf_size)) {
+                    goto fail;
+                }
 
-            bh_memcpy_s(
-                &(global->initial_value), sizeof(WASMValue),
-                &(globals[init_expr->u.global_index].initial_value),
-                sizeof(globals[init_expr->u.global_index].initial_value));
-        }
-#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
-        else if (init_expr->init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST) {
-            /* UINT32_MAX indicates that it is an null reference */
-            global->initial_value.u32 = (uint32)UINT32_MAX;
-        }
-#endif
-#if WASM_ENABLE_GC != 0
-        else if (init_expr->init_expr_type == INIT_EXPR_TYPE_I31_NEW) {
-            global->initial_value.gc_obj =
-                (void *)wasm_i31_obj_new(init_expr->u.i32);
-        }
-        else if (init_expr->init_expr_type
-                 == INIT_EXPR_TYPE_STRUCT_NEW_CANON_DEFAULT) {
-            WASMRttType *rtt_type;
-            WASMStructObjectRef struct_obj;
-            WASMStructType *struct_type;
-            uint32 type_idx = init_expr->u.i32;
-
-            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");
-                goto fail;
+                bh_memcpy_s(
+                    &(global->initial_value), sizeof(WASMValue),
+                    &(globals[init_expr->u.global_index].initial_value),
+                    sizeof(globals[init_expr->u.global_index].initial_value));
+                break;
             }
+#if WASM_ENABLE_GC != 0
+            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;
+
+                if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
+                    init_values = (WASMStructNewInitValues *)init_expr->u.data;
+                    type_idx = init_values->type_idx;
+                }
+                else {
+                    type_idx = init_expr->u.type_index;
+                }
 
-            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;
+                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");
+                    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;
             }
+            case INIT_EXPR_TYPE_ARRAY_NEW:
+            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 };
+                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.N;
+                    arr_init_val = &empty_val;
+                }
+                else {
+                    init_values = (WASMArrayNewInitValues *)init_expr->u.data;
+                    type_idx = init_values->type_idx;
+                    len = init_values->length;
 
-            global->initial_value.gc_obj = (void *)struct_obj;
-        }
-#endif
-        else {
-            bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
-                        &(init_expr->u), sizeof(init_expr->u));
+                    if (flag == INIT_EXPR_TYPE_ARRAY_NEW) {
+                        arr_init_val = 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]);
+                    }
+                }
+
+                global->initial_value.gc_obj = (void *)array_obj;
+
+                break;
+            }
+            case INIT_EXPR_TYPE_I31_NEW:
+            {
+                global->initial_value.gc_obj =
+                    (wasm_obj_t)wasm_i31_obj_new(init_expr->u.i32);
+                break;
+            }
+#endif /* end of WASM_ENABLE_GC != 0 */
+            default:
+                bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
+                            &(init_expr->u), sizeof(init_expr->u));
+                break;
         }
+
         global++;
     }
 
@@ -2026,8 +2113,31 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                     break;
 #endif
                 default:
+                {
 #if WASM_ENABLE_GC != 0
-                    if (global->type != REF_TYPE_NULLFUNCREF
+                    InitializerExpression *global_init = NULL;
+                    bh_assert(wasm_is_type_reftype(global->type));
+
+                    if (i >= module->import_global_count) {
+                        global_init =
+                            &module->globals[i - module->import_global_count]
+                                 .init_expr;
+                    }
+
+                    if (global->type == REF_TYPE_NULLFUNCREF
+                        || global->type == REF_TYPE_NULLEXTERNREF
+                        || global->type == REF_TYPE_NULLREF) {
+                        STORE_PTR((void **)global_data, NULL_REF);
+                        global_data += sizeof(void *);
+                        break;
+                    }
+
+                    /* We can't create funcref obj during global instantiation
+                     * since the functions are not instantiated yet, so we need
+                     * to defer the initialization here */
+                    if (global_init
+                        && (global_init->init_expr_type
+                            == INIT_EXPR_TYPE_FUNCREF_CONST)
                         && wasm_reftype_is_subtype_of(
                             global->type, global->ref_type, REF_TYPE_FUNCREF,
                             NULL, module_inst->module->types,
@@ -2042,27 +2152,21 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                         }
                         STORE_PTR((void **)global_data, func_obj);
                         global_data += sizeof(void *);
+                        /* Also update the inital_value since other globals may
+                         * refer to this */
+                        global->initial_value.gc_obj = (wasm_obj_t)func_obj;
                         break;
                     }
-                    else if (global->type != REF_TYPE_NULLREF
-                             && wasm_reftype_is_subtype_of(
-                                 global->type, global->ref_type,
-                                 REF_TYPE_I31REF, NULL,
-                                 module_inst->module->types,
-                                 module_inst->module->type_count)) {
+                    else {
                         STORE_PTR((void **)global_data,
                                   global->initial_value.gc_obj);
                         global_data += sizeof(void *);
                         break;
                     }
-                    else if (wasm_is_type_reftype(global->type)) {
-                        STORE_PTR((void **)global_data, NULL_REF);
-                        global_data += sizeof(void *);
-                        break;
-                    }
 #endif
                     bh_assert(0);
                     break;
+                }
             }
         }
         bh_assert(global_data == global_data_end);
@@ -2160,6 +2264,61 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
         }
     }
 
+#if WASM_ENABLE_GC != 0
+    /* Initialize the table data with init expr */
+    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;
+        uint32 j;
+
+        if (table->init_expr.init_expr_type == 0) {
+            /* No table initializer */
+            continue;
+        }
+
+        table_data = table_inst->elems;
+
+        bh_assert(
+            table->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
+            || table->init_expr.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
+            || table->init_expr.init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST);
+
+        if (table->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
+            if (!check_global_init_expr(module, table->init_expr.u.global_index,
+                                        error_buf, error_buf_size)) {
+                goto fail;
+            }
+
+            table->init_expr.u.gc_obj =
+                globals[table->init_expr.u.global_index].initial_value.gc_obj;
+        }
+        else if (table->init_expr.init_expr_type
+                 == INIT_EXPR_TYPE_FUNCREF_CONST) {
+            uint32 func_idx = table->init_expr.u.ref_index;
+            if (func_idx != UINT32_MAX) {
+                if (!(table->init_expr.u.gc_obj =
+                          wasm_create_func_obj(module_inst, func_idx, false,
+                                               error_buf, error_buf_size)))
+                    goto fail;
+            }
+            else {
+                table->init_expr.u.gc_obj = NULL_REF;
+            }
+        }
+        else if (table->init_expr.init_expr_type
+                 == INIT_EXPR_TYPE_REFNULL_CONST) {
+            table->init_expr.u.gc_obj = NULL_REF;
+        }
+
+        LOG_DEBUG("Init table [%d] elements from [%d] to [%d] as: %p", i, 0,
+                  table_inst->cur_size, (void *)table->init_expr.u.gc_obj);
+        for (j = 0; j < table_inst->cur_size; j++) {
+            *(table_data + j) = table->init_expr.u.gc_obj;
+        }
+    }
+#endif /* end of WASM_ENABLE_GC != 0 */
+
     /* Initialize the table data with table segment section */
     for (i = 0; module_inst->table_count > 0 && i < module->table_seg_count;
          i++) {
@@ -2167,13 +2326,13 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
         /* 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;
         uint32 tbl_init_size, tbl_max_size;
 #endif
 #if WASM_ENABLE_GC != 0
         WASMRefType *tbl_elem_ref_type;
-        uint32 j;
 #endif
 
         bh_assert(table);
@@ -2191,7 +2350,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
         if (tbl_elem_type != VALUE_TYPE_FUNCREF
             && tbl_elem_type != VALUE_TYPE_EXTERNREF) {
             set_error_buf(error_buf, error_buf_size,
-                          "elements segment does not fit");
+                          "type mismatch: elements segment does not fit");
             goto fail;
         }
 #elif WASM_ENABLE_GC != 0
@@ -2201,7 +2360,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                 table->elem_type, table->elem_ref_type.elem_ref_type,
                 module->types, module->type_count)) {
             set_error_buf(error_buf, error_buf_size,
-                          "elements segment does not fit");
+                          "type mismatch: elements segment does not fit");
             goto fail;
         }
 #endif
@@ -2254,7 +2413,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                 || globals[table_seg->base_offset.u.global_index].type
                        != VALUE_TYPE_I32) {
                 set_error_buf(error_buf, error_buf_size,
-                              "elements segment does not fit");
+                              "type mismatch: elements segment does not fit");
                 goto fail;
             }
 
@@ -2272,13 +2431,13 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                           "out of bounds table access");
 #else
             set_error_buf(error_buf, error_buf_size,
-                          "elements segment does not fit");
+                          "type mismatch: elements segment does not fit");
 #endif
             goto fail;
         }
 
         /* check offset + length(could be zero) */
-        length = table_seg->function_count;
+        length = table_seg->value_count;
         if ((uint32)table_seg->base_offset.u.i32 + length > table->cur_size) {
             LOG_DEBUG("base_offset(%d) + length(%d)> table->cur_size(%d)",
                       table_seg->base_offset.u.i32, length, table->cur_size);
@@ -2287,40 +2446,189 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                           "out of bounds table access");
 #else
             set_error_buf(error_buf, error_buf_size,
-                          "elements segment does not fit");
+                          "type mismatch: elements segment does not fit");
 #endif
             goto fail;
         }
 
-        /**
-         * Check function index in the current module inst for now.
-         * will check the linked table inst owner in future.
-         * so loader check is enough
-         */
+        for (j = 0; j < length; j++) {
+            InitializerExpression *init_expr = &table_seg->init_values[j];
+            uint8 flag = init_expr->init_expr_type;
+            void *ref = NULL;
+
+            /* const and get global init values should be resolved during
+             * loading */
+            bh_assert((flag == INIT_EXPR_TYPE_GET_GLOBAL)
+                      || (flag == INIT_EXPR_TYPE_REFNULL_CONST)
+                      || ((flag >= INIT_EXPR_TYPE_FUNCREF_CONST)
+                          && (flag <= INIT_EXPR_TYPE_EXTERN_CONVERT_ANY)));
+
+            switch (flag) {
+                case INIT_EXPR_TYPE_REFNULL_CONST:
+                    ref = NULL;
+                    break;
+                case INIT_EXPR_TYPE_FUNCREF_CONST:
+                {
 #if WASM_ENABLE_GC == 0
-        bh_memcpy_s(
-            table_data + table_seg->base_offset.u.i32,
-            (uint32)((table->cur_size - (uint32)table_seg->base_offset.u.i32)
-                     * sizeof(table_elem_type_t)),
-            table_seg->func_indexes, (uint32)(length * sizeof(uintptr_t)));
+                    ref = (void *)(uintptr_t)init_expr->u.ref_index;
 #else
-        for (j = 0; j < length; j++) {
-            WASMFuncObjectRef func_obj;
-            uint32 func_idx = table_seg->func_indexes[j];
-            /* UINT32_MAX indicates that it is an null reference */
-            if (func_idx != UINT32_MAX) {
-                if (!(func_obj =
-                          wasm_create_func_obj(module_inst, func_idx, false,
-                                               error_buf, error_buf_size))) {
-                    goto fail;
+                    WASMFuncObjectRef func_obj;
+                    uint32 func_idx = init_expr->u.ref_index;
+                    /* UINT32_MAX indicates that it is an null reference */
+                    if (func_idx != UINT32_MAX) {
+                        if (!(func_obj = wasm_create_func_obj(
+                                  module_inst, func_idx, false, error_buf,
+                                  error_buf_size))) {
+                            goto fail;
+                        }
+                        ref = func_obj;
+                    }
+                    else {
+                        ref = NULL_REF;
+                    }
+#endif /* end of WASM_ENABLE_GC != 0 */
+                    break;
                 }
-                *(table_data + table_seg->base_offset.u.i32 + j) = func_obj;
-            }
-            else {
-                *(table_data + table_seg->base_offset.u.i32 + j) = NULL_REF;
+#if WASM_ENABLE_GC != 0
+                case INIT_EXPR_TYPE_GET_GLOBAL:
+                {
+                    if (!check_global_init_expr(module,
+                                                init_expr->u.global_index,
+                                                error_buf, error_buf_size)) {
+                        goto fail;
+                    }
+
+                    ref =
+                        globals[init_expr->u.global_index].initial_value.gc_obj;
+                    break;
+                }
+                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;
+
+                    if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
+                        init_values =
+                            (WASMStructNewInitValues *)init_expr->u.data;
+                        type_idx = init_values->type_idx;
+                    }
+                    else {
+                        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");
+                        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]);
+                        }
+                    }
+
+                    ref = struct_obj;
+                    break;
+                }
+                case INIT_EXPR_TYPE_ARRAY_NEW:
+                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 };
+                    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.N;
+                        arr_init_val = &empty_val;
+                    }
+                    else {
+                        init_values =
+                            (WASMArrayNewInitValues *)init_expr->u.data;
+                        type_idx = init_values->type_idx;
+                        len = init_values->length;
+
+                        if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
+                            arr_init_val = 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]);
+                        }
+                    }
+
+                    ref = array_obj;
+
+                    break;
+                }
+                case INIT_EXPR_TYPE_I31_NEW:
+                {
+                    ref = (wasm_obj_t)wasm_i31_obj_new(init_expr->u.i32);
+                    break;
+                }
+#endif /* end of WASM_ENABLE_GC != 0 */
             }
+
+            *(table_data + table_seg->base_offset.u.i32 + j) =
+                (table_elem_type_t)ref;
         }
-#endif
     }
 
     /* Initialize the thread related data */
@@ -3142,7 +3450,8 @@ wasm_get_module_mem_consumption(const WASMModule *module,
         sizeof(WASMTableSeg) * module->table_seg_count;
     for (i = 0; i < module->table_seg_count; i++) {
         WASMTableSeg *table_seg = &module->table_segments[i];
-        mem_conspn->tables_size += sizeof(uint32) * table_seg->function_count;
+        mem_conspn->tables_size +=
+            sizeof(InitializerExpression *) * table_seg->value_count;
     }
 
     mem_conspn->data_segs_size = sizeof(WASMDataSeg *) * module->data_seg_count;
@@ -3644,11 +3953,11 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
 {
     WASMTableInstance *tbl_inst;
     WASMTableSeg *tbl_seg;
-#if WASM_ENABLE_GC != 0
     table_elem_type_t *table_elems;
-    uintptr_t *func_indexes;
-    void *func_obj;
+    InitializerExpression *init_values;
     uint32 i;
+#if WASM_ENABLE_GC != 0
+    void *func_obj;
 #endif
 
     bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
@@ -3659,7 +3968,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
     bh_assert(tbl_inst);
     bh_assert(tbl_seg);
 
-    if (offset_len_out_of_bounds(src_offset, length, tbl_seg->function_count)
+    if (offset_len_out_of_bounds(src_offset, length, tbl_seg->value_count)
         || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
         jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
         return;
@@ -3679,14 +3988,15 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
         return;
     }
 
-#if WASM_ENABLE_GC != 0
     table_elems = tbl_inst->elems + dst_offset;
-    func_indexes = tbl_seg->func_indexes + src_offset;
+    init_values = tbl_seg->init_values + src_offset;
 
     for (i = 0; i < length; i++) {
+#if WASM_ENABLE_GC != 0
         /* UINT32_MAX indicates that it is a null ref */
-        if (func_indexes[i] != UINT32_MAX) {
-            if (!(func_obj = wasm_create_func_obj(module_inst, func_indexes[i],
+        if (init_values[i].u.ref_index != UINT32_MAX) {
+            if (!(func_obj = wasm_create_func_obj(module_inst,
+                                                  init_values[i].u.ref_index,
                                                   true, NULL, 0))) {
                 wasm_set_exception(module_inst, "null function object");
                 return;
@@ -3696,15 +4006,10 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
         else {
             table_elems[i] = NULL_REF;
         }
-    }
 #else
-    bh_memcpy_s((uint8 *)tbl_inst + offsetof(WASMTableInstance, elems)
-                    + dst_offset * sizeof(table_elem_type_t),
-                (uint32)sizeof(table_elem_type_t)
-                    * (tbl_inst->cur_size - dst_offset),
-                tbl_seg->func_indexes + src_offset,
-                (uint32)(length * sizeof(table_elem_type_t)));
+        table_elems[i] = init_values[i].u.ref_index;
 #endif
+    }
 }
 
 void

+ 4 - 0
core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c

@@ -1090,6 +1090,10 @@ static WASMNativeGlobalDef native_global_defs[] = {
     { "test", "global-f32", VALUE_TYPE_F32, false, .value.f32 = 0 },
     { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 },
     { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 },
+#if WASM_ENABLE_GC != 0
+    { "G", "g", VALUE_TYPE_I32, false, .value.i32 = 4 },
+    { "M", "g", REF_TYPE_HT_NON_NULLABLE, false, .value.gc_obj = 0 },
+#endif
 #endif
     { "global", "NaN", VALUE_TYPE_F64, .value.u64 = 0x7FF8000000000000LL },
     { "global", "Infinity", VALUE_TYPE_F64, .value.u64 = 0x7FF0000000000000LL }

+ 1 - 1
tests/wamr-test-suites/spec-test-script/all.py

@@ -91,7 +91,7 @@ def ignore_the_case(
         return True
 
     if gc_flag:
-        if case_name in ["type-canon", "type-equivalence", "type-rec"]:
+        if case_name in ["type-equivalence", "type-rec", "array_init_elem", "array_init_data"]:
             return True
 
     if sgx_flag:

Разница между файлами не показана из-за своего большого размера
+ 606 - 230
tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch


+ 4 - 3
tests/wamr-test-suites/test_wamr.sh

@@ -436,13 +436,13 @@ function spec_test()
         pushd spec
 
         git restore . && git clean -ffd .
-        # Sync constant expression descriptions
-        git reset --hard 62beb94ddd41987517781732f17f213d8b866dcc
+        # Reset to commit: "[test] Unify the error message."
+        git reset --hard 0caaadc65b5e1910512d8ae228502edcf9d60390
         git apply ../../spec-test-script/gc_ignore_cases.patch
 
         echo "compile the reference intepreter"
         pushd interpreter
-        make opt
+        make
         popd
     fi
 
@@ -813,6 +813,7 @@ function trigger()
         EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_GC=1"
         EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_REF_TYPES=1"
         EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_BULK_MEMORY=1"
+        EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_TAIL_CALL=1"
     fi
 
     if [[ ${ENABLE_DEBUG_VERSION} == 1 ]]; then

+ 0 - 3
wamr-compiler/CMakeLists.txt

@@ -49,9 +49,6 @@ add_definitions(-DWASM_ENABLE_LIB_WASI_THREADS=1)
 add_definitions(-DWASM_ENABLE_MODULE_INST_CONTEXT=1)
 
 add_definitions(-DWASM_ENABLE_GC=1)
-if (WAMR_BUILD_GC_BINARYEN EQUAL 1)
-  add_definitions(-DWASM_ENABLE_GC_BINARYEN=1)
-endif ()
 
 set (WAMR_BUILD_STRINGREF 1)
 set (WAMR_STRINGREF_IMPL_SOURCE "STUB")

Некоторые файлы не были показаны из-за большого количества измененных файлов