Sfoglia il codice sorgente

[instantiation linking] Create and import WASMTableInstance (#3898)

- Implement import table and table creation
- Enhance memory de-instantiation checks and adjust stack size for wasm execution environment
- Improve shared memory reference handling and enhance table de-instantiation checks
liang.he 1 anno fa
parent
commit
ee2d60bf62
39 ha cambiato i file con 1652 aggiunte e 636 eliminazioni
  1. 1 0
      core/config.h
  2. 33 8
      core/iwasm/aot/aot_loader.c
  3. 266 92
      core/iwasm/aot/aot_runtime.c
  4. 28 2
      core/iwasm/aot/aot_runtime.h
  5. 28 14
      core/iwasm/common/wasm_c_api.c
  6. 250 101
      core/iwasm/common/wasm_runtime_common.c
  7. 18 0
      core/iwasm/common/wasm_shared_memory.c
  8. 3 0
      core/iwasm/common/wasm_shared_memory.h
  9. 0 0
      core/iwasm/common/wasm_table.c
  10. 97 51
      core/iwasm/compilation/aot.c
  11. 7 17
      core/iwasm/compilation/aot.h
  12. 10 3
      core/iwasm/compilation/aot_compiler.h
  13. 187 126
      core/iwasm/compilation/aot_emit_aot_file.c
  14. 2 11
      core/iwasm/compilation/aot_emit_function.c
  15. 98 44
      core/iwasm/compilation/aot_emit_table.c
  16. 4 0
      core/iwasm/compilation/aot_emit_table.h
  17. 3 0
      core/iwasm/compilation/aot_llvm.c
  18. 2 0
      core/iwasm/compilation/aot_llvm.h
  19. 3 1
      core/iwasm/fast-jit/fe/jit_emit_table.c
  20. 13 0
      core/iwasm/fast-jit/jit_frontend.c
  21. 1 0
      core/iwasm/include/aot_comp_option.h
  22. 45 27
      core/iwasm/include/wasm_export.h
  23. 3 2
      core/iwasm/interpreter/wasm.h
  24. 19 8
      core/iwasm/interpreter/wasm_interp_classic.c
  25. 19 8
      core/iwasm/interpreter/wasm_interp_fast.c
  26. 226 102
      core/iwasm/interpreter/wasm_runtime.c
  27. 53 2
      core/iwasm/interpreter/wasm_runtime.h
  28. 3 3
      product-mini/platforms/posix/main.c
  29. 11 1
      samples/linking/CMakeLists.txt
  30. 11 0
      samples/linking/import-memory/CMakeLists.txt
  31. 10 6
      samples/linking/import-memory/main.c
  32. 11 0
      samples/linking/import-table/CMakeLists.txt
  33. 113 0
      samples/linking/import-table/main.c
  34. 0 6
      samples/linking/raw/CMakeLists.txt
  35. 17 0
      samples/linking/wasm/CMakeLists.txt
  36. 40 0
      samples/linking/wasm/import_table.c
  37. 3 0
      tests/wamr-test-suites/spec-test-script/runtest.py
  38. 9 1
      tests/wamr-test-suites/test_wamr.sh
  39. 5 0
      wamr-compiler/main.c

+ 1 - 0
core/config.h

@@ -84,6 +84,7 @@
 #endif
 #endif
 
 
 #define AOT_MAGIC_NUMBER 0x746f6100
 #define AOT_MAGIC_NUMBER 0x746f6100
+/* FIXME: maybe 5? need a discussion */
 #define AOT_CURRENT_VERSION 4
 #define AOT_CURRENT_VERSION 4
 
 
 #ifndef WASM_ENABLE_JIT
 #ifndef WASM_ENABLE_JIT

+ 33 - 8
core/iwasm/aot/aot_loader.c

@@ -507,6 +507,14 @@ check_feature_flags(char *error_buf, uint32 error_buf_size,
     }
     }
 #endif
 #endif
 
 
+#if WASM_ENABLE_MULTI_MODULE == 0
+    if (feature_flags & WASM_FEATURE_MULTI_MODULE) {
+        set_error_buf(error_buf, error_buf_size,
+                      "multi-module is not enabled in this build");
+        return false;
+    }
+#endif
+
     return true;
     return true;
 }
 }
 
 
@@ -530,7 +538,7 @@ load_target_info_section(const uint8 *buf, const uint8 *buf_end,
                          AOTModule *module, char *error_buf,
                          AOTModule *module, char *error_buf,
                          uint32 error_buf_size)
                          uint32 error_buf_size)
 {
 {
-    AOTTargetInfo target_info;
+    AOTTargetInfo target_info = { 0 };
     const uint8 *p = buf, *p_end = buf_end;
     const uint8 *p = buf, *p_end = buf_end;
     bool is_target_little_endian, is_target_64_bit;
     bool is_target_little_endian, is_target_64_bit;
 
 
@@ -1364,8 +1372,8 @@ fail:
 
 
 static bool
 static bool
 load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
 load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
-                       AOTModule *module, char *error_buf,
-                       uint32 error_buf_size)
+                       AOTModule *module, bool is_load_from_file_buf,
+                       char *error_buf, uint32 error_buf_size)
 {
 {
     const uint8 *buf = *p_buf;
     const uint8 *buf = *p_buf;
     AOTImportTable *import_table;
     AOTImportTable *import_table;
@@ -1382,7 +1390,7 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
         return false;
         return false;
     }
     }
 
 
-    /* keep sync with aot_emit_table_info() aot_emit_aot_file */
+    /* keep sync with aot_emit_import_table_info() aot_emit_aot_file */
     for (i = 0; i < module->import_table_count; i++, import_table++) {
     for (i = 0; i < module->import_table_count; i++, import_table++) {
         read_uint8(buf, buf_end, import_table->table_type.elem_type);
         read_uint8(buf, buf_end, import_table->table_type.elem_type);
         read_uint8(buf, buf_end, import_table->table_type.flags);
         read_uint8(buf, buf_end, import_table->table_type.flags);
@@ -1391,7 +1399,13 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
         if (wasm_is_type_multi_byte_type(import_table->table_type.elem_type)) {
         if (wasm_is_type_multi_byte_type(import_table->table_type.elem_type)) {
             read_uint8(buf, buf_end, ref_type.ref_ht_common.nullable);
             read_uint8(buf, buf_end, ref_type.ref_ht_common.nullable);
         }
         }
+        else
 #endif
 #endif
+        {
+            /* Skip 1 byte */
+            buf += 1;
+        }
+
         read_uint32(buf, buf_end, import_table->table_type.init_size);
         read_uint32(buf, buf_end, import_table->table_type.init_size);
         read_uint32(buf, buf_end, import_table->table_type.max_size);
         read_uint32(buf, buf_end, import_table->table_type.max_size);
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
@@ -1409,6 +1423,9 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
             }
             }
         }
         }
 #endif
 #endif
+
+        read_string(buf, buf_end, import_table->module_name);
+        read_string(buf, buf_end, import_table->table_name);
     }
     }
 
 
     *p_buf = buf;
     *p_buf = buf;
@@ -1451,7 +1468,13 @@ load_table_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
         if (wasm_is_type_multi_byte_type(table->table_type.elem_type)) {
         if (wasm_is_type_multi_byte_type(table->table_type.elem_type)) {
             read_uint8(buf, buf_end, ref_type.ref_ht_common.nullable);
             read_uint8(buf, buf_end, ref_type.ref_ht_common.nullable);
         }
         }
+        else
 #endif
 #endif
+        {
+            /* Skip 1 byte */
+            buf += 1;
+        }
+
         read_uint32(buf, buf_end, table->table_type.init_size);
         read_uint32(buf, buf_end, table->table_type.init_size);
         read_uint32(buf, buf_end, table->table_type.max_size);
         read_uint32(buf, buf_end, table->table_type.max_size);
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
@@ -1582,14 +1605,15 @@ fail:
 
 
 static bool
 static bool
 load_table_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
 load_table_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
-                char *error_buf, uint32 error_buf_size)
+                bool is_load_from_file_buf, char *error_buf,
+                uint32 error_buf_size)
 {
 {
     const uint8 *buf = *p_buf;
     const uint8 *buf = *p_buf;
 
 
     read_uint32(buf, buf_end, module->import_table_count);
     read_uint32(buf, buf_end, module->import_table_count);
     if (module->import_table_count > 0
     if (module->import_table_count > 0
-        && !load_import_table_list(&buf, buf_end, module, error_buf,
-                                   error_buf_size))
+        && !load_import_table_list(&buf, buf_end, module, is_load_from_file_buf,
+                                   error_buf, error_buf_size))
         return false;
         return false;
 
 
     read_uint32(buf, buf_end, module->table_count);
     read_uint32(buf, buf_end, module->table_count);
@@ -2475,7 +2499,8 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end,
 
 
     if (!load_memory_info(&p, p_end, module, is_load_from_file_buf, error_buf,
     if (!load_memory_info(&p, p_end, module, is_load_from_file_buf, error_buf,
                           error_buf_size)
                           error_buf_size)
-        || !load_table_info(&p, p_end, module, error_buf, error_buf_size)
+        || !load_table_info(&p, p_end, module, is_load_from_file_buf, error_buf,
+                            error_buf_size)
         || !load_type_info(&p, p_end, module, error_buf, error_buf_size)
         || !load_type_info(&p, p_end, module, error_buf, error_buf_size)
         || !load_import_global_info(&p, p_end, module, is_load_from_file_buf,
         || !load_import_global_info(&p, p_end, module, is_load_from_file_buf,
                                     error_buf, error_buf_size)
                                     error_buf, error_buf_size)

+ 266 - 92
core/iwasm/aot/aot_runtime.c

@@ -662,73 +662,151 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
     return true;
     return true;
 }
 }
 
 
+/**
+ * Destroy table instances.
+ */
+static void
+tables_deinstantiate(AOTModuleInstance *inst)
+{
+    if (!inst || !inst->tables) {
+        return;
+    }
+
+#if WASM_ENABLE_MULTI_MODULE == 0
+    AOTModule *module = (AOTModule *)inst->module;
+    /* only imported tables */
+    for (uint32 i = 0; i < module->import_table_count; i++) {
+        WASMTableInstance *table = inst->tables[i];
+        if (!table) {
+            continue;
+        }
+
+        table_elem_type_t *table_elems =
+            aot_locate_table_elems(module, table, i);
+
+        if (!table_elems) {
+            continue;
+        }
+
+        void *table_imported =
+            ((uint8 *)(table_elems)) - offsetof(WASMTableInstance, elems);
+
+        wasm_runtime_free(table_imported);
+    }
+#endif
+
+    wasm_runtime_free(inst->tables);
+}
+
 static bool
 static bool
 tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
-                   AOTTableInstance *first_tbl_inst, char *error_buf,
-                   uint32 error_buf_size)
+                   AOTTableInstance *tables_data,
+                   const WASMExternInstance *imports, uint32 import_count,
+                   char *error_buf, uint32 error_buf_size)
 {
 {
-    uint32 i, global_index, global_data_offset, base_offset, length;
-    uint64 total_size;
-    AOTTableInitData *table_seg;
-    AOTTableInstance *tbl_inst = first_tbl_inst;
-
-    total_size = (uint64)sizeof(AOTTableInstance *) * module_inst->table_count;
+    uint64 total_size =
+        (uint64)sizeof(AOTTableInstance *) * module_inst->table_count;
     if (total_size > 0
     if (total_size > 0
         && !(module_inst->tables =
         && !(module_inst->tables =
                  runtime_malloc(total_size, error_buf, error_buf_size))) {
                  runtime_malloc(total_size, error_buf, error_buf_size))) {
         return false;
         return false;
     }
     }
 
 
-    /*
-     * treat import table like a local one until we enable module linking
-     * in AOT mode
-     */
-    for (i = 0; i != module_inst->table_count; ++i) {
-        if (i < module->import_table_count) {
-            AOTImportTable *import_table = module->import_tables + i;
-            tbl_inst->cur_size = import_table->table_type.init_size;
-            tbl_inst->max_size =
-                aot_get_imp_tbl_data_slots(import_table, false);
-            tbl_inst->elem_type = module->tables[i].table_type.elem_type;
+    AOTTableInstance *table = tables_data;
+    uint32 table_index;
+    for (table_index = 0; table_index < module->import_table_count;
+         table_index++) {
+        AOTTableType *table_type =
+            &((module->import_tables + table_index)->table_type);
+
+        table->cur_size = table_type->init_size;
+        table->max_size = aot_get_tbl_data_slots(table_type, false);
+        table->elem_type = table_type->elem_type;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
-            tbl_inst->elem_ref_type.elem_ref_type =
-                module->tables[i].table_type.elem_ref_type;
+        table->elem_ref_type.elem_ref_type = table_type->elem_ref_type;
 #endif
 #endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+        /* Set all elements to -1 or NULL_REF to mark them as uninitialized
+         * elements */
+        memset(table->elems,
+#if WASM_ENABLE_GC == 0
+               0xff,
+#else
+               0x00,
+#endif
+               sizeof(table_elem_type_t) * table->max_size);
+
+#else
+        /* use import table elem */
+        AOTImportTable *import_table_type = module->import_tables + table_index;
+        const WASMExternInstance *extern_inst =
+            wasm_runtime_get_extern_instance(imports, import_count,
+                                             WASM_IMPORT_EXPORT_KIND_TABLE,
+                                             table_index);
+        if (!extern_inst) {
+            LOG_ERROR("missing an import table(%s, %s)",
+                      import_table_type->module_name,
+                      import_table_type->table_name);
+            return false;
         }
         }
-        else {
-            AOTTable *table = module->tables + (i - module->import_table_count);
-            tbl_inst->cur_size = table->table_type.init_size;
-            tbl_inst->max_size = aot_get_tbl_data_slots(table, false);
-            tbl_inst->elem_type = module->tables[i].table_type.elem_type;
+
+        /* just in case */
+#ifndef NDEBUG
+        if (strcmp(import_table_type->table_name, extern_inst->field_name)) {
+            LOG_ERROR("mismatched import table name: expect \"%s\", got \"%s\"",
+                      import_table_type->table_name, extern_inst->field_name);
+            return false;
+        }
+#endif
+
+        /* store the pointer value */
+        table->elems[0] = (table_elem_type_t)extern_inst->u.table->elems;
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
+
+        module_inst->tables[table_index] = table;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+        table =
+            (AOTTableInstance *)((uint8 *)table
+                                 + offsetof(AOTTableInstance, elems)
+                                 + sizeof(table_elem_type_t) * table->max_size);
+#else
+        table = (AOTTableInstance *)((uint8 *)table
+                                     + offsetof(AOTTableInstance, elems)
+                                     + sizeof(table_elem_type_t));
+#endif
+    }
+
+    for (table_index = 0; table_index < module->table_count; table_index++) {
+        AOTTableType *table_type =
+            &((module->tables + table_index)->table_type);
+
+        table->cur_size = table_type->init_size;
+        table->max_size = aot_get_tbl_data_slots(table_type, false);
+        table->elem_type = table_type->elem_type;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
-            tbl_inst->elem_ref_type.elem_ref_type =
-                module->tables[i].table_type.elem_ref_type;
+        table->elem_ref_type.elem_ref_type = table_type->elem_ref_type;
 #endif
 #endif
-        }
 
 
         /* Set all elements to -1 or NULL_REF to mark them as uninitialized
         /* Set all elements to -1 or NULL_REF to mark them as uninitialized
          * elements */
          * elements */
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
-        memset(tbl_inst->elems, 0xff,
-               sizeof(table_elem_type_t) * tbl_inst->max_size);
+        memset(table->elems, 0xff, sizeof(table_elem_type_t) * table->max_size);
 #else
 #else
-        memset(tbl_inst->elems, 0x00,
-               sizeof(table_elem_type_t) * tbl_inst->max_size);
+        memset(table->elems, 0x00, sizeof(table_elem_type_t) * table->max_size);
 #endif
 #endif
 
 
-        module_inst->tables[i] = tbl_inst;
-        tbl_inst = (AOTTableInstance *)((uint8 *)tbl_inst
-                                        + offsetof(AOTTableInstance, elems)
-                                        + sizeof(table_elem_type_t)
-                                              * tbl_inst->max_size);
+        module_inst->tables[table_index] = table;
+        table =
+            (AOTTableInstance *)((uint8 *)table
+                                 + offsetof(AOTTableInstance, elems)
+                                 + sizeof(table_elem_type_t) * table->max_size);
     }
     }
 
 
     /* fill table with element segment content */
     /* fill table with element segment content */
-    for (i = 0; i < module->table_init_data_count; i++) {
-#if WASM_ENABLE_GC == 0
-        uint32 j;
-#endif
-        table_seg = module->table_init_data_list[i];
+    for (uint32 i = 0; i < module->table_init_data_count; i++) {
+        AOTTableInitData *table_seg = module->table_init_data_list[i];
 
 
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
         if (!wasm_elem_is_active(table_seg->mode))
         if (!wasm_elem_is_active(table_seg->mode))
@@ -737,31 +815,32 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 
 
         bh_assert(table_seg->table_index < module_inst->table_count);
         bh_assert(table_seg->table_index < module_inst->table_count);
 
 
-        tbl_inst = module_inst->tables[table_seg->table_index];
-        bh_assert(tbl_inst);
-
+        table = module_inst->tables[table_seg->table_index];
 #if WASM_ENABLE_REF_TYPES != 0
 #if WASM_ENABLE_REF_TYPES != 0
         bh_assert(
         bh_assert(
             table_seg->offset.init_expr_type
             table_seg->offset.init_expr_type
-                == (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
-                                         : INIT_EXPR_TYPE_I32_CONST)
+                == (table->is_table64 ? INIT_EXPR_TYPE_I64_CONST
+                                      : INIT_EXPR_TYPE_I32_CONST)
             || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
             || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
             || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
             || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
             || table_seg->offset.init_expr_type
             || table_seg->offset.init_expr_type
                    == INIT_EXPR_TYPE_REFNULL_CONST);
                    == INIT_EXPR_TYPE_REFNULL_CONST);
 #else
 #else
         bh_assert(table_seg->offset.init_expr_type
         bh_assert(table_seg->offset.init_expr_type
-                      == (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
-                                               : INIT_EXPR_TYPE_I32_CONST)
+                      == (table->is_table64 ? INIT_EXPR_TYPE_I64_CONST
+                                            : INIT_EXPR_TYPE_I32_CONST)
                   || table_seg->offset.init_expr_type
                   || table_seg->offset.init_expr_type
                          == INIT_EXPR_TYPE_GET_GLOBAL);
                          == INIT_EXPR_TYPE_GET_GLOBAL);
 #endif
 #endif
+        bh_assert(table);
 
 
         /* Resolve table data base offset */
         /* Resolve table data base offset */
         /* TODO: The table64 current implementation assumes table max size
         /* TODO: The table64 current implementation assumes table max size
          * UINT32_MAX, so the offset conversion here is safe */
          * UINT32_MAX, so the offset conversion here is safe */
+        uint32 base_offset;
         if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
         if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
-            global_index = table_seg->offset.u.global_index;
+            uint32 global_index = table_seg->offset.u.global_index;
+            uint32 global_data_offset;
 
 
             if (!check_global_init_expr(module, global_index, error_buf,
             if (!check_global_init_expr(module, global_index, error_buf,
                                         error_buf_size)) {
                                         error_buf_size)) {
@@ -784,7 +863,7 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 
 
         /* Copy table data */
         /* Copy table data */
         /* base_offset only since length might negative */
         /* base_offset only since length might negative */
-        if (base_offset > tbl_inst->cur_size) {
+        if (base_offset > table->cur_size) {
 #if WASM_ENABLE_REF_TYPES != 0
 #if WASM_ENABLE_REF_TYPES != 0
             set_error_buf(error_buf, error_buf_size,
             set_error_buf(error_buf, error_buf_size,
                           "out of bounds table access");
                           "out of bounds table access");
@@ -796,8 +875,8 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
         }
         }
 
 
         /* base_offset + length(could be zero) */
         /* base_offset + length(could be zero) */
-        length = table_seg->value_count;
-        if (base_offset + length > tbl_inst->cur_size) {
+        uint32 length = table_seg->value_count;
+        if (base_offset + length > table->cur_size) {
 #if WASM_ENABLE_REF_TYPES != 0
 #if WASM_ENABLE_REF_TYPES != 0
             set_error_buf(error_buf, error_buf_size,
             set_error_buf(error_buf, error_buf_size,
                           "out of bounds table access");
                           "out of bounds table access");
@@ -813,8 +892,10 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
          * will check the linked table inst owner in future
          * will check the linked table inst owner in future
          */
          */
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
-        for (j = 0; j < length; j++) {
-            tbl_inst->elems[base_offset + j] =
+        table_elem_type_t *table_elems =
+            aot_locate_table_elems(module, table, table_seg->table_index);
+        for (uint32 j = 0; j < length; j++) {
+            table_elems[base_offset + j] =
                 table_seg->init_values[j].u.ref_index;
                 table_seg->init_values[j].u.ref_index;
         }
         }
 #endif
 #endif
@@ -856,11 +937,34 @@ memory_deinstantiate(AOTMemoryInstance *memory)
 static void
 static void
 memories_deinstantiate(AOTModuleInstance *module_inst)
 memories_deinstantiate(AOTModuleInstance *module_inst)
 {
 {
-    if (!module_inst->memories)
+    if (!module_inst->memories) {
         return;
         return;
+    }
+
+    uint32 mem_index = 0;
+    AOTModule *module = (AOTModule *)module_inst->module;
+    for (; mem_index < module->import_memory_count; mem_index++) {
+        AOTMemoryInstance *memory = module_inst->memories[mem_index];
+        if (!memory) {
+            continue;
+        }
 
 
-    for (uint32 i = 0; i < module_inst->memory_count; i++) {
-        memory_deinstantiate(module_inst->memories[i]);
+        memory_deinstantiate(memory);
+
+#if WASM_ENABLE_MULTI_MODULE == 0 && WASM_ENABLE_SHARED_MEMORY != 0
+        /* for spawned only */
+        if (!shared_memory_is_shared(memory)) {
+            continue;
+        }
+
+        if (shared_memory_get_reference(memory) == 0) {
+            wasm_runtime_free(memory);
+        }
+#endif
+    }
+
+    for (; mem_index < module->memory_count; mem_index++) {
+        memory_deinstantiate(module_inst->memories[mem_index]);
     }
     }
 
 
     wasm_runtime_free(module_inst->memories);
     wasm_runtime_free(module_inst->memories);
@@ -958,7 +1062,7 @@ memory_instantiate(const AOTModule *module, AOTModuleInstance *parent,
                         < (uint64)num_bytes_per_page * init_page_count) {
                         < (uint64)num_bytes_per_page * init_page_count) {
             /* Insert app heap before __heap_base */
             /* Insert app heap before __heap_base */
             aux_heap_base = module->aux_heap_base;
             aux_heap_base = module->aux_heap_base;
-            bytes_of_last_page = aux_heap_base % num_bytes_per_page;
+            bytes_of_last_page = (uint32)(aux_heap_base % num_bytes_per_page);
             if (bytes_of_last_page == 0)
             if (bytes_of_last_page == 0)
                 bytes_of_last_page = num_bytes_per_page;
                 bytes_of_last_page = num_bytes_per_page;
             bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
             bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
@@ -968,7 +1072,7 @@ memory_instantiate(const AOTModule *module, AOTModuleInstance *parent,
             heap_offset = aux_heap_base;
             heap_offset = aux_heap_base;
             aux_heap_base += heap_size;
             aux_heap_base += heap_size;
 
 
-            bytes_of_last_page = aux_heap_base % num_bytes_per_page;
+            bytes_of_last_page = (uint32)(aux_heap_base % num_bytes_per_page);
             if (bytes_of_last_page == 0)
             if (bytes_of_last_page == 0)
                 bytes_of_last_page = num_bytes_per_page;
                 bytes_of_last_page = num_bytes_per_page;
             bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
             bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
@@ -1959,21 +2063,26 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
      */
      */
     for (i = 0; i != module->import_table_count; ++i) {
     for (i = 0; i != module->import_table_count; ++i) {
         table_size += offsetof(AOTTableInstance, elems);
         table_size += offsetof(AOTTableInstance, elems);
+#if WASM_ENABLE_MULTI_MODULE != 0
         table_size += (uint64)sizeof(table_elem_type_t)
         table_size += (uint64)sizeof(table_elem_type_t)
-                      * (uint64)aot_get_imp_tbl_data_slots(
-                          module->import_tables + i, false);
+                      * (uint64)aot_get_tbl_data_slots(
+                          &(module->import_tables + i)->table_type, false);
+#else
+        /* keep a reference to the imported table's elem */
+        table_size += sizeof(void *);
+#endif
     }
     }
 
 
     for (i = 0; i != module->table_count; ++i) {
     for (i = 0; i != module->table_count; ++i) {
         table_size += offsetof(AOTTableInstance, elems);
         table_size += offsetof(AOTTableInstance, elems);
-        table_size +=
-            (uint64)sizeof(table_elem_type_t)
-            * (uint64)aot_get_tbl_data_slots(module->tables + i, false);
+        table_size += (uint64)sizeof(table_elem_type_t)
+                      * (uint64)aot_get_tbl_data_slots(
+                          &((module->tables + i)->table_type), false);
     }
     }
     total_size += table_size;
     total_size += table_size;
 
 
     /* The offset of AOTModuleInstanceExtra, make it 8-byte aligned */
     /* The offset of AOTModuleInstanceExtra, make it 8-byte aligned */
-    total_size = (total_size + 7LL) & ~7LL;
+    total_size = (total_size + 7ULL) & ~7ULL;
     extra_info_offset = (uint32)total_size;
     extra_info_offset = (uint32)total_size;
     total_size += sizeof(AOTModuleInstanceExtra);
     total_size += sizeof(AOTModuleInstanceExtra);
 
 
@@ -2093,8 +2202,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     /* Initialize table info */
     /* Initialize table info */
     p += module->global_data_size;
     p += module->global_data_size;
     module_inst->table_count = module->table_count + module->import_table_count;
     module_inst->table_count = module->table_count + module->import_table_count;
-    if (!tables_instantiate(module_inst, module, (AOTTableInstance *)p,
-                            error_buf, error_buf_size))
+    if (!tables_instantiate(module_inst, module, (AOTTableInstance *)p, imports,
+                            import_count, error_buf, error_buf_size))
         goto fail;
         goto fail;
 
 
     /* Initialize memory space */
     /* Initialize memory space */
@@ -2187,7 +2296,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         table_inst = module_inst->tables[i];
         table_inst = module_inst->tables[i];
         bh_assert(table_inst);
         bh_assert(table_inst);
 
 
-        table_data = table_inst->elems;
+        table_data = aot_locate_table_elems(module, table_inst, i);
         bh_assert(table_data);
         bh_assert(table_data);
 
 
         for (j = 0; j < table_inst->cur_size; j++) {
         for (j = 0; j < table_inst->cur_size; j++) {
@@ -2217,7 +2326,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         table = module_inst->tables[table_init_data->table_index];
         table = module_inst->tables[table_init_data->table_index];
         bh_assert(table);
         bh_assert(table);
 
 
-        table_data = table->elems;
+        table_data =
+            aot_locate_table_elems(module, table, table_init_data->table_index);
         bh_assert(table_data);
         bh_assert(table_data);
 
 
         wasm_runtime_get_table_inst_elem_type(
         wasm_runtime_get_table_inst_elem_type(
@@ -2392,8 +2502,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
         wasm_runtime_free(extra->import_func_module_insts);
         wasm_runtime_free(extra->import_func_module_insts);
 #endif
 #endif
 
 
-    if (module_inst->tables)
-        wasm_runtime_free(module_inst->tables);
+    tables_deinstantiate(module_inst);
 
 
     if (module_inst->memories)
     if (module_inst->memories)
         memories_deinstantiate(module_inst);
         memories_deinstantiate(module_inst);
@@ -2451,6 +2560,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
 #if WASM_ENABLE_REF_TYPES != 0
 #if WASM_ENABLE_REF_TYPES != 0
     bh_bitmap_delete(common->elem_dropped);
     bh_bitmap_delete(common->elem_dropped);
 #endif
 #endif
+    (void)common;
 
 
     wasm_runtime_free(module_inst);
     wasm_runtime_free(module_inst);
 }
 }
@@ -3372,7 +3482,10 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
         goto fail;
         goto fail;
     }
     }
 
 
-    tbl_elem_val = ((table_elem_type_t *)tbl_inst->elems)[table_elem_idx];
+    table_elem_type_t *table_elems =
+        aot_locate_table_elems(aot_module, tbl_inst, tbl_idx);
+
+    tbl_elem_val = table_elems[table_elem_idx];
     if (tbl_elem_val == NULL_REF) {
     if (tbl_elem_val == NULL_REF) {
         aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT);
         aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT);
         goto fail;
         goto fail;
@@ -3793,6 +3906,7 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
     for (i = 0; i < module_inst->table_count; i++) {
     for (i = 0; i < module_inst->table_count; i++) {
         tbl_inst = module_inst->tables[i];
         tbl_inst = module_inst->tables[i];
         mem_conspn->tables_size += offsetof(AOTTableInstance, elems);
         mem_conspn->tables_size += offsetof(AOTTableInstance, elems);
+        /*TODO: correct import tables' elems */
         mem_conspn->tables_size += sizeof(uint32) * tbl_inst->max_size;
         mem_conspn->tables_size += sizeof(uint32) * tbl_inst->max_size;
     }
     }
 
 
@@ -3834,7 +3948,6 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
     AOTTableInstance *tbl_inst;
     AOTTableInstance *tbl_inst;
     AOTTableInitData *tbl_seg;
     AOTTableInitData *tbl_seg;
     const AOTModule *module = (AOTModule *)module_inst->module;
     const AOTModule *module = (AOTModule *)module_inst->module;
-    table_elem_type_t *table_elems;
     InitializerExpression *tbl_seg_init_values = NULL, *init_values;
     InitializerExpression *tbl_seg_init_values = NULL, *init_values;
     uint32 i, tbl_seg_len = 0;
     uint32 i, tbl_seg_len = 0;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
@@ -3865,7 +3978,9 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
         return;
         return;
     }
     }
 
 
-    table_elems = tbl_inst->elems + dst_offset;
+    table_elem_type_t *table_elems =
+        aot_locate_table_elems(module, tbl_inst, tbl_idx);
+    table_elems += dst_offset;
     init_values = tbl_seg_init_values + src_offset;
     init_values = tbl_seg_init_values + src_offset;
 
 
     for (i = 0; i < length; i++) {
     for (i = 0; i < length; i++) {
@@ -3909,16 +4024,21 @@ aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx,
         return;
         return;
     }
     }
 
 
+    table_elem_type_t *src_table_elems = aot_locate_table_elems(
+        (AOTModule *)module_inst->module, src_tbl_inst, src_tbl_idx);
+    src_table_elems += src_offset;
+
+    table_elem_type_t *dst_table_elems = aot_locate_table_elems(
+        (AOTModule *)module_inst->module, dst_tbl_inst, dst_tbl_idx);
+    dst_table_elems += dst_offset;
+
     /* if src_offset >= dst_offset, copy from front to back */
     /* if src_offset >= dst_offset, copy from front to back */
     /* if src_offset < dst_offset, copy from back to front */
     /* if src_offset < dst_offset, copy from back to front */
     /* merge all together */
     /* merge all together */
-    bh_memmove_s((uint8 *)dst_tbl_inst + offsetof(AOTTableInstance, elems)
-                     + dst_offset * sizeof(table_elem_type_t),
+    bh_memmove_s(dst_table_elems,
                  (dst_tbl_inst->cur_size - dst_offset)
                  (dst_tbl_inst->cur_size - dst_offset)
                      * sizeof(table_elem_type_t),
                      * sizeof(table_elem_type_t),
-                 (uint8 *)src_tbl_inst + offsetof(AOTTableInstance, elems)
-                     + src_offset * sizeof(table_elem_type_t),
-                 length * sizeof(table_elem_type_t));
+                 src_table_elems, length * sizeof(table_elem_type_t));
 }
 }
 
 
 void
 void
@@ -3935,8 +4055,11 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length,
         return;
         return;
     }
     }
 
 
+    table_elem_type_t *table_elems = aot_locate_table_elems(
+        (AOTModule *)module_inst->module, tbl_inst, tbl_idx);
+
     for (; length != 0; data_offset++, length--) {
     for (; length != 0; data_offset++, length--) {
-        tbl_inst->elems[data_offset] = val;
+        table_elems[data_offset] = val;
     }
     }
 }
 }
 
 
@@ -3978,8 +4101,11 @@ aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 inc_size,
     }
     }
 
 
     /* fill in */
     /* fill in */
+    table_elem_type_t *table_elems = aot_locate_table_elems(
+        (AOTModule *)module_inst->module, tbl_inst, tbl_idx);
+
     for (i = 0; i < inc_size; ++i) {
     for (i = 0; i < inc_size; ++i) {
-        tbl_inst->elems[tbl_inst->cur_size + i] = init_val;
+        table_elems[tbl_inst->cur_size + i] = init_val;
     }
     }
 
 
     tbl_inst->cur_size = total_size;
     tbl_inst->cur_size = total_size;
@@ -5199,6 +5325,7 @@ aot_global_traverse_gc_rootset(AOTModuleInstance *module_inst, void *heap)
 static bool
 static bool
 aot_table_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap)
 aot_table_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap)
 {
 {
+    AOTModule *module = (AOTModule *)module_inst->module;
     AOTTableInstance **tables = (AOTTableInstance **)module_inst->tables;
     AOTTableInstance **tables = (AOTTableInstance **)module_inst->tables;
     AOTTableInstance *table;
     AOTTableInstance *table;
     uint32 table_count = module_inst->table_count, i, j;
     uint32 table_count = module_inst->table_count, i, j;
@@ -5206,7 +5333,9 @@ aot_table_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap)
 
 
     for (i = 0; i < table_count; i++) {
     for (i = 0; i < table_count; i++) {
         table = tables[i];
         table = tables[i];
-        table_elems = (WASMObjectRef *)table->elems;
+
+        table_elems = (WASMObjectRef *)aot_locate_table_elems(module, table, i);
+
         for (j = 0; j < table->cur_size; j++) {
         for (j = 0; j < table->cur_size; j++) {
             gc_obj = table_elems[j];
             gc_obj = table_elems[j];
             if (wasm_obj_is_created_from_heap(gc_obj)) {
             if (wasm_obj_is_created_from_heap(gc_obj)) {
@@ -5343,7 +5472,7 @@ aot_const_str_set_insert(const uint8 *str, int32 len, AOTModule *module,
     else
     else
 #endif
 #endif
     {
     {
-        bh_memcpy_s(c_str, len, str, (uint32)len);
+        bh_memcpy_s(c_str, (uint32)len, str, (uint32)len);
     }
     }
 
 
     if ((value = bh_hash_map_find(set, c_str))) {
     if ((value = bh_hash_map_find(set, c_str))) {
@@ -5381,7 +5510,7 @@ aot_set_module_name(AOTModule *module, const char *name, char *error_buf,
         return false;
         return false;
 
 
     module->name = aot_const_str_set_insert((const uint8 *)name,
     module->name = aot_const_str_set_insert((const uint8 *)name,
-                                            (uint32)(strlen(name) + 1), module,
+                                            (int32)(strlen(name) + 1), module,
 #if (WASM_ENABLE_WORD_ALIGN_READ != 0)
 #if (WASM_ENABLE_WORD_ALIGN_READ != 0)
                                             false,
                                             false,
 #endif
 #endif
@@ -5535,20 +5664,25 @@ aot_resolve_import_func(AOTModule *module, AOTImportFunc *import_func)
  */
  */
 int32
 int32
 aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst,
 aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst,
-                    WASMExternInstance *out, int32 out_len)
+                    WASMExternInstance *out, uint32 out_len)
 {
 {
     if (!module || !inst || !out)
     if (!module || !inst || !out)
         return -1;
         return -1;
 
 
-    int32 spawned_import_count =
+    int32 spawned_import_count_s =
         wasm_runtime_get_import_count((WASMModuleCommon *)module);
         wasm_runtime_get_import_count((WASMModuleCommon *)module);
+    if (spawned_import_count_s < 0) {
+        return -1;
+    }
+
+    uint32 spawned_import_count = spawned_import_count_s;
     if (spawned_import_count > out_len) {
     if (spawned_import_count > out_len) {
         LOG_WARNING("The number of imported functions is more than the "
         LOG_WARNING("The number of imported functions is more than the "
                     "length of provided buffer ");
                     "length of provided buffer ");
         return -1;
         return -1;
     }
     }
 
 
-    for (int32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) {
+    for (uint32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) {
         wasm_import_t import_type = { 0 };
         wasm_import_t import_type = { 0 };
 
 
         wasm_runtime_get_import_type((WASMModuleCommon *)module, i,
         wasm_runtime_get_import_type((WASMModuleCommon *)module, i,
@@ -5577,20 +5711,21 @@ aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst,
 
 
 void
 void
 aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports,
 aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports,
-                       int32 import_count)
+                       uint32 import_count)
 {
 {
     if (!module || !imports)
     if (!module || !imports)
         return;
         return;
 
 
     int32 spawned_import_count =
     int32 spawned_import_count =
         wasm_runtime_get_import_count((WASMModuleCommon *)module);
         wasm_runtime_get_import_count((WASMModuleCommon *)module);
-    if (spawned_import_count > import_count) {
+    if (spawned_import_count < 0
+        || (uint32)spawned_import_count > import_count) {
         LOG_WARNING("The number of imported functions is more than the "
         LOG_WARNING("The number of imported functions is more than the "
                     "length of provided buffer ");
                     "length of provided buffer ");
         return;
         return;
     }
     }
 
 
-    for (int32 i = 0; i < import_count; i++) {
+    for (uint32 i = 0; i < import_count; i++) {
         WASMExternInstance *import = imports + i;
         WASMExternInstance *import = imports + i;
 
 
         if (import->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
         if (import->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
@@ -5608,3 +5743,42 @@ aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports,
     }
     }
 }
 }
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
+
+AOTTableInstance *
+aot_create_table(const AOTModule *module, const AOTTableType *type)
+{
+    uint32 max_size = aot_get_tbl_data_slots(type, false);
+    uint64 table_size = offsetof(AOTTableInstance, elems)
+                        + sizeof(table_elem_type_t) * (uint64)max_size;
+
+    AOTTableInstance *table = runtime_malloc(table_size, NULL, 0);
+    if (!table) {
+        return NULL;
+    }
+
+    table->cur_size = type->init_size;
+    table->elem_type = type->elem_type;
+    table->max_size = max_size;
+#if WASM_ENABLE_GC != 0
+    table->elem_ref_type.elem_ref_type = type->elem_ref_type;
+#endif
+
+    /* Set all elements to -1 or NULL_REF to mark them as uninitialized
+     * elements */
+#if WASM_ENABLE_GC == 0
+    memset(table->elems, 0xff, sizeof(table_elem_type_t) * table->max_size);
+#else
+    memset(table->elems, 0x00, sizeof(table_elem_type_t) * table->max_size);
+#endif
+
+    return table;
+}
+
+void
+aot_destroy_table(AOTTableInstance *table)
+{
+    if (!table)
+        return;
+
+    wasm_runtime_free(table);
+}

+ 28 - 2
core/iwasm/aot/aot_runtime.h

@@ -35,6 +35,7 @@ extern "C" {
  * and not at the beginning of each function call */
  * and not at the beginning of each function call */
 #define WASM_FEATURE_FRAME_PER_FUNCTION (1 << 12)
 #define WASM_FEATURE_FRAME_PER_FUNCTION (1 << 12)
 #define WASM_FEATURE_FRAME_NO_FUNC_IDX (1 << 13)
 #define WASM_FEATURE_FRAME_NO_FUNC_IDX (1 << 13)
+#define WASM_FEATURE_MULTI_MODULE (1 << 14)
 
 
 typedef enum AOTSectionType {
 typedef enum AOTSectionType {
     AOT_SECTION_TYPE_TARGET_INFO = 0,
     AOT_SECTION_TYPE_TARGET_INFO = 0,
@@ -484,6 +485,21 @@ typedef struct LLVMProfileData_64 {
 } LLVMProfileData_64;
 } LLVMProfileData_64;
 #endif /* end of WASM_ENABLE_STATIC_PGO != 0 */
 #endif /* end of WASM_ENABLE_STATIC_PGO != 0 */
 
 
+static inline table_elem_type_t *
+aot_locate_table_elems(const AOTModule *module, AOTTableInstance *table,
+                       uint32 table_index)
+{
+#if WASM_ENABLE_MULTI_MODULE == 0
+    if (table_index < module->import_table_count) {
+        table_elem_type_t **table_elems =
+            (table_elem_type_t **)(uintptr_t)table->elems;
+
+        return *table_elems;
+    }
+#endif
+    return table->elems;
+}
+
 /**
 /**
  * Load a AOT module from aot file buffer
  * Load a AOT module from aot file buffer
  * @param buf the byte buffer which contains the AOT file data
  * @param buf the byte buffer which contains the AOT file data
@@ -884,13 +900,23 @@ aot_get_module_name(AOTModule *module);
 #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0
 #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0
 int32
 int32
 aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst,
 aot_inherit_imports(AOTModule *module, AOTModuleInstance *inst,
-                    WASMExternInstance *out, int32 out_len);
+                    WASMExternInstance *out, uint32 out_len);
 
 
 void
 void
 aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports,
 aot_disinherit_imports(AOTModule *module, WASMExternInstance *imports,
-                       int32 import_count);
+                       uint32 import_count);
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
 
 
+AOTTableInstance *
+aot_create_table(const AOTModule *module, const AOTTableType *type);
+
+bool
+aot_set_table_elem(const AOTModule *module, AOTTableInstance *table,
+                   uint32 index, uint32 func_idx);
+
+void
+aot_destroy_table(AOTTableInstance *table);
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 } /* end of extern "C" */
 } /* end of extern "C" */
 #endif
 #endif

+ 28 - 14
core/iwasm/common/wasm_c_api.c

@@ -4011,24 +4011,34 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
 
 
 #if WASM_ENABLE_INTERP != 0
 #if WASM_ENABLE_INTERP != 0
     if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
     if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
-        WASMTableInstance *table_interp =
-            ((WASMModuleInstance *)table->inst_comm_rt)
-                ->tables[table->table_idx_rt];
-        if (index >= table_interp->cur_size) {
+        WASMModuleInstance *inst_wasm =
+            (WASMModuleInstance *)table->inst_comm_rt;
+        WASMModule *module_wasm = inst_wasm->module;
+        WASMTableInstance *table_wasm = inst_wasm->tables[table->table_idx_rt];
+
+        if (index >= table_wasm->cur_size) {
             return NULL;
             return NULL;
         }
         }
-        ref_idx = (uint32)table_interp->elems[index];
+
+        table_elem_type_t *table_elems = wasm_locate_table_elems(
+            module_wasm, table_wasm, table->table_idx_rt);
+        ref_idx = (uint32)table_elems[index];
     }
     }
 #endif
 #endif
 
 
 #if WASM_ENABLE_AOT != 0
 #if WASM_ENABLE_AOT != 0
     if (table->inst_comm_rt->module_type == Wasm_Module_AoT) {
     if (table->inst_comm_rt->module_type == Wasm_Module_AoT) {
         AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt;
         AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt;
+        AOTModule *module_aot = (AOTModule *)inst_aot->module;
         AOTTableInstance *table_aot = inst_aot->tables[table->table_idx_rt];
         AOTTableInstance *table_aot = inst_aot->tables[table->table_idx_rt];
+
         if (index >= table_aot->cur_size) {
         if (index >= table_aot->cur_size) {
             return NULL;
             return NULL;
         }
         }
-        ref_idx = (uint32)table_aot->elems[index];
+
+        table_elem_type_t *table_elems =
+            aot_locate_table_elems(module_aot, table_aot, table->table_idx_rt);
+        ref_idx = (uint32)table_elems[index];
     }
     }
 #endif
 #endif
 
 
@@ -4080,17 +4090,19 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
 
 
 #if WASM_ENABLE_INTERP != 0
 #if WASM_ENABLE_INTERP != 0
     if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
     if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
-        WASMTableInstance *table_interp =
-            ((WASMModuleInstance *)table->inst_comm_rt)
-                ->tables[table->table_idx_rt];
+        WASMModuleInstance *inst_wasm =
+            (WASMModuleInstance *)table->inst_comm_rt;
+        WASMModule *module_wasm = inst_wasm->module;
+        WASMTableInstance *table_wasm = inst_wasm->tables[table->table_idx_rt];
 
 
-        if (index >= table_interp->cur_size) {
+        if (index >= table_wasm->cur_size) {
             return false;
             return false;
         }
         }
 
 
-        p_ref_idx = (uint32 *)(table_interp->elems + index);
-        function_count =
-            ((WASMModuleInstance *)table->inst_comm_rt)->e->function_count;
+        table_elem_type_t *table_elems = wasm_locate_table_elems(
+            module_wasm, table_wasm, table->table_idx_rt);
+        p_ref_idx = (uint32 *)(table_elems + index);
+        function_count = inst_wasm->e->function_count;
     }
     }
 #endif
 #endif
 
 
@@ -4104,7 +4116,9 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
             return false;
             return false;
         }
         }
 
 
-        p_ref_idx = (uint32 *)(table_aot->elems + index);
+        table_elem_type_t *table_elems =
+            aot_locate_table_elems(module_aot, table_aot, table->table_idx_rt);
+        p_ref_idx = (uint32 *)(table_elems + index);
         function_count = module_aot->func_count;
         function_count = module_aot->func_count;
     }
     }
 #endif
 #endif

+ 250 - 101
core/iwasm/common/wasm_runtime_common.c

@@ -454,6 +454,55 @@ wasm_runtime_get_exec_env_tls()
 }
 }
 #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
 #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
 
 
+/* FIXME: remove when merging wasm_table_inst_t with WASMTableInstance and
+ * AOTTableInstance */
+#if WASM_ENABLE_INTERP != 0
+static void
+WASMTableInstance_to_wasm_table_inst_t(const WASMModule *module,
+                                       const WASMTableInstance *table_rt,
+                                       int64 table_index,
+                                       wasm_table_inst_t *out)
+{
+    out->elem_kind = val_type_to_val_kind(table_rt->elem_type);
+    out->max_size = table_rt->max_size;
+    out->cur_size = table_rt->cur_size;
+
+    /* table_index < 0, it means it is created by host */
+    uintptr_t tmp = (uintptr_t)table_rt->elems;
+    if (table_index > 0 && table_index < (int64)module->import_table_count) {
+        out->elems = *(void **)tmp;
+    }
+    else {
+        out->elems = (void *)tmp;
+    }
+
+    bh_assert(out->elems);
+}
+#endif
+
+#if WASM_ENABLE_AOT != 0
+static void
+AOTTableInstance_to_wasm_table_inst_t(const AOTModule *module,
+                                      const AOTTableInstance *table_rt,
+                                      int64 table_index, wasm_table_inst_t *out)
+{
+    out->elem_kind = val_type_to_val_kind(table_rt->elem_type);
+    out->max_size = table_rt->max_size;
+    out->cur_size = table_rt->cur_size;
+
+    /* table_index < 0, it means it is created by host */
+    uintptr_t tmp = (uintptr_t)table_rt->elems;
+    if (table_index > 0 && table_index < (int64)module->import_table_count) {
+        out->elems = *(void **)tmp;
+    }
+    else {
+        out->elems = (void *)tmp;
+    }
+
+    bh_assert(out->elems);
+}
+#endif
+
 static bool
 static bool
 wasm_runtime_env_init(void)
 wasm_runtime_env_init(void)
 {
 {
@@ -2122,20 +2171,23 @@ wasm_runtime_get_export_table_inst(WASMModuleInstanceCommon *const module_inst,
         const WASMModuleInstance *wasm_module_inst =
         const WASMModuleInstance *wasm_module_inst =
             (const WASMModuleInstance *)module_inst;
             (const WASMModuleInstance *)module_inst;
         const WASMModule *wasm_module = wasm_module_inst->module;
         const WASMModule *wasm_module = wasm_module_inst->module;
-        uint32 i;
-        for (i = 0; i < wasm_module->export_count; i++) {
+
+        for (uint32 i = 0; i < wasm_module->export_count; i++) {
             const WASMExport *wasm_export = &wasm_module->exports[i];
             const WASMExport *wasm_export = &wasm_module->exports[i];
-            if ((wasm_export->kind == WASM_IMPORT_EXPORT_KIND_TABLE)
-                && !strcmp(wasm_export->name, name)) {
-                const WASMTableInstance *wasm_table_inst =
-                    wasm_module_inst->tables[wasm_export->index];
-                table_inst->elem_kind =
-                    val_type_to_val_kind(wasm_table_inst->elem_type);
-                table_inst->cur_size = wasm_table_inst->cur_size;
-                table_inst->max_size = wasm_table_inst->max_size;
-                table_inst->elems = (void *)wasm_table_inst->elems;
-                return true;
+
+            if (wasm_export->kind != WASM_IMPORT_EXPORT_KIND_TABLE) {
+                continue;
             }
             }
+
+            if (strcmp(wasm_export->name, name)) {
+                continue;
+            }
+
+            const WASMTableInstance *wasm_table_inst =
+                wasm_module_inst->tables[wasm_export->index];
+            WASMTableInstance_to_wasm_table_inst_t(
+                wasm_module, wasm_table_inst, wasm_export->index, table_inst);
+            return true;
         }
         }
     }
     }
 #endif
 #endif
@@ -2144,20 +2196,23 @@ wasm_runtime_get_export_table_inst(WASMModuleInstanceCommon *const module_inst,
         const AOTModuleInstance *aot_module_inst =
         const AOTModuleInstance *aot_module_inst =
             (AOTModuleInstance *)module_inst;
             (AOTModuleInstance *)module_inst;
         const AOTModule *aot_module = (AOTModule *)aot_module_inst->module;
         const AOTModule *aot_module = (AOTModule *)aot_module_inst->module;
-        uint32 i;
-        for (i = 0; i < aot_module->export_count; i++) {
+
+        for (uint32 i = 0; i < aot_module->export_count; i++) {
             const AOTExport *aot_export = &aot_module->exports[i];
             const AOTExport *aot_export = &aot_module->exports[i];
-            if ((aot_export->kind == WASM_IMPORT_EXPORT_KIND_TABLE)
-                && !strcmp(aot_export->name, name)) {
-                const AOTTableInstance *aot_table_inst =
-                    aot_module_inst->tables[aot_export->index];
-                table_inst->elem_kind =
-                    val_type_to_val_kind(aot_table_inst->elem_type);
-                table_inst->cur_size = aot_table_inst->cur_size;
-                table_inst->max_size = aot_table_inst->max_size;
-                table_inst->elems = (void *)aot_table_inst->elems;
-                return true;
+
+            if (aot_export->kind != WASM_IMPORT_EXPORT_KIND_TABLE) {
+                continue;
+            }
+
+            if (strcmp(aot_export->name, name)) {
+                continue;
             }
             }
+
+            const AOTTableInstance *aot_table_inst =
+                aot_module_inst->tables[aot_export->index];
+            AOTTableInstance_to_wasm_table_inst_t(
+                aot_module, aot_table_inst, aot_export->index, table_inst);
+            return true;
         }
         }
     }
     }
 #endif
 #endif
@@ -4102,8 +4157,8 @@ wasm_runtime_get_import_count(WASMModuleCommon *const module)
 }
 }
 
 
 void
 void
-wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
-                             wasm_import_t *import_type)
+wasm_runtime_get_import_type(WASMModuleCommon *const module,
+                             uint32 import_index, wasm_import_t *import_type)
 {
 {
     if (!import_type) {
     if (!import_type) {
         bh_assert(0);
         bh_assert(0);
@@ -4121,7 +4176,7 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
     if (module->module_type == Wasm_Module_AoT) {
     if (module->module_type == Wasm_Module_AoT) {
         const AOTModule *aot_module = (const AOTModule *)module;
         const AOTModule *aot_module = (const AOTModule *)module;
 
 
-        uint32 func_index = (uint32)import_index;
+        uint32 func_index = import_index;
         if (func_index < aot_module->import_func_count) {
         if (func_index < aot_module->import_func_count) {
             const AOTImportFunc *aot_import_func =
             const AOTImportFunc *aot_import_func =
                 &aot_module->import_funcs[func_index];
                 &aot_module->import_funcs[func_index];
@@ -4182,7 +4237,7 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
     if (module->module_type == Wasm_Module_Bytecode) {
     if (module->module_type == Wasm_Module_Bytecode) {
         const WASMModule *wasm_module = (const WASMModule *)module;
         const WASMModule *wasm_module = (const WASMModule *)module;
 
 
-        if ((uint32)import_index >= wasm_module->import_count) {
+        if (import_index >= wasm_module->import_count) {
             bh_assert(0);
             bh_assert(0);
             return;
             return;
         }
         }
@@ -6470,7 +6525,6 @@ static void
 interp_mark_all_externrefs(WASMModuleInstance *module_inst)
 interp_mark_all_externrefs(WASMModuleInstance *module_inst)
 {
 {
     uint32 i, j, externref_idx;
     uint32 i, j, externref_idx;
-    table_elem_type_t *table_data;
     uint8 *global_data = module_inst->global_data;
     uint8 *global_data = module_inst->global_data;
     WASMGlobalInstance *global;
     WASMGlobalInstance *global;
     WASMTableInstance *table;
     WASMTableInstance *table;
@@ -6493,9 +6547,11 @@ interp_mark_all_externrefs(WASMModuleInstance *module_inst)
             &max_size);
             &max_size);
 
 
         if (elem_type == VALUE_TYPE_EXTERNREF) {
         if (elem_type == VALUE_TYPE_EXTERNREF) {
-            table_data = table->elems;
+            table_elem_type_t *table_elems =
+                wasm_locate_table_elems(module_inst->module, table, i);
+
             for (j = 0; j < table->cur_size; j++) {
             for (j = 0; j < table->cur_size; j++) {
-                externref_idx = table_data[j];
+                externref_idx = (uint32)table_elems[j];
                 mark_externref(externref_idx);
                 mark_externref(externref_idx);
             }
             }
         }
         }
@@ -6513,7 +6569,7 @@ aot_mark_all_externrefs(AOTModuleInstance *module_inst)
     const AOTModule *module = (AOTModule *)module_inst->module;
     const AOTModule *module = (AOTModule *)module_inst->module;
     const AOTTable *table = module->tables;
     const AOTTable *table = module->tables;
     const AOTGlobal *global = module->globals;
     const AOTGlobal *global = module->globals;
-    const AOTTableInstance *table_inst;
+    AOTTableInstance *table_inst;
 
 
     for (i = 0; i < module->global_count; i++, global++) {
     for (i = 0; i < module->global_count; i++, global++) {
         if (global->type.val_type == VALUE_TYPE_EXTERNREF) {
         if (global->type.val_type == VALUE_TYPE_EXTERNREF) {
@@ -6525,8 +6581,11 @@ aot_mark_all_externrefs(AOTModuleInstance *module_inst)
     for (i = 0; i < module->table_count; i++) {
     for (i = 0; i < module->table_count; i++) {
         table_inst = module_inst->tables[i];
         table_inst = module_inst->tables[i];
         if ((table + i)->table_type.elem_type == VALUE_TYPE_EXTERNREF) {
         if ((table + i)->table_type.elem_type == VALUE_TYPE_EXTERNREF) {
+            table_elem_type_t *table_elems =
+                aot_locate_table_elems(module, table_inst, i);
+
             while (j < table_inst->cur_size) {
             while (j < table_inst->cur_size) {
-                mark_externref(table_inst->elems[j++]);
+                mark_externref(table_elems[j++]);
             }
             }
         }
         }
     }
     }
@@ -7759,6 +7818,99 @@ wasm_runtime_is_underlying_binary_freeable(WASMModuleCommon *const module)
     return true;
     return true;
 }
 }
 
 
+wasm_table_inst_t *
+wasm_runtime_create_table(WASMModuleCommon *const module,
+                          wasm_table_type_t const type)
+{
+    if (!module || !type)
+        return NULL;
+
+#if WASM_ENABLE_INTERP != 0
+    if (module->module_type == Wasm_Module_Bytecode) {
+        wasm_table_inst_t *out_table =
+            runtime_malloc(sizeof(wasm_table_inst_t), NULL, NULL, 0);
+        if (!out_table)
+            return NULL;
+
+        WASMTableInstance *wasm_table =
+            wasm_create_table((WASMModule *)module, type);
+        if (!wasm_table) {
+            wasm_runtime_free(wasm_table);
+            return NULL;
+        }
+
+        WASMTableInstance_to_wasm_table_inst_t((WASMModule *)module, wasm_table,
+                                               -1, out_table);
+        /* TODO: wasm_table ownership ?*/
+        return out_table;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (module->module_type == Wasm_Module_AoT) {
+        wasm_table_inst_t *out_table =
+            runtime_malloc(sizeof(wasm_table_inst_t), NULL, NULL, 0);
+        if (!out_table)
+            return NULL;
+
+        AOTTableInstance *aot_table =
+            aot_create_table((AOTModule *)module, type);
+        if (!aot_table) {
+            wasm_runtime_free(aot_table);
+            return NULL;
+        }
+
+        AOTTableInstance_to_wasm_table_inst_t((AOTModule *)module, aot_table,
+                                              -1, out_table);
+        /* TODO: aot_table ownership ?*/
+        return out_table;
+    }
+#endif
+
+    LOG_ERROR("create table failed, invalid module type");
+    return NULL;
+}
+
+void
+wasm_runtime_destroy_table(WASMModuleCommon *const module,
+                           wasm_table_inst_t *table)
+{
+    if (!module || !table)
+        return;
+
+#if WASM_ENABLE_INTERP != 0
+    if (module->module_type == Wasm_Module_Bytecode) {
+        /*
+         * TODO: for now we only release the shell itself
+         * but after optimize the wasm_table_inst_t in wasm_export.h
+         * we shall focus on wasm_table itself
+         */
+        // void *wasm_table =
+        //     (void *)((uint8 *)table - offsetof(WASMTableInstance, elems));
+        // wasm_destroy_table((WASMTableInstance *)wasm_table);
+        wasm_runtime_free(table);
+        return;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (module->module_type == Wasm_Module_AoT) {
+        /*
+         * TODO: for now we only release the shell itself
+         * but after optimize the wasm_table_inst_t in wasm_export.h
+         * we shall focus on aot_table itself
+         */
+        // void *aot_table =
+        //     (void *)((uint8 *)table - offsetof(AOTTableInstance, elems));
+        // aot_destroy_table((AOTTableInstance *)aot_table);
+        wasm_runtime_free(table);
+        return;
+    }
+#endif
+
+    LOG_ERROR("destroy table failed, invalid module type");
+}
+
 /*TODO: take us(below) out when have a linker */
 /*TODO: take us(below) out when have a linker */
 WASMModuleInstanceCommon *
 WASMModuleInstanceCommon *
 wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module,
 wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module,
@@ -7766,14 +7918,15 @@ wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module,
                                              uint32 heap_size, char *error_buf,
                                              uint32 heap_size, char *error_buf,
                                              uint32 error_buf_size)
                                              uint32 error_buf_size)
 {
 {
-    int32 import_count = 0;
+    int32 import_count_s = 0;
     WASMExternInstance *imports = NULL;
     WASMExternInstance *imports = NULL;
 
 
-    import_count = wasm_runtime_get_import_count(module);
-    if (import_count < 0) {
+    import_count_s = wasm_runtime_get_import_count(module);
+    if (import_count_s < 0) {
         return NULL;
         return NULL;
     }
     }
 
 
+    uint32 import_count = (uint32)import_count_s;
     if (import_count) {
     if (import_count) {
         imports =
         imports =
             runtime_malloc(sizeof(WASMExternInstance) * (uint64)import_count,
             runtime_malloc(sizeof(WASMExternInstance) * (uint64)import_count,
@@ -7797,6 +7950,18 @@ wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module,
         0, // max_memory_pages
         0, // max_memory_pages
         imports, (uint32)import_count, error_buf, error_buf_size);
         imports, (uint32)import_count, error_buf, error_buf_size);
 
 
+    /*
+     * during wasm_instantiate()/aot_instantiate()
+     *
+     * WASModuleInstance->memories[i] takes the ownership of
+     * WASMExternInstance->u.memory
+     *
+     * WASModuleInstance->tables[i].elems takes
+     * the ownership of WASMExternInstance->u.table
+     *
+     * WASMModuleInstance->e->globals[i] copies the content of
+     * WASMExternInstance->u.global
+     */
     if (imports) {
     if (imports) {
         wasm_runtime_free(imports);
         wasm_runtime_free(imports);
     }
     }
@@ -7806,30 +7971,40 @@ wasm_runtime_instantiate_with_builtin_linker(WASMModuleCommon *module,
 
 
 bool
 bool
 wasm_runtime_create_extern_inst(WASMModuleCommon *module,
 wasm_runtime_create_extern_inst(WASMModuleCommon *module,
-                                wasm_import_t import_type,
+                                wasm_import_t *import_type,
                                 WASMExternInstance *out)
                                 WASMExternInstance *out)
 {
 {
     if (!out)
     if (!out)
         return false;
         return false;
 
 
-    LOG_DEBUG("create import(%s,%s) kind %d", import_type.module_name,
-              import_type.name, import_type.kind);
+    LOG_DEBUG("create import(%s,%s) kind %d", import_type->module_name,
+              import_type->name, import_type->kind);
 
 
-    out->module_name = import_type.module_name;
-    out->field_name = import_type.name;
-    out->kind = import_type.kind;
+    out->module_name = import_type->module_name;
+    out->field_name = import_type->name;
+    out->kind = import_type->kind;
 
 
-    if (import_type.kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
+    if (import_type->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
         out->u.memory =
         out->u.memory =
-            wasm_runtime_create_memory(module, import_type.u.memory_type);
+            wasm_runtime_create_memory(module, import_type->u.memory_type);
         if (!out->u.memory) {
         if (!out->u.memory) {
             LOG_ERROR("create memory failed\n");
             LOG_ERROR("create memory failed\n");
             return false;
             return false;
         }
         }
     }
     }
+    else if (import_type->kind == WASM_IMPORT_EXPORT_KIND_TABLE) {
+        wasm_table_inst_t *table =
+            wasm_runtime_create_table(module, import_type->u.table_type);
+        out->u.table = table;
+        if (!out->u.table) {
+            LOG_ERROR("create table failed\n");
+            return false;
+        }
+    }
     else {
     else {
         LOG_DEBUG("unimplemented import(%s,%s) kind %d",
         LOG_DEBUG("unimplemented import(%s,%s) kind %d",
-                  import_type.module_name, import_type.name, import_type.kind);
+                  import_type->module_name, import_type->name,
+                  import_type->kind);
     }
     }
 
 
     return true;
     return true;
@@ -7856,37 +8031,6 @@ wasm_runtime_destroy_extern_inst(WASMModuleCommon *module,
     extern_inst->field_name = NULL;
     extern_inst->field_name = NULL;
 }
 }
 
 
-/*
- * willn't take the ownership of new_extern_inst
- * take the ownership of the content of new_extern_inst
- */
-bool
-wasm_runtime_overwirte_imports(WASMModuleCommon *module,
-                               WASMExternInstance *orig_extern_inst_list,
-                               WASMExternInstance *new_extern_inst, int32 index)
-{
-    // argument check
-    if (!module || !orig_extern_inst_list || !new_extern_inst) {
-        return false;
-    }
-
-    // check index with the import count of the module
-    if (index < 0 || index >= wasm_runtime_get_import_count(module)) {
-        return false;
-    }
-
-    // get the targeted extern_inst. allow to be NULL
-    WASMExternInstance *old_extern_inst = orig_extern_inst_list + index;
-
-    // release the targeted extern_inst if not NULL
-    wasm_runtime_destroy_extern_inst(module, old_extern_inst);
-
-    // overwrite the targeted extern_inst
-    bh_memcpy_s(old_extern_inst, sizeof(WASMExternInstance), new_extern_inst,
-                sizeof(WASMExternInstance));
-    return true;
-}
-
 /*
 /*
  * Be aware that it will remove all items in the list, regardless of whether
  * Be aware that it will remove all items in the list, regardless of whether
  * they were created by the runtime (for built-ins) or by users.
  * they were created by the runtime (for built-ins) or by users.
@@ -7907,23 +8051,24 @@ wasm_runtime_destroy_imports(WASMModuleCommon *module,
 bool
 bool
 wasm_runtime_create_imports(WASMModuleCommon *module,
 wasm_runtime_create_imports(WASMModuleCommon *module,
                             bool (*module_name_filter)(const char *),
                             bool (*module_name_filter)(const char *),
-                            WASMExternInstance *out, int32 out_len)
+                            WASMExternInstance *out, uint32 out_len)
 {
 {
-    int32 import_count = wasm_runtime_get_import_count(module);
+    int32 import_count_s = wasm_runtime_get_import_count(module);
 
 
-    if (import_count < 0)
+    if (import_count_s < 0)
         return false;
         return false;
 
 
-    if (import_count == 0)
+    if (import_count_s == 0)
         return true;
         return true;
 
 
+    uint32 import_count = (uint32)import_count_s;
     if (!out || out_len < import_count) {
     if (!out || out_len < import_count) {
         LOG_ERROR("invalid arguments");
         LOG_ERROR("invalid arguments");
         return false;
         return false;
     }
     }
 
 
-    memset(out, 0, sizeof(WASMExternInstance) * (uint32)import_count);
-    for (int32 i = 0; i < import_count; i++) {
+    memset(out, 0, sizeof(WASMExternInstance) * import_count);
+    for (uint32 i = 0; i < import_count; i++) {
         wasm_import_t import_type = { 0 };
         wasm_import_t import_type = { 0 };
         wasm_runtime_get_import_type(module, i, &import_type);
         wasm_runtime_get_import_type(module, i, &import_type);
 
 
@@ -7935,7 +8080,7 @@ wasm_runtime_create_imports(WASMModuleCommon *module,
         }
         }
 
 
         WASMExternInstance *extern_instance = out + i;
         WASMExternInstance *extern_instance = out + i;
-        if (!wasm_runtime_create_extern_inst(module, import_type,
+        if (!wasm_runtime_create_extern_inst(module, &import_type,
                                              extern_instance)) {
                                              extern_instance)) {
             wasm_runtime_destroy_imports(module, out);
             wasm_runtime_destroy_imports(module, out);
             LOG_ERROR("create import failed");
             LOG_ERROR("create import failed");
@@ -7948,7 +8093,8 @@ wasm_runtime_create_imports(WASMModuleCommon *module,
 
 
 bool
 bool
 wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module,
 wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module,
-                                         WASMExternInstance *out, int32 out_len)
+                                         WASMExternInstance *out,
+                                         uint32 out_len)
 {
 {
     LOG_DEBUG("create imports with builtin");
     LOG_DEBUG("create imports with builtin");
     return wasm_runtime_create_imports(module, wasm_runtime_is_built_in_module,
     return wasm_runtime_create_imports(module, wasm_runtime_is_built_in_module,
@@ -7964,7 +8110,7 @@ wasm_runtime_create_imports_with_builtin(WASMModuleCommon *module,
 static int32
 static int32
 wasm_runtime_inherit_imports(WASMModuleCommon *module,
 wasm_runtime_inherit_imports(WASMModuleCommon *module,
                              WASMModuleInstanceCommon *inst,
                              WASMModuleInstanceCommon *inst,
-                             WASMExternInstance *out, int32 out_len)
+                             WASMExternInstance *out, uint32 out_len)
 {
 {
 #if WASM_ENABLE_INTERP != 0
 #if WASM_ENABLE_INTERP != 0
     if (module->module_type == Wasm_Module_Bytecode) {
     if (module->module_type == Wasm_Module_Bytecode) {
@@ -7988,25 +8134,28 @@ wasm_runtime_instantiate_with_inheritance(
     WASMExecEnv *exec_env, uint32 stack_size, uint32 heap_size,
     WASMExecEnv *exec_env, uint32 stack_size, uint32 heap_size,
     uint32 max_memory_pages, char *error_buf, uint32 error_buf_size)
     uint32 max_memory_pages, char *error_buf, uint32 error_buf_size)
 {
 {
-    int32 spawned_import_count = wasm_runtime_get_import_count(module);
-    if (spawned_import_count < 0) {
+    int32 spawned_import_count_s = wasm_runtime_get_import_count(module);
+    if (spawned_import_count_s < 0) {
         return NULL;
         return NULL;
     }
     }
 
 
-    WASMExternInstance *spawned_imports = runtime_malloc(
-        sizeof(WASMExternInstance) * (uint64)spawned_import_count, NULL,
-        error_buf, error_buf_size);
-    if (spawned_imports == NULL) {
-        LOG_ERROR("Failed to allocate memory for imports");
-        return NULL;
-    }
-
-    int ret = wasm_runtime_inherit_imports(module, parent_inst, spawned_imports,
-                                           spawned_import_count);
-    if (ret != 0) {
-        LOG_ERROR("Failed to inherit imports");
-        wasm_runtime_free(spawned_imports);
-        return NULL;
+    uint32 spawned_import_count = (uint32)spawned_import_count_s;
+    WASMExternInstance *spawned_imports = NULL;
+    if (spawned_import_count > 0) {
+        spawned_imports = runtime_malloc(sizeof(WASMExternInstance)
+                                             * (uint64)spawned_import_count,
+                                         NULL, error_buf, error_buf_size);
+        if (spawned_imports == NULL) {
+            LOG_ERROR("Failed to allocate memory for imports");
+            return NULL;
+        }
+        int ret = wasm_runtime_inherit_imports(
+            module, parent_inst, spawned_imports, spawned_import_count);
+        if (ret != 0) {
+            LOG_ERROR("Failed to inherit imports");
+            wasm_runtime_free(spawned_imports);
+            return NULL;
+        }
     }
     }
 
 
     wasm_module_inst_t child_inst = wasm_runtime_instantiate_internal(
     wasm_module_inst_t child_inst = wasm_runtime_instantiate_internal(

+ 18 - 0
core/iwasm/common/wasm_shared_memory.c

@@ -110,6 +110,24 @@ shared_memory_dec_reference(WASMMemoryInstance *memory)
     return old - 1;
     return old - 1;
 }
 }
 
 
+uint16
+shared_memory_get_reference(WASMMemoryInstance *memory)
+{
+    bh_assert(shared_memory_is_shared(memory));
+
+#if BH_ATOMIC_16_IS_ATOMIC == 0
+    os_mutex_lock(&g_shared_memory_lock);
+#endif
+
+    uint16 old = BH_ATOMIC_16_FETCH_OR(memory->ref_count, 0);
+
+#if BH_ATOMIC_16_IS_ATOMIC == 0
+    os_mutex_unlock(&g_shared_memory_lock);
+#endif
+
+    return old;
+}
+
 static korp_mutex *
 static korp_mutex *
 shared_memory_get_lock_pointer(WASMMemoryInstance *memory)
 shared_memory_get_lock_pointer(WASMMemoryInstance *memory)
 {
 {

+ 3 - 0
core/iwasm/common/wasm_shared_memory.h

@@ -28,6 +28,9 @@ shared_memory_inc_reference(WASMMemoryInstance *memory);
 uint16
 uint16
 shared_memory_dec_reference(WASMMemoryInstance *memory);
 shared_memory_dec_reference(WASMMemoryInstance *memory);
 
 
+uint16
+shared_memory_get_reference(WASMMemoryInstance *memory);
+
 #define shared_memory_is_shared(memory) memory->is_shared_memory
 #define shared_memory_is_shared(memory) memory->is_shared_memory
 
 
 #define shared_memory_lock(memory)                                            \
 #define shared_memory_lock(memory)                                            \

+ 0 - 0
core/iwasm/common/wasm_table.c


+ 97 - 51
core/iwasm/compilation/aot.c

@@ -48,7 +48,7 @@ aot_create_import_memories(const WASMModule *module, uint32 import_memory_count)
 
 
     import_memories = wasm_runtime_malloc((uint32)size);
     import_memories = wasm_runtime_malloc((uint32)size);
     if (!import_memories) {
     if (!import_memories) {
-        aot_set_last_error("allocate memory failed.");
+        aot_set_last_error("allocate import memories failed.");
         return NULL;
         return NULL;
     }
     }
 
 
@@ -161,6 +161,89 @@ fail:
     return NULL;
     return NULL;
 }
 }
 
 
+static AOTImportTable *
+aot_create_import_tables(const WASMModule *module)
+{
+    uint64 size = sizeof(AOTImportTable) * (uint64)module->import_table_count;
+    if (size >= UINT32_MAX) {
+        aot_set_last_error("too big allocate size");
+        return NULL;
+    }
+
+    AOTImportTable *import_tables = wasm_runtime_malloc((uint32)size);
+    if (!import_tables) {
+        aot_set_last_error("allocate import tables failed.");
+        return NULL;
+    }
+
+    memset(import_tables, 0, (uint32)size);
+
+    for (uint32 i = 0; i < module->import_table_count; i++) {
+        AOTImportTable *table_aot = import_tables + i;
+        WASMImport *table_wasm = module->import_tables + i;
+
+        table_aot->module_name = table_wasm->u.table.module_name;
+        table_aot->table_name = table_wasm->u.table.field_name;
+        table_aot->table_type.elem_type =
+            table_wasm->u.table.table_type.elem_type;
+        table_aot->table_type.flags = table_wasm->u.table.table_type.flags;
+        table_aot->table_type.init_size =
+            table_wasm->u.table.table_type.init_size;
+        table_aot->table_type.max_size =
+            table_wasm->u.table.table_type.max_size;
+#if WASM_ENABLE_GC != 0
+        table_aot->table_type.elem_ref_type =
+            table_wasm->u.table.table_type.elem_ref_type;
+#endif
+        table_aot->table_type.possible_grow =
+            table_wasm->u.table.table_type.possible_grow;
+    }
+
+    return import_tables;
+}
+
+static AOTTable *
+aot_create_tables(const WASMModule *module)
+{
+    uint64 size = sizeof(AOTTable) * (uint64)module->table_count;
+    if (size >= UINT32_MAX) {
+        aot_set_last_error("too big allocate size");
+        return NULL;
+    }
+
+    AOTTable *tables = wasm_runtime_malloc((uint32)size);
+    if (!tables) {
+        aot_set_last_error("allocate tables failed.");
+        return NULL;
+    }
+
+    memset(tables, 0, (uint32)size);
+
+    for (uint32 i = 0; i < module->table_count; i++) {
+        AOTTable *table_aot = tables + i;
+        WASMTable *table_wasm = module->tables + i;
+
+        table_aot->table_type.elem_type = table_wasm->table_type.elem_type;
+        table_aot->table_type.flags = table_wasm->table_type.flags;
+        table_aot->table_type.init_size = table_wasm->table_type.init_size;
+        table_aot->table_type.max_size = table_wasm->table_type.max_size;
+        table_aot->table_type.possible_grow =
+            table_wasm->table_type.possible_grow;
+#if WASM_ENABLE_GC != 0
+        table_aot->table_type.elem_ref_type =
+            table_wasm->table_type.elem_ref_type;
+        /* Note: if the init_expr contains extra data for struct/array
+         * initialization information (init_expr.u.data), the pointer is
+         * copied.
+         * The pointers should still belong to wasm module, so DO NOT
+         * free the pointers copied to comp_data */
+        table_aot->init_expr = table_wasm->init_expr;
+#endif
+    }
+
+    return tables;
+}
+
 static void
 static void
 aot_destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
 aot_destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
 {
 {
@@ -568,9 +651,8 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
                      bool gc_enabled)
                      bool gc_enabled)
 {
 {
     AOTCompData *comp_data;
     AOTCompData *comp_data;
-    uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0, i, j;
+    uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0;
     uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0;
     uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0;
-    uint64 size;
     bool is_64bit_target = false;
     bool is_64bit_target = false;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
     bool is_target_x86 = false;
     bool is_target_x86 = false;
@@ -647,58 +729,22 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
                  aot_create_mem_init_data_list(module)))
                  aot_create_mem_init_data_list(module)))
         goto fail;
         goto fail;
 
 
-    /* Create tables */
-    comp_data->table_count = module->import_table_count + module->table_count;
+    /* Create import tables */
+    comp_data->import_table_count = module->import_table_count;
+    if (comp_data->import_table_count > 0) {
+        comp_data->import_tables = aot_create_import_tables(module);
+        if (!comp_data->import_tables) {
+            goto fail;
+        }
+    }
 
 
+    /* Create tables */
+    comp_data->table_count = module->table_count;
     if (comp_data->table_count > 0) {
     if (comp_data->table_count > 0) {
-        size = sizeof(AOTTable) * (uint64)comp_data->table_count;
-        if (size >= UINT32_MAX
-            || !(comp_data->tables = wasm_runtime_malloc((uint32)size))) {
-            aot_set_last_error("create memories array failed.\n");
+        comp_data->tables = aot_create_tables(module);
+        if (!comp_data->tables) {
             goto fail;
             goto fail;
         }
         }
-        memset(comp_data->tables, 0, size);
-        for (i = 0; i < comp_data->table_count; i++) {
-            if (i < module->import_table_count) {
-                comp_data->tables[i].table_type.elem_type =
-                    module->import_tables[i].u.table.table_type.elem_type;
-                comp_data->tables[i].table_type.flags =
-                    module->import_tables[i].u.table.table_type.flags;
-                comp_data->tables[i].table_type.init_size =
-                    module->import_tables[i].u.table.table_type.init_size;
-                comp_data->tables[i].table_type.max_size =
-                    module->import_tables[i].u.table.table_type.max_size;
-#if WASM_ENABLE_GC != 0
-                comp_data->tables[i].table_type.elem_ref_type =
-                    module->import_tables[i].u.table.table_type.elem_ref_type;
-#endif
-                comp_data->tables[i].table_type.possible_grow =
-                    module->import_tables[i].u.table.table_type.possible_grow;
-            }
-            else {
-                j = i - module->import_table_count;
-                comp_data->tables[i].table_type.elem_type =
-                    module->tables[j].table_type.elem_type;
-                comp_data->tables[i].table_type.flags =
-                    module->tables[j].table_type.flags;
-                comp_data->tables[i].table_type.init_size =
-                    module->tables[j].table_type.init_size;
-                comp_data->tables[i].table_type.max_size =
-                    module->tables[j].table_type.max_size;
-                comp_data->tables[i].table_type.possible_grow =
-                    module->tables[j].table_type.possible_grow;
-#if WASM_ENABLE_GC != 0
-                comp_data->tables[j].table_type.elem_ref_type =
-                    module->tables[j].table_type.elem_ref_type;
-                /* Note: if the init_expr contains extra data for struct/array
-                 * initialization information (init_expr.u.data), the pointer is
-                 * copied.
-                 * The pointers should still belong to wasm module, so DO NOT
-                 * free the pointers copied to comp_data */
-                comp_data->tables[j].init_expr = module->tables[j].init_expr;
-#endif
-            }
-        }
     }
     }
 
 
     /* Create table data segments */
     /* Create table data segments */

+ 7 - 17
core/iwasm/compilation/aot.h

@@ -334,29 +334,19 @@ aot_set_last_error_v(const char *format, ...);
 #endif
 #endif
 
 
 static inline uint32
 static inline uint32
-aot_get_imp_tbl_data_slots(const AOTImportTable *tbl, bool is_jit_mode)
+aot_get_tbl_data_slots(const AOTTableType *type, bool is_jit_mode)
 {
 {
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
     if (is_jit_mode)
     if (is_jit_mode)
-        return tbl->table_type.max_size;
+        return type->max_size;
 #else
 #else
     (void)is_jit_mode;
     (void)is_jit_mode;
 #endif
 #endif
-    return tbl->table_type.possible_grow ? tbl->table_type.max_size
-                                         : tbl->table_type.init_size;
-}
-
-static inline uint32
-aot_get_tbl_data_slots(const AOTTable *tbl, bool is_jit_mode)
-{
-#if WASM_ENABLE_MULTI_MODULE != 0
-    if (is_jit_mode)
-        return tbl->table_type.max_size;
-#else
-    (void)is_jit_mode;
-#endif
-    return tbl->table_type.possible_grow ? tbl->table_type.max_size
-                                         : tbl->table_type.init_size;
+    /*
+     * TODO: if it is a host created table or a to be exported table, might need
+     * to ignore possible_grow
+     */
+    return type->possible_grow ? type->max_size : type->init_size;
 }
 }
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 10 - 3
core/iwasm/compilation/aot_compiler.h

@@ -534,6 +534,13 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
          ? comp_ctx->comp_data->import_memories[0].mem_type \
          ? comp_ctx->comp_data->import_memories[0].mem_type \
          : comp_ctx->comp_data->memories[0])
          : comp_ctx->comp_data->memories[0])
 
 
+#define TABLE_TYPE(i)                                                \
+    (i < comp_ctx->comp_data->import_table_count                     \
+         ? comp_ctx->comp_data->import_tables[i].table_type          \
+         : comp_ctx->comp_data                                       \
+               ->tables[i - comp_ctx->comp_data->import_table_count] \
+               .table_type)
+
 #define DEFAULT_MEMORY_TYPE_FLAG (DEFAULT_MEMORY_TYPE.flags)
 #define DEFAULT_MEMORY_TYPE_FLAG (DEFAULT_MEMORY_TYPE.flags)
 
 
 #define DEFAULT_MEMORY_TYPE_NUM_BYTES_PER_PAGE \
 #define DEFAULT_MEMORY_TYPE_NUM_BYTES_PER_PAGE \
@@ -552,14 +559,14 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
 #define IS_MEMORY64 (DEFAULT_MEMORY_TYPE_FLAG & MEMORY64_FLAG)
 #define IS_MEMORY64 (DEFAULT_MEMORY_TYPE_FLAG & MEMORY64_FLAG)
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \
     (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
     (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
-#define IS_TABLE64(i) \
-    (comp_ctx->comp_data->tables[i].table_type.flags & TABLE64_FLAG)
+#define IS_TABLE64(i) (TABLE_TYPE(i).flags & TABLE64_FLAG)
 #define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) \
 #define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) \
     (IS_TABLE64(i) ? VAL_IF_ENABLED : VAL_IF_DISABLED)
     (IS_TABLE64(i) ? VAL_IF_ENABLED : VAL_IF_DISABLED)
 #else
 #else
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
 #define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
 #define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
-#endif
+#define IS_TABLE64(i) false
+#endif /* WASM_ENABLE_MEMORY64 != 0 */
 
 
 #define POP_I32(v) POP(v, VALUE_TYPE_I32)
 #define POP_I32(v) POP(v, VALUE_TYPE_I32)
 #define POP_I64(v) POP(v, VALUE_TYPE_I64)
 #define POP_I64(v) POP(v, VALUE_TYPE_I64)

+ 187 - 126
core/iwasm/compilation/aot_emit_aot_file.c

@@ -353,9 +353,7 @@ get_table_init_data_size(AOTCompContext *comp_ctx,
 }
 }
 
 
 static uint32
 static uint32
-get_table_init_data_list_size(AOTCompContext *comp_ctx,
-                              AOTTableInitData **table_init_data_list,
-                              uint32 table_init_data_count)
+get_table_init_data_list_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 {
 {
     /*
     /*
      * ------------------------------
      * ------------------------------
@@ -370,13 +368,13 @@ get_table_init_data_list_size(AOTCompContext *comp_ctx,
      * |                     | UINTPTR [func_index_count] / [elem_count]
      * |                     | UINTPTR [func_index_count] / [elem_count]
      * ------------------------------
      * ------------------------------
      */
      */
-    AOTTableInitData **table_init_data = table_init_data_list;
+    AOTTableInitData **table_init_data = comp_data->table_init_data_list;
     uint32 size = 0, i;
     uint32 size = 0, i;
 
 
     /* table_init_data_count(4 bytes) */
     /* table_init_data_count(4 bytes) */
     size = (uint32)sizeof(uint32);
     size = (uint32)sizeof(uint32);
 
 
-    for (i = 0; i < table_init_data_count; i++, table_init_data++) {
+    for (i = 0; i < comp_data->table_init_data_count; i++, table_init_data++) {
         size = align_uint(size, 4);
         size = align_uint(size, 4);
         size += get_table_init_data_size(comp_ctx, *table_init_data);
         size += get_table_init_data_size(comp_ctx, *table_init_data);
     }
     }
@@ -384,57 +382,44 @@ get_table_init_data_list_size(AOTCompContext *comp_ctx,
 }
 }
 
 
 static uint32
 static uint32
-get_import_table_size(const AOTCompContext *comp_ctx,
-                      const AOTCompData *comp_data)
+get_import_table_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 {
 {
-    /*
-     * ------------------------------
-     * | import_table_count
-     * ------------------------------
-     * |                   | U8 elem_type
-     * |                   | U8 flags
-     * |                   | U8 possible_grow
-     * | AOTImportTable[N] | U8 elem_ref_type.nullable (for GC only)
-     * |                   | U32 init_size
-     * |                   | U32 max_size
-     * |                   | U32 elem_ref_type.heap_type (for GC only)
-     * ------------------------------
-     */
-    uint32 size = 0, i;
+    /* import_table_count */
+    uint32 size = (uint32)sizeof(uint32);
 
 
-    size = (uint32)sizeof(uint32);
-    for (i = 0; i < comp_data->import_table_count; i++) {
+    for (uint32 i = 0; i < comp_data->import_table_count; i++) {
+        size = align_uint(size, 4);
+        /*
+         *   u8 elem_type + u8 flags
+         *   + u8 possible_grow + u8 elem_ref_type.nullable
+         * ------------------------------ =u32
+         *   + u32 init_size + u32 max_size
+         *   + u32 elem_ref_type.heap_type (Optional)
+         */
         size += sizeof(uint32) * 3;
         size += sizeof(uint32) * 3;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
         if (comp_ctx->enable_gc
         if (comp_ctx->enable_gc
             && comp_data->import_tables[i].table_type.elem_ref_type)
             && comp_data->import_tables[i].table_type.elem_ref_type)
             size += sizeof(uint32);
             size += sizeof(uint32);
 #endif
 #endif
+        /* module_name */
+        size +=
+            get_string_size(comp_ctx, comp_data->import_tables[i].module_name);
+        size = align_uint(size, 2);
+        /* field_name */
+        size +=
+            get_string_size(comp_ctx, comp_data->import_tables[i].table_name);
     }
     }
     return size;
     return size;
 }
 }
 
 
 static uint32
 static uint32
-get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data)
+get_table_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
 {
 {
-    /*
-     * ------------------------------
-     * | table_count
-     * ------------------------------
-     * |             | U8 elem_type
-     * |             | U8 flags
-     * |             | U8 possible_grow
-     * | AOTTable[N] | U8 elem_ref_type.nullable (for GC only)
-     * |             | U32 init_size
-     * |             | U32 max_size
-     * |             | U32 elem_ref_type.heap_type (for GC only)
-     * |             | N   init_expr (for GC only)
-     * ------------------------------
-     */
-    uint32 size = 0, i;
+    /* table_count */
+    uint32 size = (uint32)sizeof(uint32);
 
 
-    size = (uint32)sizeof(uint32);
-    for (i = 0; i < comp_data->table_count; i++) {
+    for (uint32 i = 0; i < comp_data->table_count; i++) {
         size += sizeof(uint32) * 3;
         size += sizeof(uint32) * 3;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
         if (comp_ctx->enable_gc) {
         if (comp_ctx->enable_gc) {
@@ -449,37 +434,6 @@ get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data)
     return size;
     return size;
 }
 }
 
 
-static uint32
-get_table_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
-{
-    /*
-     * ------------------------------
-     * | import_table_count
-     * ------------------------------
-     * |
-     * | AOTImportTable[import_table_count]
-     * |
-     * ------------------------------
-     * | table_count
-     * ------------------------------
-     * |
-     * | AOTTable[table_count]
-     * |
-     * ------------------------------
-     * | table_init_data_count
-     * ------------------------------
-     * |
-     * | AOTTableInitData*[table_init_data_count]
-     * |
-     * ------------------------------
-     */
-    return get_import_table_size(comp_ctx, comp_data)
-           + get_table_size(comp_ctx, comp_data)
-           + get_table_init_data_list_size(comp_ctx,
-                                           comp_data->table_init_data_list,
-                                           comp_data->table_init_data_count);
-}
-
 static uint32
 static uint32
 get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
 get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
 {
 {
@@ -780,32 +734,36 @@ get_init_data_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
      * -------------------------------------------------------
      * -------------------------------------------------------
      * | u32 import_memory_count
      * | u32 import_memory_count
      * -------------------------------------------------------
      * -------------------------------------------------------
-     * |                                      | u32 flags
-     * | AOTImportMemory[import_memory_count] | u32 num_bytes_per_page
-     * |                                      | u32 init_page_count
-     * |                                      | u32 max_page_count
-     * |                                      | str module_name
-     * |                                      | str field_name
+     * |                            | u32 flags
+     * | AOTImportMemory[N]         | u32 num_bytes_per_page
+     * |                            | u32 init_page_count
+     * |                            | u32 max_page_count
+     * |                            | str module_name
+     * |                            | str field_name
      * -------------------------------------------------------
      * -------------------------------------------------------
      * | padding
      * | padding
+     * | previous version doesn't have it by design.
+     * | But alignment will make it 0
      * -------------------------------------------------------
      * -------------------------------------------------------
      * | u32 memory_count
      * | u32 memory_count
      * -------------------------------------------------------
      * -------------------------------------------------------
-     * |                             | u32 flags
-     * | AOTMemoryType[memory_count] | u32 num_bytes_per_page
-     * |                             | u32 init_page_count
-     * |                             | u32 max_page_count
+     * |                            | u32 flags
+     * | AOTMemoryType[N]           | u32 num_bytes_per_page
+     * |                            | u32 init_page_count
+     * |                            | u32 max_page_count
      * -------------------------------------------------------
      * -------------------------------------------------------
-     * | padding (TBC: previous aot doesn't have this padding by design)
+     * | padding
+     * | previous version doesn't have it by design.
+     * | But alignment will make it 0
      * -------------------------------------------------------
      * -------------------------------------------------------
      * | u32 mem_init_data_count
      * | u32 mem_init_data_count
      * -------------------------------------------------------
      * -------------------------------------------------------
-     * |                                     | u32 is_passive/placeholder
-     * |                                     | u32 memory_index/placeholder
-     * |                                     | u32 init expr type
-     * | AOTMemInitData[mem_init_data_count] | u32 init expr value
-     * |                                     | u32 byte count
-     * |                                     | u8* bytes
+     * |                            | u32 is_passive/placeholder
+     * |                            | u32 memory_index/placeholder
+     * |                            | u32 init expr type
+     * | AOTMemInitData[N]          | u32 init expr value
+     * |                            | u32 byte count
+     * |                            | u8* bytes
      * -------------------------------------------------------
      * -------------------------------------------------------
      */
      */
     size += get_import_memory_size(comp_ctx, comp_data);
     size += get_import_memory_size(comp_ctx, comp_data);
@@ -816,8 +774,60 @@ get_init_data_section_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
     size = align_uint(size, 4);
     size = align_uint(size, 4);
     size += get_mem_init_data_list_size(comp_ctx, comp_data);
     size += get_mem_init_data_list_size(comp_ctx, comp_data);
 
 
+    /*
+     * -------------------------------------------------------
+     * | u32 import_table_count
+     * -------------------------------------------------------
+     * |                         |  u8 elem_type
+     * |                         |  u8 flags
+     * |                         |  u8 possible_grow
+     * |                         |  u8 elem_ref_type.nullable(GC)
+     * |  AOTImportTable[N]      | u32 init_size
+     * |                         | u32 max_size
+     * |                         | u32 elem_ref_type.heap_type(GC)
+     * |                         | str module_name
+     * |                         | str field_name
+     * -------------------------------------------------------
+     * | padding
+     * | previous version doesn't have it by design.
+     * | but import_table_count used to be 0
+     * -------------------------------------------------------
+     * | u32 table_count
+     * -------------------------------------------------------
+     * |                         |  u8 elem_type
+     * |                         |  u8 flags
+     * |                         |  u8 possible_grow
+     * |                         |  u8 elem_ref_type.nullable(GC)
+     * |  AOTTable[N]            | u32 init_size
+     * |                         | u32 max_size
+     * |                         | u32 elem_ref_type.heap_type(GC)
+     * |                         |   N init_expr(GC)
+     * -------------------------------------------------------
+     * | padding
+     * | previous version doesn't have it by design.
+     * | But alignment will make it 0
+     * | table_init_data_count
+     * -------------------------------------------------------
+     * | u32 table_init_data_count
+     * -------------------------------------------------------
+     * |                         | U32 mode
+     * | AOTTableInitData[N]     | U32 elem_type
+     * |                         | U32 table_index
+     * |                         | U32 offset.init_expr_type
+     * |                         | U64 offset.u.i64
+     * |                         | U32 func_index_count / elem_count
+     * |                         | UINTPTR [func_index_count] / [elem_count]
+     * -------------------------------------------------------
+     */
+
+    size = align_uint(size, 4);
+    size += get_import_table_size(comp_ctx, comp_data);
+
     size = align_uint(size, 4);
     size = align_uint(size, 4);
-    size += get_table_info_size(comp_ctx, comp_data);
+    size += get_table_size(comp_ctx, comp_data);
+
+    size = align_uint(size, 4);
+    size += get_table_init_data_list_size(comp_ctx, comp_data);
 
 
     size = align_uint(size, 4);
     size = align_uint(size, 4);
     size += get_type_info_size(comp_ctx, comp_data);
     size += get_type_info_size(comp_ctx, comp_data);
@@ -2040,31 +2050,27 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
 }
 }
 
 
 static bool
 static bool
-aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
-                    AOTCompContext *comp_ctx, AOTCompData *comp_data,
-                    AOTObjectData *obj_data)
+aot_emit_import_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                           AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                           AOTObjectData *obj_data)
 {
 {
-    uint32 offset = *p_offset, i, j;
-    AOTTableInitData **init_datas = comp_data->table_init_data_list;
+    uint32 offset = *p_offset;
 
 
     *p_offset = offset = align_uint(offset, 4);
     *p_offset = offset = align_uint(offset, 4);
 
 
-    /* Emit import table count */
     EMIT_U32(comp_data->import_table_count);
     EMIT_U32(comp_data->import_table_count);
-    /* Emit table items */
-    for (i = 0; i < comp_data->import_table_count; i++) {
-        /* TODO:
-         * EMIT_STR(comp_data->import_tables[i].module_name );
-         * EMIT_STR(comp_data->import_tables[i].table_name);
-         */
-        EMIT_U8(comp_data->import_tables[i].table_type.elem_type);
-        EMIT_U8(comp_data->import_tables[i].table_type.flags);
-        EMIT_U8(comp_data->import_tables[i].table_type.possible_grow);
+
+    AOTImportTable *import_table = comp_data->import_tables;
+    for (uint32 i = 0; i < comp_data->import_table_count; i++, import_table++) {
+        offset = align_uint(offset, 4);
+
+        EMIT_U8(import_table->table_type.elem_type);
+        EMIT_U8(import_table->table_type.flags);
+        EMIT_U8(import_table->table_type.possible_grow);
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
-        if (comp_ctx->enable_gc
-            && comp_data->import_tables[i].table_type.elem_ref_type) {
-            EMIT_U8(comp_data->import_tables[i]
-                        .table_type.elem_ref_type->ref_ht_common.nullable);
+        if (comp_ctx->enable_gc && import_table->table_type.elem_ref_type) {
+            EMIT_U8(
+                import_table->table_type.elem_ref_type->ref_ht_common.nullable);
         }
         }
         else
         else
 #endif
 #endif
@@ -2072,23 +2078,46 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
             /* emit one placeholder to keep the same size */
             /* emit one placeholder to keep the same size */
             EMIT_U8(0);
             EMIT_U8(0);
         }
         }
-        EMIT_U32(comp_data->import_tables[i].table_type.init_size);
-        EMIT_U32(comp_data->import_tables[i].table_type.max_size);
+
+        EMIT_U32(import_table->table_type.init_size);
+        EMIT_U32(import_table->table_type.max_size);
+
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
-        if (comp_ctx->enable_gc
-            && comp_data->import_tables[i].table_type.elem_ref_type) {
+        if (comp_ctx->enable_gc && import_table->table_type.elem_ref_type) {
             bh_assert(wasm_is_type_multi_byte_type(
             bh_assert(wasm_is_type_multi_byte_type(
-                comp_data->import_tables[i].table_type.elem_type));
-            EMIT_U32(comp_data->import_tables[i]
-                         .table_type.elem_ref_type->ref_ht_common.heap_type);
+                import_table->table_type.elem_type));
+            EMIT_U32(import_table->table_type.elem_ref_type->ref_ht_common
+                         .heap_type);
         }
         }
 #endif
 #endif
+
+        EMIT_STR(import_table->module_name);
+        offset = align_uint(offset, 2);
+
+        EMIT_STR(import_table->table_name);
+    }
+
+    if (offset - *p_offset != get_import_table_size(comp_ctx, comp_data)) {
+        aot_set_last_error("emit import table info failed.");
+        return false;
     }
     }
 
 
-    /* Emit table count */
+    *p_offset = offset;
+    return true;
+}
+
+static bool
+aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                    AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                    AOTObjectData *obj_data)
+{
+    uint32 offset = *p_offset;
+
+    *p_offset = offset = align_uint(offset, 4);
+
     EMIT_U32(comp_data->table_count);
     EMIT_U32(comp_data->table_count);
-    /* Emit table items */
-    for (i = 0; i < comp_data->table_count; i++) {
+
+    for (uint32 i = 0; i < comp_data->table_count; i++) {
         EMIT_U8(comp_data->tables[i].table_type.elem_type);
         EMIT_U8(comp_data->tables[i].table_type.elem_type);
         EMIT_U8(comp_data->tables[i].table_type.flags);
         EMIT_U8(comp_data->tables[i].table_type.flags);
         EMIT_U8(comp_data->tables[i].table_type.possible_grow);
         EMIT_U8(comp_data->tables[i].table_type.possible_grow);
@@ -2104,8 +2133,10 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
             /* emit one placeholder to keep the same size */
             /* emit one placeholder to keep the same size */
             EMIT_U8(0);
             EMIT_U8(0);
         }
         }
+
         EMIT_U32(comp_data->tables[i].table_type.init_size);
         EMIT_U32(comp_data->tables[i].table_type.init_size);
         EMIT_U32(comp_data->tables[i].table_type.max_size);
         EMIT_U32(comp_data->tables[i].table_type.max_size);
+
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
         if (comp_ctx->enable_gc) {
         if (comp_ctx->enable_gc) {
             if (comp_data->tables[i].table_type.elem_ref_type) {
             if (comp_data->tables[i].table_type.elem_ref_type) {
@@ -2123,16 +2154,37 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
 #endif
 #endif
     }
     }
 
 
-    /* Emit table init data count */
+    if (offset - *p_offset != get_table_size(comp_ctx, comp_data)) {
+        aot_set_last_error("emit table info failed.");
+        return false;
+    }
+
+    *p_offset = offset;
+
+    return true;
+}
+
+static bool
+aot_emit_table_init_data_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                              AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                              AOTObjectData *obj_data)
+{
+    uint32 offset = *p_offset;
+
+    *p_offset = offset = align_uint(offset, 4);
+
     EMIT_U32(comp_data->table_init_data_count);
     EMIT_U32(comp_data->table_init_data_count);
-    /* Emit table init data items */
-    for (i = 0; i < comp_data->table_init_data_count; i++) {
+
+    AOTTableInitData **init_datas = comp_data->table_init_data_list;
+    for (uint32 i = 0; i < comp_data->table_init_data_count; i++) {
         offset = align_uint(offset, 4);
         offset = align_uint(offset, 4);
+
         EMIT_U32(init_datas[i]->mode);
         EMIT_U32(init_datas[i]->mode);
         EMIT_U32(init_datas[i]->elem_type);
         EMIT_U32(init_datas[i]->elem_type);
         EMIT_U32(init_datas[i]->table_index);
         EMIT_U32(init_datas[i]->table_index);
         EMIT_U32(init_datas[i]->offset.init_expr_type);
         EMIT_U32(init_datas[i]->offset.init_expr_type);
         EMIT_U64(init_datas[i]->offset.u.i64);
         EMIT_U64(init_datas[i]->offset.u.i64);
+
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
         if (comp_ctx->enable_gc && init_datas[i]->elem_ref_type) {
         if (comp_ctx->enable_gc && init_datas[i]->elem_ref_type) {
             EMIT_U16(init_datas[i]->elem_ref_type->ref_ht_common.ref_type);
             EMIT_U16(init_datas[i]->elem_ref_type->ref_ht_common.ref_type);
@@ -2146,21 +2198,23 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
             EMIT_U16(0);
             EMIT_U16(0);
             EMIT_U32(0);
             EMIT_U32(0);
         }
         }
+
         EMIT_U32(init_datas[i]->value_count);
         EMIT_U32(init_datas[i]->value_count);
-        for (j = 0; j < init_datas[i]->value_count; j++) {
+
+        for (uint j = 0; j < init_datas[i]->value_count; j++) {
             if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
             if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
                                     &init_datas[i]->init_values[j]))
                                     &init_datas[i]->init_values[j]))
                 return false;
                 return false;
         }
         }
     }
     }
 
 
-    if (offset - *p_offset != get_table_info_size(comp_ctx, comp_data)) {
-        aot_set_last_error("emit table info failed.");
+    if (offset - *p_offset
+        != get_table_init_data_list_size(comp_ctx, comp_data)) {
+        aot_set_last_error("emit table init data info failed.");
         return false;
         return false;
     }
     }
 
 
     *p_offset = offset;
     *p_offset = offset;
-
     return true;
     return true;
 }
 }
 
 
@@ -2490,8 +2544,12 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                                  obj_data)
                                  obj_data)
         || !aot_emit_memory_init_data_list(buf, buf_end, &offset, comp_ctx,
         || !aot_emit_memory_init_data_list(buf, buf_end, &offset, comp_ctx,
                                            comp_data, obj_data)
                                            comp_data, obj_data)
+        || !aot_emit_import_table_info(buf, buf_end, &offset, comp_ctx,
+                                       comp_data, obj_data)
         || !aot_emit_table_info(buf, buf_end, &offset, comp_ctx, comp_data,
         || !aot_emit_table_info(buf, buf_end, &offset, comp_ctx, comp_data,
                                 obj_data)
                                 obj_data)
+        || !aot_emit_table_init_data_info(buf, buf_end, &offset, comp_ctx,
+                                          comp_data, obj_data)
         || !aot_emit_type_info(buf, buf_end, &offset, comp_ctx, comp_data,
         || !aot_emit_type_info(buf, buf_end, &offset, comp_ctx, comp_data,
                                obj_data)
                                obj_data)
         || !aot_emit_import_global_info(buf, buf_end, &offset, comp_ctx,
         || !aot_emit_import_global_info(buf, buf_end, &offset, comp_ctx,
@@ -4534,6 +4592,9 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
     if (!comp_ctx->call_stack_features.func_idx) {
     if (!comp_ctx->call_stack_features.func_idx) {
         obj_data->target_info.feature_flags |= WASM_FEATURE_FRAME_NO_FUNC_IDX;
         obj_data->target_info.feature_flags |= WASM_FEATURE_FRAME_NO_FUNC_IDX;
     }
     }
+    if (comp_ctx->enable_multi_module) {
+        obj_data->target_info.feature_flags |= WASM_FEATURE_MULTI_MODULE;
+    }
 
 
     bh_print_time("Begin to resolve object file info");
     bh_print_time("Begin to resolve object file info");
 
 

+ 2 - 11
core/iwasm/compilation/aot_emit_function.c

@@ -2239,17 +2239,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                              cmp_elem_idx, check_elem_idx_succ)))
                              cmp_elem_idx, check_elem_idx_succ)))
         goto fail;
         goto fail;
 
 
-    /* load data as i32* */
-    if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
-                             + offsetof(AOTTableInstance, elems)))) {
-        HANDLE_FAILURE("LLVMConstInt");
-        goto fail;
-    }
-
-    if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
-                                                  func_ctx->aot_inst, &offset,
-                                                  1, "table_elem_base_i8p"))) {
-        aot_set_last_error("llvm build add failed.");
+    if (!(table_elem_base =
+              aot_compile_get_table_elem_base(comp_ctx, func_ctx, tbl_idx))) {
         goto fail;
         goto fail;
     }
     }
 
 

+ 98 - 44
core/iwasm/compilation/aot_emit_table.c

@@ -86,25 +86,30 @@ uint64
 get_tbl_inst_offset(const AOTCompContext *comp_ctx,
 get_tbl_inst_offset(const AOTCompContext *comp_ctx,
                     const AOTFuncContext *func_ctx, uint32 tbl_idx)
                     const AOTFuncContext *func_ctx, uint32 tbl_idx)
 {
 {
-    uint64 offset = 0, i = 0;
-    AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
-    AOTTable *tbls = comp_ctx->comp_data->tables;
-
-    offset = offsetof(AOTModuleInstance, global_table_data.bytes)
-             + (uint64)(comp_ctx->comp_data->memory_count
-                        + comp_ctx->comp_data->import_memory_count)
-                   * sizeof(AOTMemoryInstance)
-             /* Get global data size according to target info */
-             + (comp_ctx->pointer_size == sizeof(uint64)
-                    ? comp_ctx->comp_data->global_data_size_64bit
-                    : comp_ctx->comp_data->global_data_size_32bit);
-
+    uint64 offset = offsetof(AOTModuleInstance, global_table_data.bytes)
+                    + (uint64)(comp_ctx->comp_data->memory_count
+                               + comp_ctx->comp_data->import_memory_count)
+                          * sizeof(AOTMemoryInstance)
+                    /* Get global data size according to target info */
+                    + (comp_ctx->pointer_size == sizeof(uint64)
+                           ? comp_ctx->comp_data->global_data_size_64bit
+                           : comp_ctx->comp_data->global_data_size_32bit);
+
+    uint64 i = 0;
     while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
     while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
         offset += offsetof(AOTTableInstance, elems);
         offset += offsetof(AOTTableInstance, elems);
-        /* avoid loading from current AOTTableInstance */
-        offset +=
-            (uint64)comp_ctx->pointer_size
-            * aot_get_imp_tbl_data_slots(imp_tbls + i, comp_ctx->is_jit_mode);
+        if (comp_ctx->enable_multi_module) {
+            AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
+            /* avoid loading from current AOTTableInstance */
+            offset += (uint64)comp_ctx->pointer_size
+                      * aot_get_tbl_data_slots(&(imp_tbls + i)->table_type,
+                                               comp_ctx->is_jit_mode);
+        }
+        else {
+            /* there is only one pointer for imported elem */
+            offset += (uint64)comp_ctx->pointer_size;
+        }
+
         ++i;
         ++i;
     }
     }
 
 
@@ -112,13 +117,15 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx,
         return offset;
         return offset;
     }
     }
 
 
+    AOTTable *tbls = comp_ctx->comp_data->tables;
     tbl_idx -= comp_ctx->comp_data->import_table_count;
     tbl_idx -= comp_ctx->comp_data->import_table_count;
     i -= comp_ctx->comp_data->import_table_count;
     i -= comp_ctx->comp_data->import_table_count;
     while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
     while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
         offset += offsetof(AOTTableInstance, elems);
         offset += offsetof(AOTTableInstance, elems);
         /* avoid loading from current AOTTableInstance */
         /* avoid loading from current AOTTableInstance */
         offset += (uint64)comp_ctx->pointer_size
         offset += (uint64)comp_ctx->pointer_size
-                  * aot_get_tbl_data_slots(tbls + i, comp_ctx->is_jit_mode);
+                  * aot_get_tbl_data_slots(&(tbls + i)->table_type,
+                                           comp_ctx->is_jit_mode);
         ++i;
         ++i;
     }
     }
 
 
@@ -137,6 +144,70 @@ get_module_inst_extra_offset(AOTCompContext *comp_ctx)
     return offset_32;
     return offset_32;
 }
 }
 
 
+LLVMValueRef
+aot_compile_get_table_elem_base(AOTCompContext *comp_ctx,
+                                AOTFuncContext *func_ctx, uint32 table_index)
+{
+    /* locate elems of a AOTTableInstance in a AOTModuleInstance */
+    LLVMValueRef offset =
+        I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, table_index)
+                  + offsetof(AOTTableInstance, elems));
+    if (!offset) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    /*
+     * for local table,
+     *   table_elem_base = (*(uint8*)WASMModuleInstance) + offset
+     *
+     * if for import table, if enable_multi_module == true
+     *   table_elem_base = (*(uint8*)WASMModuleInstance) + offset
+     *   table_elem_base = *(uintptr_t*)(table_elem_base)
+     */
+    LLVMValueRef table_elem_base =
+        LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
+                              &offset, 1, "table_elem_base_i8p");
+    if (!table_elem_base) {
+        HANDLE_FAILURE("LLVMBuildInBoundsGEP");
+        goto fail;
+    }
+
+    if (comp_ctx->enable_multi_module) {
+        return table_elem_base;
+    }
+
+    if (table_index < comp_ctx->comp_data->import_table_count) {
+        table_elem_base =
+            LLVMBuildIntToPtr(comp_ctx->builder, table_elem_base,
+                              INTPTR_T_PTR_TYPE, "import_table_elem_base_pp");
+        if (!table_elem_base) {
+            HANDLE_FAILURE("LLVMBuildBitCast");
+            goto fail;
+        }
+
+        table_elem_base =
+            LLVMBuildLoad2(comp_ctx->builder, INTPTR_T_TYPE, table_elem_base,
+                           "import_table_elem_base_p_addr");
+        if (!table_elem_base) {
+            HANDLE_FAILURE("LLVMBuildLoad");
+            goto fail;
+        }
+
+        table_elem_base =
+            LLVMBuildIntToPtr(comp_ctx->builder, table_elem_base,
+                              INTPTR_T_PTR_TYPE, "import_table_elem_base_p");
+        if (!table_elem_base) {
+            HANDLE_FAILURE("LLVMBuildBitCast");
+            goto fail;
+        }
+    }
+
+    return table_elem_base;
+fail:
+    return NULL;
+}
+
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
 
 
 LLVMValueRef
 LLVMValueRef
@@ -266,7 +337,7 @@ bool
 aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 tbl_idx)
                          uint32 tbl_idx)
 {
 {
-    LLVMValueRef elem_idx, offset, func_idx;
+    LLVMValueRef elem_idx, func_idx;
     LLVMValueRef table_elem_base, table_elem_addr, table_elem;
     LLVMValueRef table_elem_base, table_elem_addr, table_elem;
 
 
     POP_TBL_ELEM_IDX(elem_idx);
     POP_TBL_ELEM_IDX(elem_idx);
@@ -275,17 +346,9 @@ aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
         goto fail;
     }
     }
 
 
-    /* load data as i32* */
-    if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
-                             + offsetof(AOTTableInstance, elems)))) {
-        HANDLE_FAILURE("LLVMConstInt");
-        goto fail;
-    }
-
-    if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
-                                                  func_ctx->aot_inst, &offset,
-                                                  1, "table_elem_base_i8p"))) {
-        aot_set_last_error("llvm build add failed.");
+    if (!(table_elem_base =
+              aot_compile_get_table_elem_base(comp_ctx, func_ctx, tbl_idx))) {
+        aot_set_last_error("llvm build table_elem_base failed.");
         goto fail;
         goto fail;
     }
     }
 
 
@@ -352,7 +415,7 @@ bool
 aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 tbl_idx)
                          uint32 tbl_idx)
 {
 {
-    LLVMValueRef val = NULL, elem_idx, offset, table_elem_base, table_elem_addr;
+    LLVMValueRef val = NULL, elem_idx, table_elem_base, table_elem_addr;
 
 
     if (comp_ctx->enable_gc)
     if (comp_ctx->enable_gc)
         POP_GC_REF(val);
         POP_GC_REF(val);
@@ -372,17 +435,9 @@ aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
         goto fail;
     }
     }
 
 
-    /* load data as gc_obj_ref* or i32* */
-    if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
-                             + offsetof(AOTTableInstance, elems)))) {
-        HANDLE_FAILURE("LLVMConstInt");
-        goto fail;
-    }
-
-    if (!(table_elem_base = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
-                                                  func_ctx->aot_inst, &offset,
-                                                  1, "table_elem_base_i8p"))) {
-        HANDLE_FAILURE("LLVMBuildInBoundsGEP");
+    if (!(table_elem_base =
+              aot_compile_get_table_elem_base(comp_ctx, func_ctx, tbl_idx))) {
+        aot_set_last_error("llvm build table_elem_base failed.");
         goto fail;
         goto fail;
     }
     }
 
 
@@ -519,8 +574,7 @@ aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* In table64, the length should be i32 type if any one of src/dst table
     /* In table64, the length should be i32 type if any one of src/dst table
      * is i32 type, set the table index to the lesser-or-equal table when
      * is i32 type, set the table index to the lesser-or-equal table when
      * popping length n */
      * popping length n */
-    if (!(comp_ctx->comp_data->tables[src_tbl_idx].table_type.flags
-          & TABLE64_FLAG))
+    if (!IS_TABLE64(src_tbl_idx))
         tbl_idx = src_tbl_idx;
         tbl_idx = src_tbl_idx;
     else
     else
         tbl_idx = dst_tbl_idx;
         tbl_idx = dst_tbl_idx;

+ 4 - 0
core/iwasm/compilation/aot_emit_table.h

@@ -56,6 +56,10 @@ LLVMValueRef
 aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 tbl_idx);
                          uint32 tbl_idx);
 
 
+LLVMValueRef
+aot_compile_get_table_elem_base(AOTCompContext *comp_ctx,
+                                AOTFuncContext *func_ctx, uint32 table_index);
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 } /* end of extern "C" */
 } /* end of extern "C" */
 #endif
 #endif

+ 3 - 0
core/iwasm/compilation/aot_llvm.c

@@ -2695,6 +2695,9 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
     if (option->enable_shared_heap)
     if (option->enable_shared_heap)
         comp_ctx->enable_shared_heap = true;
         comp_ctx->enable_shared_heap = true;
 
 
+    if (option->enable_multi_module)
+        comp_ctx->enable_multi_module = true;
+
     comp_ctx->opt_level = option->opt_level;
     comp_ctx->opt_level = option->opt_level;
     comp_ctx->size_level = option->size_level;
     comp_ctx->size_level = option->size_level;
 
 

+ 2 - 0
core/iwasm/compilation/aot_llvm.h

@@ -484,6 +484,8 @@ typedef struct AOTCompContext {
 
 
     bool enable_shared_heap;
     bool enable_shared_heap;
 
 
+    bool enable_multi_module;
+
     uint32 opt_level;
     uint32 opt_level;
     uint32 size_level;
     uint32 size_level;
 
 

+ 3 - 1
core/iwasm/fast-jit/fe/jit_emit_table.c

@@ -290,8 +290,10 @@ wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst_offset,
     if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
     if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
         goto out_of_bounds;
         goto out_of_bounds;
 
 
+    table_elem_type_t *table_elems =
+        wasm_locate_table_elems(inst->module, tbl, tbl_idx);
     for (; len != 0; dst_offset++, len--) {
     for (; len != 0; dst_offset++, len--) {
-        tbl->elems[dst_offset] = val;
+        table_elems[dst_offset] = val;
     }
     }
 
 
     return 0;
     return 0;

+ 13 - 0
core/iwasm/fast-jit/jit_frontend.c

@@ -706,6 +706,19 @@ get_table_elems_reg(JitFrame *frame, uint32 tbl_idx)
         GEN_INSN(ADD, frame->table_regs[tbl_idx].table_elems, module_inst,
         GEN_INSN(ADD, frame->table_regs[tbl_idx].table_elems, module_inst,
                  NEW_CONST(PTR, offset));
                  NEW_CONST(PTR, offset));
     }
     }
+
+    if (tbl_idx < cc->cur_wasm_module->import_table_count) {
+        /*
+         * If the table is imported, table_elems is a pointer to the
+         * imported table's elements. We need to load the actual elements.
+         */
+        /* table_elems = *(void**)table_elems */
+        JitReg tmp = jit_cc_new_reg_ptr(cc);
+        GEN_INSN(LDPTR, tmp, frame->table_regs[tbl_idx].table_elems,
+                 NEW_CONST(I32, 0));
+        GEN_INSN(MOV, frame->table_regs[tbl_idx].table_elems, tmp);
+    }
+
     return frame->table_regs[tbl_idx].table_elems;
     return frame->table_regs[tbl_idx].table_elems;
 }
 }
 
 

+ 1 - 0
core/iwasm/include/aot_comp_option.h

@@ -74,6 +74,7 @@ typedef struct AOTCompOption {
     bool enable_stack_estimation;
     bool enable_stack_estimation;
     bool quick_invoke_c_api_import;
     bool quick_invoke_c_api_import;
     bool enable_shared_heap;
     bool enable_shared_heap;
+    bool enable_multi_module;
     char *use_prof_file;
     char *use_prof_file;
     uint32_t opt_level;
     uint32_t opt_level;
     uint32_t size_level;
     uint32_t size_level;

+ 45 - 27
core/iwasm/include/wasm_export.h

@@ -112,6 +112,20 @@ typedef struct wasm_export_t {
     } u;
     } u;
 } wasm_export_t;
 } wasm_export_t;
 
 
+#ifndef WASM_VALKIND_T_DEFINED
+#define WASM_VALKIND_T_DEFINED
+typedef uint8_t wasm_valkind_t;
+enum wasm_valkind_enum {
+    WASM_I32,
+    WASM_I64,
+    WASM_F32,
+    WASM_F64,
+    WASM_V128,
+    WASM_EXTERNREF = 128,
+    WASM_FUNCREF,
+};
+#endif
+
 /* Instantiated WASM module */
 /* Instantiated WASM module */
 struct WASMModuleInstanceCommon;
 struct WASMModuleInstanceCommon;
 typedef struct WASMModuleInstanceCommon *wasm_module_inst_t;
 typedef struct WASMModuleInstanceCommon *wasm_module_inst_t;
@@ -124,6 +138,17 @@ typedef WASMFunctionInstanceCommon *wasm_function_inst_t;
 struct WASMMemoryInstance;
 struct WASMMemoryInstance;
 typedef struct WASMMemoryInstance *wasm_memory_inst_t;
 typedef struct WASMMemoryInstance *wasm_memory_inst_t;
 
 
+/* Table instance*/
+/*TODO: better to use WASMTableInstance and AOTTableInstance directly */
+typedef struct wasm_table_inst_t {
+    wasm_valkind_t elem_kind;
+    uint32_t cur_size;
+    uint32_t max_size;
+    /* represents the elements of the table, for internal use only */
+    /* always a table_elem_type_t elems[] */
+    void *elems;
+} wasm_table_inst_t;
+
 /* WASM section */
 /* WASM section */
 typedef struct wasm_section_t {
 typedef struct wasm_section_t {
     struct wasm_section_t *next;
     struct wasm_section_t *next;
@@ -270,6 +295,7 @@ typedef struct WASMExternInstance {
     wasm_import_export_kind_t kind;
     wasm_import_export_kind_t kind;
     union {
     union {
         wasm_memory_inst_t memory;
         wasm_memory_inst_t memory;
+        wasm_table_inst_t *table;
     } u;
     } u;
 } WASMExternInstance, *wasm_extern_inst_t;
 } WASMExternInstance, *wasm_extern_inst_t;
 
 
@@ -296,20 +322,6 @@ typedef struct InstantiationArgs {
 } InstantiationArgs;
 } InstantiationArgs;
 #endif /* INSTANTIATION_ARGS_OPTION_DEFINED */
 #endif /* INSTANTIATION_ARGS_OPTION_DEFINED */
 
 
-#ifndef WASM_VALKIND_T_DEFINED
-#define WASM_VALKIND_T_DEFINED
-typedef uint8_t wasm_valkind_t;
-enum wasm_valkind_enum {
-    WASM_I32,
-    WASM_I64,
-    WASM_F32,
-    WASM_F64,
-    WASM_V128,
-    WASM_EXTERNREF = 128,
-    WASM_FUNCREF,
-};
-#endif
-
 #ifndef WASM_VAL_T_DEFINED
 #ifndef WASM_VAL_T_DEFINED
 #define WASM_VAL_T_DEFINED
 #define WASM_VAL_T_DEFINED
 struct wasm_ref_t;
 struct wasm_ref_t;
@@ -337,15 +349,6 @@ typedef struct wasm_global_inst_t {
     void *global_data;
     void *global_data;
 } wasm_global_inst_t;
 } wasm_global_inst_t;
 
 
-/* Table instance*/
-typedef struct wasm_table_inst_t {
-    wasm_valkind_t elem_kind;
-    uint32_t cur_size;
-    uint32_t max_size;
-    /* represents the elements of the table, for internal use only */
-    void *elems;
-} wasm_table_inst_t;
-
 typedef enum {
 typedef enum {
     WASM_LOG_LEVEL_FATAL = 0,
     WASM_LOG_LEVEL_FATAL = 0,
     WASM_LOG_LEVEL_ERROR = 1,
     WASM_LOG_LEVEL_ERROR = 1,
@@ -733,6 +736,13 @@ wasm_runtime_instantiate(const wasm_module_t module,
  *
  *
  * Same as wasm_runtime_instantiate, but it also allows overwriting maximum
  * Same as wasm_runtime_instantiate, but it also allows overwriting maximum
  * memory
  * memory
+ *
+ * The ownership of `imports.u`, globals and tables and memories, from `args`
+ * will be transferred to the runtime. You only need to worry about
+ * releasing them if the instantiate() fails.
+ *
+ * TODO: for now, wasm_table_inst still needs to be managed by the caller.
+ * but only the shell
  */
  */
 WASM_RUNTIME_API_EXTERN wasm_module_inst_t
 WASM_RUNTIME_API_EXTERN wasm_module_inst_t
 wasm_runtime_instantiate_ex(const wasm_module_t module,
 wasm_runtime_instantiate_ex(const wasm_module_t module,
@@ -1000,7 +1010,7 @@ wasm_runtime_create_memory(const wasm_module_t module,
  */
  */
 WASM_RUNTIME_API_EXTERN void
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_destroy_memory(const wasm_module_t module,
 wasm_runtime_destroy_memory(const wasm_module_t module,
-                            wasm_memory_inst_t memory_inst);
+                            wasm_memory_inst_t memory);
 
 
 /**
 /**
  * @brief Lookup a memory instance by name
  * @brief Lookup a memory instance by name
@@ -1495,7 +1505,7 @@ wasm_runtime_get_import_count(const wasm_module_t module);
  * @param import_type the location to store information about the import
  * @param import_type the location to store information about the import
  */
  */
 WASM_RUNTIME_API_EXTERN void
 WASM_RUNTIME_API_EXTERN void
-wasm_runtime_get_import_type(const wasm_module_t module, int32_t import_index,
+wasm_runtime_get_import_type(const wasm_module_t module, uint32_t import_index,
                              wasm_import_t *import_type);
                              wasm_import_t *import_type);
 
 
 /**
 /**
@@ -2341,6 +2351,14 @@ wasm_runtime_shared_heap_malloc(wasm_module_inst_t module_inst, uint64_t size,
 WASM_RUNTIME_API_EXTERN void
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_shared_heap_free(wasm_module_inst_t module_inst, uint64_t ptr);
 wasm_runtime_shared_heap_free(wasm_module_inst_t module_inst, uint64_t ptr);
 
 
+WASM_RUNTIME_API_EXTERN wasm_table_inst_t *
+wasm_runtime_create_table(const wasm_module_t module,
+                          const wasm_table_type_t type);
+
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy_table(const wasm_module_t module,
+                           wasm_table_inst_t *table);
+
 /*TODO: take me out when have a linker */
 /*TODO: take me out when have a linker */
 WASM_RUNTIME_API_EXTERN wasm_module_inst_t
 WASM_RUNTIME_API_EXTERN wasm_module_inst_t
 wasm_runtime_instantiate_with_builtin_linker(wasm_module_t module,
 wasm_runtime_instantiate_with_builtin_linker(wasm_module_t module,
@@ -2355,7 +2373,7 @@ wasm_runtime_instantiate_with_builtin_linker(wasm_module_t module,
 WASM_RUNTIME_API_EXTERN bool
 WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_create_imports_with_builtin(wasm_module_t module,
 wasm_runtime_create_imports_with_builtin(wasm_module_t module,
                                          wasm_extern_inst_t out,
                                          wasm_extern_inst_t out,
-                                         int32_t out_len);
+                                         uint32_t out_len);
 
 
 WASM_RUNTIME_API_EXTERN void
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_destroy_imports(wasm_module_t module, wasm_extern_inst_t imports);
 wasm_runtime_destroy_imports(wasm_module_t module, wasm_extern_inst_t imports);
@@ -2363,7 +2381,7 @@ wasm_runtime_destroy_imports(wasm_module_t module, wasm_extern_inst_t imports);
 WASM_RUNTIME_API_EXTERN bool
 WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_create_imports(wasm_module_t module,
 wasm_runtime_create_imports(wasm_module_t module,
                             bool (*module_name_filter)(const char *),
                             bool (*module_name_filter)(const char *),
-                            wasm_extern_inst_t out, int32_t out_len);
+                            wasm_extern_inst_t out, uint32_t out_len);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 3 - 2
core/iwasm/interpreter/wasm.h

@@ -1260,7 +1260,8 @@ wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size)
 inline static uint16
 inline static uint16
 wasm_value_type_cell_num_internal(uint8 value_type, uint8 pointer_size)
 wasm_value_type_cell_num_internal(uint8 value_type, uint8 pointer_size)
 {
 {
-    return wasm_value_type_size_internal(value_type, pointer_size) / 4;
+    return (uint16)(wasm_value_type_size_internal(value_type, pointer_size)
+                    / 4);
 }
 }
 
 
 /**
 /**
@@ -1275,7 +1276,7 @@ wasm_value_type_size(uint8 value_type)
 inline static uint16
 inline static uint16
 wasm_value_type_cell_num(uint8 value_type)
 wasm_value_type_cell_num(uint8 value_type)
 {
 {
-    return wasm_value_type_size(value_type) / 4;
+    return (uint16)(wasm_value_type_size(value_type) / 4);
 }
 }
 
 
 inline static uint32
 inline static uint32

+ 19 - 8
core/iwasm/interpreter/wasm_interp_classic.c

@@ -2399,15 +2399,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     goto got_exception;
                     goto got_exception;
                 }
                 }
 
 
+                table_elem_type_t *table_elems =
+                    wasm_locate_table_elems(module->module, tbl_inst, tbl_idx);
                 /* clang-format off */
                 /* clang-format off */
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
-                fidx = tbl_inst->elems[val];
+                fidx = table_elems[val];
                 if (fidx == (uint32)-1) {
                 if (fidx == (uint32)-1) {
                     wasm_set_exception(module, "uninitialized element");
                     wasm_set_exception(module, "uninitialized element");
                     goto got_exception;
                     goto got_exception;
                 }
                 }
 #else
 #else
-                func_obj = (WASMFuncObjectRef)tbl_inst->elems[val];
+                func_obj = (WASMFuncObjectRef)table_elems[val];
                 if (!func_obj) {
                 if (!func_obj) {
                     wasm_set_exception(module, "uninitialized element");
                     wasm_set_exception(module, "uninitialized element");
                     goto got_exception;
                     goto got_exception;
@@ -2558,10 +2560,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     goto got_exception;
                     goto got_exception;
                 }
                 }
 
 
+                table_elem_type_t *table_elems =
+                    wasm_locate_table_elems(module->module, tbl_inst, tbl_idx);
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
-                PUSH_I32(tbl_inst->elems[elem_idx]);
+                PUSH_I32(table_elems[elem_idx]);
 #else
 #else
-                PUSH_REF(tbl_inst->elems[elem_idx]);
+                PUSH_REF(table_elems[elem_idx]);
 #endif
 #endif
                 HANDLE_OP_END();
                 HANDLE_OP_END();
             }
             }
@@ -2592,7 +2596,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     goto got_exception;
                     goto got_exception;
                 }
                 }
 
 
-                tbl_inst->elems[elem_idx] = elem_val;
+                table_elem_type_t *table_elems =
+                    wasm_locate_table_elems(module->module, tbl_inst, tbl_idx);
+                table_elems[elem_idx] = elem_val;
                 HANDLE_OP_END();
                 HANDLE_OP_END();
             }
             }
 
 
@@ -5907,7 +5913,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         tbl_elem_idx_t elem_idx, d;
                         tbl_elem_idx_t elem_idx, d;
                         uint32 n, s;
                         uint32 n, s;
                         WASMTableInstance *tbl_inst;
                         WASMTableInstance *tbl_inst;
-                        table_elem_type_t *table_elems;
                         InitializerExpression *tbl_seg_init_values = NULL,
                         InitializerExpression *tbl_seg_init_values = NULL,
                                               *init_values;
                                               *init_values;
                         uint32 tbl_seg_len = 0;
                         uint32 tbl_seg_len = 0;
@@ -5957,7 +5962,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             break;
                             break;
                         }
                         }
 
 
-                        table_elems = tbl_inst->elems + d;
+                        table_elem_type_t *table_elems =
+                            wasm_locate_table_elems(module->module, tbl_inst,
+                                                    tbl_idx);
+                        table_elems = table_elems + d;
                         init_values = tbl_seg_init_values + s;
                         init_values = tbl_seg_init_values + s;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
                         SYNC_ALL_TO_FRAME();
                         SYNC_ALL_TO_FRAME();
@@ -6143,8 +6151,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                             goto got_exception;
                         }
                         }
 
 
+                        table_elem_type_t *table_elems =
+                            wasm_locate_table_elems(module->module, tbl_inst,
+                                                    tbl_idx);
                         for (; n != 0; elem_idx++, n--) {
                         for (; n != 0; elem_idx++, n--) {
-                            tbl_inst->elems[elem_idx] = fill_val;
+                            table_elems[elem_idx] = fill_val;
                         }
                         }
                         break;
                         break;
                     }
                     }

+ 19 - 8
core/iwasm/interpreter/wasm_interp_fast.c

@@ -1745,15 +1745,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     goto got_exception;
                     goto got_exception;
                 }
                 }
 
 
+                table_elem_type_t *table_elems =
+                    wasm_locate_table_elems(module->module, tbl_inst, tbl_idx);
                 /* clang-format off */
                 /* clang-format off */
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
-                fidx = (uint32)tbl_inst->elems[val];
+                fidx = (uint32)table_elems[val];
                 if (fidx == (uint32)-1) {
                 if (fidx == (uint32)-1) {
                     wasm_set_exception(module, "uninitialized element");
                     wasm_set_exception(module, "uninitialized element");
                     goto got_exception;
                     goto got_exception;
                 }
                 }
 #else
 #else
-                func_obj = (WASMFuncObjectRef)tbl_inst->elems[val];
+                func_obj = (WASMFuncObjectRef)table_elems[val];
                 if (!func_obj) {
                 if (!func_obj) {
                     wasm_set_exception(module, "uninitialized element");
                     wasm_set_exception(module, "uninitialized element");
                     goto got_exception;
                     goto got_exception;
@@ -1908,10 +1910,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     goto got_exception;
                     goto got_exception;
                 }
                 }
 
 
+                table_elem_type_t *table_elems =
+                    wasm_locate_table_elems(module->module, tbl_inst, tbl_idx);
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
-                PUSH_I32(tbl_inst->elems[elem_idx]);
+                PUSH_I32(table_elems[elem_idx]);
 #else
 #else
-                PUSH_REF(tbl_inst->elems[elem_idx]);
+                PUSH_REF(table_elems[elem_idx]);
 #endif
 #endif
                 HANDLE_OP_END();
                 HANDLE_OP_END();
             }
             }
@@ -1938,7 +1942,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     goto got_exception;
                     goto got_exception;
                 }
                 }
 
 
-                tbl_inst->elems[elem_idx] = elem_val;
+                table_elem_type_t *table_elems =
+                    wasm_locate_table_elems(module->module, tbl_inst, tbl_idx);
+                table_elems[elem_idx] = elem_val;
                 HANDLE_OP_END();
                 HANDLE_OP_END();
             }
             }
 
 
@@ -5170,7 +5176,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         uint32 tbl_idx, elem_idx;
                         uint32 tbl_idx, elem_idx;
                         uint32 n, s, d;
                         uint32 n, s, d;
                         WASMTableInstance *tbl_inst;
                         WASMTableInstance *tbl_inst;
-                        table_elem_type_t *table_elems;
                         InitializerExpression *tbl_seg_init_values = NULL,
                         InitializerExpression *tbl_seg_init_values = NULL,
                                               *init_values;
                                               *init_values;
                         uint64 i;
                         uint64 i;
@@ -5211,7 +5216,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             break;
                             break;
                         }
                         }
 
 
-                        table_elems = tbl_inst->elems + d;
+                        table_elem_type_t *table_elems =
+                            wasm_locate_table_elems(module->module, tbl_inst,
+                                                    tbl_idx);
+                        table_elems = table_elems + d;
                         init_values = tbl_seg_init_values + s;
                         init_values = tbl_seg_init_values + s;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
                         SYNC_ALL_TO_FRAME();
                         SYNC_ALL_TO_FRAME();
@@ -5361,8 +5369,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             goto got_exception;
                             goto got_exception;
                         }
                         }
 
 
+                        table_elem_type_t *table_elems =
+                            wasm_locate_table_elems(module->module, tbl_inst,
+                                                    tbl_idx);
                         for (; n != 0; i++, n--) {
                         for (; n != 0; i++, n--) {
-                            tbl_inst->elems[i] = fill_val;
+                            table_elems[i] = fill_val;
                         }
                         }
 
 
                         break;
                         break;

+ 226 - 102
core/iwasm/interpreter/wasm_runtime.c

@@ -263,24 +263,39 @@ memory_deinstantiate(WASMMemoryInstance *memory)
 }
 }
 
 
 static void
 static void
-memories_deinstantiate(WASMModuleInstance *module_inst,
-                       WASMMemoryInstance **memories, uint32 count)
+memories_deinstantiate(WASMModuleInstance *module_inst)
 {
 {
-
-    if (!memories)
+    if (!module_inst->memories) {
         return;
         return;
+    }
 
 
-    for (uint32 i = 0; i < count; i++) {
+    uint32 mem_index = 0;
+    WASMModule *module = module_inst->module;
+    WASMMemoryInstance **memories = module_inst->memories;
+    for (; mem_index < module->import_memory_count; mem_index++) {
+        WASMMemoryInstance *memory = memories[mem_index];
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
-        WASMModule *module = module_inst->module;
+        if (module->import_memories[mem_index].u.memory.import_module) {
+            continue;
+        }
+
+        memory_deinstantiate(memory);
+#endif
 
 
-        if (i < module->import_memory_count
-            && module->import_memories[i].u.memory.import_module) {
+#if WASM_ENABLE_MULTI_MODULE == 0 && WASM_ENABLE_SHARED_MEMORY != 0
+        /* for spawned only */
+        if (!shared_memory_is_shared(memory)) {
             continue;
             continue;
         }
         }
+
+        if (shared_memory_get_reference(memory) == 0) {
+            wasm_runtime_free(memory);
+        }
 #endif
 #endif
+    }
 
 
-        memory_deinstantiate(memories[i]);
+    for (; mem_index < module->memory_count; mem_index++) {
+        memory_deinstantiate(memories[mem_index]);
     }
     }
 
 
     wasm_runtime_free(memories);
     wasm_runtime_free(memories);
@@ -369,7 +384,8 @@ memory_instantiate(const WASMModule *module, WASMModuleInstance *parent,
                             < (uint64)num_bytes_per_page * init_page_count) {
                             < (uint64)num_bytes_per_page * init_page_count) {
                 /* Insert app heap before __heap_base */
                 /* Insert app heap before __heap_base */
                 uint64 aux_heap_base = module->aux_heap_base;
                 uint64 aux_heap_base = module->aux_heap_base;
-                uint32 bytes_of_last_page = aux_heap_base % num_bytes_per_page;
+                uint32 bytes_of_last_page =
+                    (uint32)(aux_heap_base % num_bytes_per_page);
                 if (bytes_of_last_page == 0)
                 if (bytes_of_last_page == 0)
                     bytes_of_last_page = num_bytes_per_page;
                     bytes_of_last_page = num_bytes_per_page;
                 uint32 bytes_to_page_end =
                 uint32 bytes_to_page_end =
@@ -380,7 +396,8 @@ memory_instantiate(const WASMModule *module, WASMModuleInstance *parent,
                 heap_offset = aux_heap_base;
                 heap_offset = aux_heap_base;
                 aux_heap_base += heap_size;
                 aux_heap_base += heap_size;
 
 
-                bytes_of_last_page = aux_heap_base % num_bytes_per_page;
+                bytes_of_last_page =
+                    (uint32)(aux_heap_base % num_bytes_per_page);
                 if (bytes_of_last_page == 0)
                 if (bytes_of_last_page == 0)
                     bytes_of_last_page = num_bytes_per_page;
                     bytes_of_last_page = num_bytes_per_page;
                 bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
                 bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
@@ -562,14 +579,14 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
             if (!(module_inst_linked = get_sub_module_inst(
             if (!(module_inst_linked = get_sub_module_inst(
                       module_inst, memory_type->import_module))) {
                       module_inst, memory_type->import_module))) {
                 set_error_buf(error_buf, error_buf_size, "unknown memory");
                 set_error_buf(error_buf, error_buf_size, "unknown memory");
-                memories_deinstantiate(module_inst, memories, memory_count);
+                memories_deinstantiate(module_inst);
                 return NULL;
                 return NULL;
             }
             }
 
 
             if (!(memories[mem_index] = wasm_lookup_memory(
             if (!(memories[mem_index] = wasm_lookup_memory(
                       module_inst_linked, memory_type->field_name))) {
                       module_inst_linked, memory_type->field_name))) {
                 set_error_buf(error_buf, error_buf_size, "unknown memory");
                 set_error_buf(error_buf, error_buf_size, "unknown memory");
-                memories_deinstantiate(module_inst, memories, memory_count);
+                memories_deinstantiate(module_inst);
                 return NULL;
                 return NULL;
             }
             }
         }
         }
@@ -591,7 +608,7 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
                       /* only inst->memories[0] will have an app heap */
                       /* only inst->memories[0] will have an app heap */
                       mem_index == 0 ? heap_size : 0, flags,
                       mem_index == 0 ? heap_size : 0, flags,
                       aux_heap_base_global_data, error_buf, error_buf_size))) {
                       aux_heap_base_global_data, error_buf, error_buf_size))) {
-                memories_deinstantiate(module_inst, memories, memory_count);
+                memories_deinstantiate(module_inst);
                 return NULL;
                 return NULL;
             }
             }
         }
         }
@@ -649,7 +666,7 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
                   /* only inst->memories[0] will have a app heap */
                   /* only inst->memories[0] will have a app heap */
                   mem_index == 0 ? heap_size : 0, module->memories[i].flags,
                   mem_index == 0 ? heap_size : 0, module->memories[i].flags,
                   aux_heap_base_global_data, error_buf, error_buf_size))) {
                   aux_heap_base_global_data, error_buf, error_buf_size))) {
-            memories_deinstantiate(module_inst, memories, memory_count);
+            memories_deinstantiate(module_inst);
             return NULL;
             return NULL;
         }
         }
         mem_index++;
         mem_index++;
@@ -713,14 +730,44 @@ wasm_destroy_memory(WASMMemoryInstance *memory)
 static void
 static void
 tables_deinstantiate(WASMModuleInstance *module_inst)
 tables_deinstantiate(WASMModuleInstance *module_inst)
 {
 {
-    if (module_inst->tables) {
-        wasm_runtime_free(module_inst->tables);
+    if (!module_inst) {
+        return;
     }
     }
-#if WASM_ENABLE_MULTI_MODULE != 0
+
+#if WASM_ENABLE_MULTI_MODULE == 0
+    if (!module_inst->tables) {
+        return;
+    }
+
+    WASMModule *module = module_inst->module;
+    /* only imported tables */
+    for (uint32 i = 0; i < module->import_table_count; i++) {
+        WASMTableInstance *table = module_inst->tables[i];
+        if (!table) {
+            continue;
+        }
+
+        table_elem_type_t *table_elems =
+            wasm_locate_table_elems(module, table, i);
+
+        if (!table_elems) {
+            continue;
+        }
+
+        void *table_imported =
+            ((uint8 *)(table_elems)) - offsetof(WASMTableInstance, elems);
+
+        wasm_runtime_free(table_imported);
+    }
+#else
     if (module_inst->e->table_insts_linked) {
     if (module_inst->e->table_insts_linked) {
         wasm_runtime_free(module_inst->e->table_insts_linked);
         wasm_runtime_free(module_inst->e->table_insts_linked);
+        module_inst->e->table_insts_linked = NULL;
     }
     }
 #endif
 #endif
+
+    wasm_runtime_free(module_inst->tables);
+    module_inst->tables = NULL;
 }
 }
 
 
 /**
 /**
@@ -728,14 +775,15 @@ tables_deinstantiate(WASMModuleInstance *module_inst)
  */
  */
 static WASMTableInstance **
 static WASMTableInstance **
 tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
 tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
-                   WASMTableInstance *first_table, char *error_buf,
-                   uint32 error_buf_size)
+                   WASMTableInstance *table_data,
+                   const WASMExternInstance *imports, uint32 import_count,
+                   char *error_buf, uint32 error_buf_size)
 {
 {
     WASMImport *import;
     WASMImport *import;
     uint32 table_index = 0, i;
     uint32 table_index = 0, i;
     uint32 table_count = module->import_table_count + module->table_count;
     uint32 table_count = module->import_table_count + module->table_count;
     uint64 total_size = (uint64)sizeof(WASMTableInstance *) * table_count;
     uint64 total_size = (uint64)sizeof(WASMTableInstance *) * table_count;
-    WASMTableInstance **tables, *table = first_table;
+    WASMTableInstance **tables, *table = table_data;
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
     uint64 total_size_of_tables_linked =
     uint64 total_size_of_tables_linked =
         (uint64)sizeof(WASMTableInstance *) * module->import_table_count;
         (uint64)sizeof(WASMTableInstance *) * module->import_table_count;
@@ -757,39 +805,43 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
     /* instantiate tables from import section */
     /* instantiate tables from import section */
     import = module->import_tables;
     import = module->import_tables;
     for (i = 0; i < module->import_table_count; i++, import++) {
     for (i = 0; i < module->import_table_count; i++, import++) {
-        uint32 max_size_fixed = 0;
+        WASMTableImport *import_table_type = &(module->import_tables->u.table);
+        uint32 max_size_fixed = wasm_get_tbl_data_slots(
+            &import_table_type->table_type, import_table_type);
+
+        /* sync up with table_size in wasm_instantiate() */
+        total_size = offsetof(WASMTableInstance, elems);
+
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
         WASMTableInstance *table_inst_linked = NULL;
         WASMTableInstance *table_inst_linked = NULL;
         WASMModuleInstance *module_inst_linked = NULL;
         WASMModuleInstance *module_inst_linked = NULL;
 
 
-        if (import->u.table.import_module) {
+        if (import_table_type->import_module) {
             if (!(module_inst_linked = get_sub_module_inst(
             if (!(module_inst_linked = get_sub_module_inst(
-                      module_inst, import->u.table.import_module))) {
+                      module_inst, import_table_type->import_module))) {
                 set_error_buf(error_buf, error_buf_size, "unknown table");
                 set_error_buf(error_buf, error_buf_size, "unknown table");
                 goto fail;
                 goto fail;
             }
             }
 
 
             if (!(table_inst_linked = wasm_lookup_table(
             if (!(table_inst_linked = wasm_lookup_table(
-                      module_inst_linked, import->u.table.field_name))) {
+                      module_inst_linked, import_table_type->field_name))) {
                 set_error_buf(error_buf, error_buf_size, "unknown table");
                 set_error_buf(error_buf, error_buf_size, "unknown table");
                 goto fail;
                 goto fail;
             }
             }
-
-            total_size = offsetof(WASMTableInstance, elems);
         }
         }
-        else
-#endif
-        {
+        else {
             /* in order to save memory, alloc resource as few as possible */
             /* in order to save memory, alloc resource as few as possible */
-            max_size_fixed = import->u.table.table_type.possible_grow
-                                 ? import->u.table.table_type.max_size
-                                 : import->u.table.table_type.init_size;
+            max_size_fixed = import_table_type->table_type.possible_grow
+                                 ? import_table_type->table_type.max_size
+                                 : import_table_type->table_type.init_size;
 
 
             /* it is a built-in table, every module has its own */
             /* it is a built-in table, every module has its own */
-            total_size = offsetof(WASMTableInstance, elems);
             /* store function indexes for non-gc, object pointers for gc */
             /* store function indexes for non-gc, object pointers for gc */
             total_size += (uint64)sizeof(table_elem_type_t) * max_size_fixed;
             total_size += (uint64)sizeof(table_elem_type_t) * max_size_fixed;
         }
         }
+#else
+        total_size += sizeof(table_elem_type_t *);
+#endif /* WASM_ENABLE_MULTI_MODULE != 0 */
 
 
         tables[table_index++] = table;
         tables[table_index++] = table;
 
 
@@ -801,10 +853,11 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
            uninitialized elements */
            uninitialized elements */
 #endif
 #endif
 
 
-        table->is_table64 = import->u.table.table_type.flags & TABLE64_FLAG;
+        table->is_table64 = import_table_type->table_type.flags & TABLE64_FLAG;
 
 
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
         *table_linked = table_inst_linked;
         *table_linked = table_inst_linked;
+
         if (table_inst_linked != NULL) {
         if (table_inst_linked != NULL) {
             table->elem_type = table_inst_linked->elem_type;
             table->elem_type = table_inst_linked->elem_type;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
@@ -813,44 +866,61 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
             table->cur_size = table_inst_linked->cur_size;
             table->cur_size = table_inst_linked->cur_size;
             table->max_size = table_inst_linked->max_size;
             table->max_size = table_inst_linked->max_size;
         }
         }
-        else
-#endif
-        {
-            table->elem_type = import->u.table.table_type.elem_type;
+        else {
+            table->elem_type = import_table_type->table_type.elem_type;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
             table->elem_ref_type.elem_ref_type =
             table->elem_ref_type.elem_ref_type =
-                import->u.table.table_type.elem_ref_type;
+                import_table_type->table_type.elem_ref_type;
 #endif
 #endif
-            table->cur_size = import->u.table.table_type.init_size;
+            table->cur_size = import_table_type->table_type.init_size;
             table->max_size = max_size_fixed;
             table->max_size = max_size_fixed;
         }
         }
 
 
-        table = (WASMTableInstance *)((uint8 *)table + (uint32)total_size);
-#if WASM_ENABLE_MULTI_MODULE != 0
-        table_linked++;
+#else
+
+        table->elem_type = import_table_type->table_type.elem_type;
+#if WASM_ENABLE_GC != 0
+        table->elem_ref_type.elem_ref_type =
+            import_table_type->table_type.elem_ref_type;
+#endif
+        table->cur_size = import_table_type->table_type.init_size;
+        table->max_size = max_size_fixed;
+
+        /* use import table elem */
+        const WASMExternInstance *extern_inst =
+            wasm_runtime_get_extern_instance(imports, import_count,
+                                             WASM_IMPORT_EXPORT_KIND_TABLE, i);
+        if (!extern_inst) {
+            LOG_ERROR("missing an import table(%s, %s)",
+                      import_table_type->module_name,
+                      import_table_type->field_name);
+            return NULL;
+        }
+
+        /* just in case */
+#ifndef NDEBUG
+        if (strcmp(import_table_type->field_name, extern_inst->field_name)) {
+            LOG_ERROR("mismatched import table name: expect \"%s\", got \"%s\"",
+                      import_table_type->field_name, extern_inst->field_name);
+            return NULL;
+        }
 #endif
 #endif
+
+        /* store the pointer value */
+        table->elems[0] = (table_elem_type_t)extern_inst->u.table->elems;
+#endif /* WASM_ENABLE_MULTI_MODULE == 0 */
+
+        table = (WASMTableInstance *)((uint8 *)table + (uint32)total_size);
     }
     }
 
 
     /* instantiate tables from table section */
     /* instantiate tables from table section */
     for (i = 0; i < module->table_count; i++) {
     for (i = 0; i < module->table_count; i++) {
-        uint32 max_size_fixed = 0;
+        uint32 max_size_fixed =
+            wasm_get_tbl_data_slots(&module->tables[i].table_type, NULL);
 
 
         total_size = offsetof(WASMTableInstance, elems);
         total_size = offsetof(WASMTableInstance, elems);
-#if WASM_ENABLE_MULTI_MODULE != 0
-        /* in case, a module which imports this table will grow it */
-        max_size_fixed = module->tables[i].table_type.max_size;
-#else
-        max_size_fixed = module->tables[i].table_type.possible_grow
-                             ? module->tables[i].table_type.max_size
-                             : module->tables[i].table_type.init_size;
-#endif
-#if WASM_ENABLE_GC == 0
-        /* Store function indexes */
-        total_size += sizeof(uintptr_t) * (uint64)max_size_fixed;
-#else
-        /* Store object pointers */
-        total_size += sizeof(uintptr_t) * (uint64)max_size_fixed;
-#endif
+        /* Store function indexes or object pointer */
+        total_size += sizeof(table_elem_type_t) * (uint64)max_size_fixed;
 
 
         tables[table_index++] = table;
         tables[table_index++] = table;
 
 
@@ -876,6 +946,7 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
     bh_assert(table_index == table_count);
     bh_assert(table_index == table_count);
     (void)module_inst;
     (void)module_inst;
     return tables;
     return tables;
+
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
 fail:
 fail:
     wasm_runtime_free(tables);
     wasm_runtime_free(tables);
@@ -972,7 +1043,7 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
         function->local_offsets = function->u.func->local_offsets;
         function->local_offsets = function->u.func->local_offsets;
 
 
 #if WASM_ENABLE_FAST_INTERP != 0
 #if WASM_ENABLE_FAST_INTERP != 0
-        function->const_cell_num = function->u.func->const_cell_num;
+        function->const_cell_num = (uint16)function->u.func->const_cell_num;
 #endif
 #endif
 
 
         function++;
         function++;
@@ -2241,13 +2312,15 @@ wasm_global_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap)
 static bool
 static bool
 wasm_table_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap)
 wasm_table_traverse_gc_rootset(WASMModuleInstance *module_inst, void *heap)
 {
 {
-    WASMTableInstance **tables = module_inst->tables, *table;
+    WASMTableInstance **tables = module_inst->tables;
     uint32 table_count = module_inst->table_count, i, j;
     uint32 table_count = module_inst->table_count, i, j;
-    WASMObjectRef gc_obj, *table_elems;
+    WASMObjectRef gc_obj;
 
 
     for (i = 0; i < table_count; i++) {
     for (i = 0; i < table_count; i++) {
-        table = tables[i];
-        table_elems = (WASMObjectRef *)table->elems;
+        WASMTableInstance *table = tables[i];
+        WASMObjectRef *table_elems = (WASMObjectRef *)wasm_locate_table_elems(
+            module_inst->module, table, i);
+
         for (j = 0; j < table->cur_size; j++) {
         for (j = 0; j < table->cur_size; j++) {
             gc_obj = table_elems[j];
             gc_obj = table_elems[j];
             if (wasm_obj_is_created_from_heap(gc_obj)) {
             if (wasm_obj_is_created_from_heap(gc_obj)) {
@@ -2526,35 +2599,32 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
 
 
     /* Calculate the size of table data */
     /* Calculate the size of table data */
     for (i = 0; i < module->import_table_count; i++) {
     for (i = 0; i < module->import_table_count; i++) {
-        WASMTableImport *import_table = &module->import_tables[i].u.table;
         table_size += offsetof(WASMTableInstance, elems);
         table_size += offsetof(WASMTableInstance, elems);
+
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
+        WASMTableImport *import_table = &module->import_tables[i].u.table;
+        /* all tables have its own elems. */
         table_size += (uint64)sizeof(table_elem_type_t)
         table_size += (uint64)sizeof(table_elem_type_t)
                       * import_table->table_type.max_size;
                       * import_table->table_type.max_size;
 #else
 #else
-        table_size += (uint64)sizeof(table_elem_type_t)
-                      * (import_table->table_type.possible_grow
-                             ? import_table->table_type.max_size
-                             : import_table->table_type.init_size);
+        /* refer to the imported table's elems */
+        table_size += (uint64)sizeof(table_elem_type_t);
 #endif
 #endif
     }
     }
+
     for (i = 0; i < module->table_count; i++) {
     for (i = 0; i < module->table_count; i++) {
         WASMTable *table = module->tables + i;
         WASMTable *table = module->tables + i;
+
+        uint32 max_size_fixed =
+            wasm_get_tbl_data_slots(&table->table_type, NULL);
+
         table_size += offsetof(WASMTableInstance, elems);
         table_size += offsetof(WASMTableInstance, elems);
-#if WASM_ENABLE_MULTI_MODULE != 0
-        table_size +=
-            (uint64)sizeof(table_elem_type_t) * table->table_type.max_size;
-#else
-        table_size +=
-            (uint64)sizeof(table_elem_type_t)
-            * (table->table_type.possible_grow ? table->table_type.max_size
-                                               : table->table_type.init_size);
-#endif
+        table_size += (uint64)sizeof(table_elem_type_t) * max_size_fixed;
     }
     }
     total_size += table_size;
     total_size += table_size;
 
 
     /* The offset of WASMModuleInstanceExtra, make it 8-byte aligned */
     /* The offset of WASMModuleInstanceExtra, make it 8-byte aligned */
-    total_size = (total_size + 7LL) & ~7LL;
+    total_size = (total_size + 7ULL) & ~7ULL;
     extra_info_offset = (uint32)total_size;
     extra_info_offset = (uint32)total_size;
     total_size += sizeof(WASMModuleInstanceExtra);
     total_size += sizeof(WASMModuleInstanceExtra);
 
 
@@ -2701,9 +2771,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                   aux_heap_base_global_data, imports, import_count, error_buf,
                   aux_heap_base_global_data, imports, import_count, error_buf,
                   error_buf_size)))
                   error_buf_size)))
         || (module_inst->table_count > 0
         || (module_inst->table_count > 0
-            && !(module_inst->tables =
-                     tables_instantiate(module, module_inst, first_table,
-                                        error_buf, error_buf_size)))
+            && !(module_inst->tables = tables_instantiate(
+                     module, module_inst, first_table, imports, import_count,
+                     error_buf, error_buf_size)))
         || (module_inst->e->function_count > 0
         || (module_inst->e->function_count > 0
             && !(module_inst->e->functions = functions_instantiate(
             && !(module_inst->e->functions = functions_instantiate(
                      module, module_inst, error_buf, error_buf_size)))
                      module, module_inst, error_buf, error_buf_size)))
@@ -2976,10 +3046,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
 
 
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
     /* Initialize the table data with init expr */
     /* Initialize the table data with init expr */
+    /* bypass WASMTableImport */
     for (i = 0; i < module->table_count; i++) {
     for (i = 0; i < module->table_count; i++) {
         WASMTable *table = module->tables + i;
         WASMTable *table = module->tables + i;
-        WASMTableInstance *table_inst = module_inst->tables[i];
-        table_elem_type_t *table_data;
+        /*TBC: confirm*/
+        WASMTableInstance *table_inst =
+            module_inst->tables[i + module->import_table_count];
         uint32 j;
         uint32 j;
 
 
         if (table->init_expr.init_expr_type == 0) {
         if (table->init_expr.init_expr_type == 0) {
@@ -2987,7 +3059,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
             continue;
             continue;
         }
         }
 
 
-        table_data = table_inst->elems;
+        table_elem_type_t *table_data =
+            wasm_locate_table_elems(module, table_inst, i);
 
 
         bh_assert(
         bh_assert(
             table->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
             table->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
@@ -3035,7 +3108,6 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
         WASMTableSeg *table_seg = module->table_segments + i;
         WASMTableSeg *table_seg = module->table_segments + i;
         /* has check it in loader */
         /* has check it in loader */
         WASMTableInstance *table = module_inst->tables[table_seg->table_index];
         WASMTableInstance *table = module_inst->tables[table_seg->table_index];
-        table_elem_type_t *table_data;
         uint32 j;
         uint32 j;
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
         uint8 tbl_elem_type;
         uint8 tbl_elem_type;
@@ -3078,7 +3150,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
         (void)tbl_max_size;
         (void)tbl_max_size;
 #endif /* end of WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */
 #endif /* end of WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */
 
 
-        table_data = table->elems;
+        table_elem_type_t *table_data =
+            wasm_locate_table_elems(module, table, table_seg->table_index);
+
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
         if (table_seg->table_index < module->import_table_count
         if (table_seg->table_index < module->import_table_count
             && module_inst->e->table_insts_linked[table_seg->table_index]) {
             && module_inst->e->table_insts_linked[table_seg->table_index]) {
@@ -3521,8 +3595,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
 #endif
 #endif
 
 
     if (module_inst->memory_count > 0) {
     if (module_inst->memory_count > 0) {
-        memories_deinstantiate(module_inst, module_inst->memories,
-                               module_inst->memory_count);
+        memories_deinstantiate(module_inst);
     }
     }
 
 
     if (module_inst->import_func_ptrs) {
     if (module_inst->import_func_ptrs) {
@@ -4079,7 +4152,9 @@ wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx,
     }
     }
 
 
     /* fill in */
     /* fill in */
-    new_table_data_start = table_inst->elems + table_inst->cur_size;
+    table_elem_type_t *table_elems =
+        wasm_locate_table_elems(module_inst->module, table_inst, table_idx);
+    new_table_data_start = table_elems + table_inst->cur_size;
     for (i = 0; i < inc_size; ++i) {
     for (i = 0; i < inc_size; ++i) {
         new_table_data_start[i] = init_val;
         new_table_data_start[i] = init_val;
     }
     }
@@ -4113,7 +4188,9 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 tbl_elem_idx,
         goto got_exception;
         goto got_exception;
     }
     }
 
 
-    tbl_elem_val = ((table_elem_type_t *)table_inst->elems)[tbl_elem_idx];
+    table_elem_type_t *table_elems =
+        wasm_locate_table_elems(module_inst->module, table_inst, tbl_idx);
+    tbl_elem_val = table_elems[tbl_elem_idx];
     if (tbl_elem_val == NULL_REF) {
     if (tbl_elem_val == NULL_REF) {
         wasm_set_exception(module_inst, "uninitialized element");
         wasm_set_exception(module_inst, "uninitialized element");
         goto got_exception;
         goto got_exception;
@@ -4774,7 +4851,6 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
 {
 {
     WASMTableInstance *tbl_inst;
     WASMTableInstance *tbl_inst;
     WASMTableSeg *tbl_seg;
     WASMTableSeg *tbl_seg;
-    table_elem_type_t *table_elems;
     InitializerExpression *tbl_seg_init_values = NULL, *init_values;
     InitializerExpression *tbl_seg_init_values = NULL, *init_values;
     uint32 i, tbl_seg_len = 0;
     uint32 i, tbl_seg_len = 0;
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
@@ -4805,7 +4881,9 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
         return;
         return;
     }
     }
 
 
-    table_elems = tbl_inst->elems + dst_offset;
+    table_elem_type_t *table_elems =
+        wasm_locate_table_elems(module_inst->module, tbl_inst, tbl_idx);
+    table_elems = table_elems + dst_offset;
     init_values = tbl_seg_init_values + src_offset;
     init_values = tbl_seg_init_values + src_offset;
 
 
     for (i = 0; i < length; i++) {
     for (i = 0; i < length; i++) {
@@ -4879,8 +4957,10 @@ llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx,
         return;
         return;
     }
     }
 
 
+    table_elem_type_t *table_elems =
+        wasm_locate_table_elems(module_inst->module, tbl_inst, tbl_idx);
     for (; length != 0; data_offset++, length--) {
     for (; length != 0; data_offset++, length--) {
-        tbl_inst->elems[data_offset] = (table_elem_type_t)val;
+        table_elems[data_offset] = (table_elem_type_t)val;
     }
     }
 }
 }
 
 
@@ -4924,8 +5004,10 @@ llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx,
     }
     }
 
 
     /* fill in */
     /* fill in */
+    table_elem_type_t *table_elems =
+        wasm_locate_table_elems(module_inst->module, tbl_inst, tbl_idx);
     for (i = 0; i < inc_size; ++i) {
     for (i = 0; i < inc_size; ++i) {
-        tbl_inst->elems[tbl_inst->cur_size + i] = (table_elem_type_t)init_val;
+        table_elems[tbl_inst->cur_size + i] = (table_elem_type_t)init_val;
     }
     }
 
 
     tbl_inst->cur_size = total_size;
     tbl_inst->cur_size = total_size;
@@ -5195,19 +5277,19 @@ wasm_get_module_name(WASMModule *module)
  */
  */
 int32
 int32
 wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst,
 wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst,
-                     WASMExternInstance *out, int32 out_len)
+                     WASMExternInstance *out, uint32 out_len)
 {
 {
     if (!module || !inst || !out)
     if (!module || !inst || !out)
         return -1;
         return -1;
 
 
-    int32 spawned_import_count = module->import_count;
+    uint32 spawned_import_count = module->import_count;
     if (spawned_import_count > out_len) {
     if (spawned_import_count > out_len) {
         LOG_WARNING("The number of imported functions is more than the "
         LOG_WARNING("The number of imported functions is more than the "
                     "length of provided buffer ");
                     "length of provided buffer ");
         return -1;
         return -1;
     }
     }
 
 
-    for (int32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) {
+    for (uint32 i = 0, import_memory_index = 0; i < spawned_import_count; i++) {
         wasm_import_t import_type = { 0 };
         wasm_import_t import_type = { 0 };
 
 
         wasm_runtime_get_import_type((WASMModuleCommon *)module, i,
         wasm_runtime_get_import_type((WASMModuleCommon *)module, i,
@@ -5224,6 +5306,7 @@ wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst,
 #endif
 #endif
             import_memory_index++;
             import_memory_index++;
         }
         }
+        /*TODO: shared_table, shared_global ?*/
         else {
         else {
             LOG_WARNING("for spawned, inherit() import(%s,%s) kind %d",
             LOG_WARNING("for spawned, inherit() import(%s,%s) kind %d",
                         import_type.module_name, import_type.name,
                         import_type.module_name, import_type.name,
@@ -5236,19 +5319,19 @@ wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst,
 
 
 void
 void
 wasm_disinherit_imports(WASMModule *module, WASMExternInstance *imports,
 wasm_disinherit_imports(WASMModule *module, WASMExternInstance *imports,
-                        int32 import_count)
+                        uint32 import_count)
 {
 {
     if (!module || !imports)
     if (!module || !imports)
         return;
         return;
 
 
-    int32 spawned_import_count = module->import_count;
+    uint32 spawned_import_count = module->import_count;
     if (spawned_import_count > import_count) {
     if (spawned_import_count > import_count) {
         LOG_WARNING("The number of imported functions is more than the "
         LOG_WARNING("The number of imported functions is more than the "
                     "length of provided buffer ");
                     "length of provided buffer ");
         return;
         return;
     }
     }
 
 
-    for (int32 i = 0; i < import_count; i++) {
+    for (uint32 i = 0; i < import_count; i++) {
         WASMExternInstance *import = imports + i;
         WASMExternInstance *import = imports + i;
 
 
         if (import->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
         if (import->kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
@@ -5266,3 +5349,44 @@ wasm_disinherit_imports(WASMModule *module, WASMExternInstance *imports,
     }
     }
 }
 }
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
+
+WASMTableInstance *
+wasm_create_table(const WASMModule *module, const WASMTableType *type)
+{
+    /* not an import table for sure */
+    uint32 max_size = wasm_get_tbl_data_slots(type, NULL);
+
+    uint64 table_size = offsetof(WASMTableInstance, elems);
+    table_size += sizeof(table_elem_type_t) * (uint64)max_size;
+
+    WASMTableInstance *table = runtime_malloc(table_size, NULL, 0);
+    if (!table) {
+        return NULL;
+    }
+
+    table->cur_size = type->init_size;
+    table->elem_type = type->elem_type;
+    table->max_size = max_size;
+#if WASM_ENABLE_GC != 0
+    table->elem_ref_type.elem_ref_type = type->elem_ref_type;
+#endif
+
+    /* Set all elements to -1 or NULL_REF to mark them as uninitialized
+     * elements */
+#if WASM_ENABLE_GC == 0
+    memset(table->elems, 0xff, sizeof(table_elem_type_t) * table->max_size);
+#else
+    memset(table->elems, 0x00, sizeof(table_elem_type_t) * table->max_size);
+#endif
+
+    return table;
+}
+
+void
+wasm_destroy_table(WASMTableInstance *table)
+{
+    if (!table)
+        return;
+
+    wasm_runtime_free(table);
+}

+ 53 - 2
core/iwasm/interpreter/wasm_runtime.h

@@ -166,6 +166,7 @@ struct WASMMemoryInstance {
 struct WASMTableInstance {
 struct WASMTableInstance {
     /* The element type */
     /* The element type */
     uint8 elem_type;
     uint8 elem_type;
+    /* TODO: may not used in AOTTableInstance */
     uint8 is_table64;
     uint8 is_table64;
     uint8 __padding__[6];
     uint8 __padding__[6];
     union {
     union {
@@ -179,6 +180,10 @@ struct WASMTableInstance {
     /* Maximum size */
     /* Maximum size */
     uint32 max_size;
     uint32 max_size;
     /* Table elements */
     /* Table elements */
+    /*
+     * if imported tables, it is table_elem_type_t[0][cur_size]
+     * if local tables, it is table_elem_type_t[cur_size]
+     */
     table_elem_type_t elems[1];
     table_elem_type_t elems[1];
 };
 };
 
 
@@ -522,6 +527,42 @@ wasm_get_func_code_end(WASMFunctionInstance *func)
 #endif
 #endif
 }
 }
 
 
+static inline table_elem_type_t *
+wasm_locate_table_elems(const WASMModule *module, WASMTableInstance *table,
+                        uint32 table_index)
+{
+#if WASM_ENABLE_MULTI_MODULE == 0
+    if (table_index < module->import_table_count) {
+        table_elem_type_t **table_elems =
+            (table_elem_type_t **)(uintptr_t)table->elems;
+
+        return *table_elems;
+    }
+#endif
+    return table->elems;
+}
+
+static inline uint32
+wasm_get_tbl_data_slots(const WASMTableType *table_type,
+                        const WASMTableImport *import_type)
+{
+#if WASM_ENABLE_MULTI_MODULE != 0
+    if (import_type) {
+        if (import_type->import_module) {
+            /* linked with other modules */
+            return table_type->max_size;
+        }
+
+        /* else linked with built-ins */
+    }
+    return table_type->max_size;
+#else
+    /* in order to save memory, alloc resource as few as possible */
+    return table_type->possible_grow ? table_type->max_size
+                                     : table_type->init_size;
+#endif
+}
+
 WASMModule *
 WASMModule *
 wasm_load(uint8 *buf, uint32 size,
 wasm_load(uint8 *buf, uint32 size,
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
@@ -898,13 +939,23 @@ wasm_get_module_name(WASMModule *module);
 #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0
 #if WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0
 int32
 int32
 wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst,
 wasm_inherit_imports(WASMModule *module, WASMModuleInstance *inst,
-                     WASMExternInstance *out, int32 out_len);
+                     WASMExternInstance *out, uint32 out_len);
 
 
 void
 void
 wasm_disinherit_imports(WASMModule *module, WASMExternInstance *imports,
 wasm_disinherit_imports(WASMModule *module, WASMExternInstance *imports,
-                        int32 import_count);
+                        uint32 import_count);
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
 #endif /* WASM_ENABLE_LIB_WASI_THREADS != 0 || WASM_ENABLE_THREAD_MGR != 0 */
 
 
+WASMTableInstance *
+wasm_create_table(const WASMModule *module, const WASMTableType *type);
+
+bool
+wasm_set_table_elem(const WASMModule *module, WASMTableInstance *table,
+                    uint32 index, uint32 func_idx);
+
+void
+wasm_destroy_table(WASMTableInstance *table);
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 3 - 3
product-mini/platforms/posix/main.c

@@ -671,12 +671,12 @@ main(int argc, char *argv[])
         else if (!strncmp(argv[0], "--stack-size=", 13)) {
         else if (!strncmp(argv[0], "--stack-size=", 13)) {
             if (argv[0][13] == '\0')
             if (argv[0][13] == '\0')
                 return print_help();
                 return print_help();
-            stack_size = atoi(argv[0] + 13);
+            stack_size = (uint32)atoi(argv[0] + 13);
         }
         }
         else if (!strncmp(argv[0], "--heap-size=", 12)) {
         else if (!strncmp(argv[0], "--heap-size=", 12)) {
             if (argv[0][12] == '\0')
             if (argv[0][12] == '\0')
                 return print_help();
                 return print_help();
-            heap_size = atoi(argv[0] + 12);
+            heap_size = (uint32)atoi(argv[0] + 12);
         }
         }
 #if WASM_ENABLE_FAST_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0
         else if (!strncmp(argv[0], "--jit-codecache-size=", 21)) {
         else if (!strncmp(argv[0], "--jit-codecache-size=", 21)) {
@@ -874,7 +874,7 @@ main(int argc, char *argv[])
     }
     }
 
 
 #if WASM_ENABLE_LOG != 0
 #if WASM_ENABLE_LOG != 0
-    bh_log_set_verbose_level(log_verbose_level);
+    bh_log_set_verbose_level((uint32)log_verbose_level);
 #endif
 #endif
 
 
 #if BH_HAS_DLFCN
 #if BH_HAS_DLFCN

+ 11 - 1
samples/linking/CMakeLists.txt

@@ -9,6 +9,9 @@ set(CMAKE_BUILD_TYPE Debug)
 list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
 list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
 find_package(WASISDK REQUIRED)
 find_package(WASISDK REQUIRED)
 
 
+include(CTest)
+enable_testing()
+
 ################  runtime settings  ################
 ################  runtime settings  ################
 string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
 string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
 include(CheckPIESupported)
 include(CheckPIESupported)
@@ -30,6 +33,12 @@ set(WAMR_BUILD_TAIL_CALL 1)
 set(WAMR_BUILD_THREAD_MGR 0)
 set(WAMR_BUILD_THREAD_MGR 0)
 set(WAMR_BUILD_LIB_WASI_THREADS 0)
 set(WAMR_BUILD_LIB_WASI_THREADS 0)
 
 
+## below two prevent valgrind from crashing
+#TODO: there is a crash if turn it on
+set(WAMR_DISABLE_HW_BOUND_CHECK 0)
+set(WAMR_DISABLE_STACK_HW_BOUND_CHECK 1)
+set(WAMR_DISABLE_WRITE_GS_BASE 1)
+
 # vmlib
 # vmlib
 set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
 set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
 include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
 include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
@@ -38,7 +47,8 @@ target_include_directories(vmlib INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include)
 target_link_libraries(vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl)
 target_link_libraries(vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl)
 
 
 ################  samples  ################
 ################  samples  ################
-add_subdirectory(raw)
+add_subdirectory(import-memory)
+add_subdirectory(import-table)
 
 
 ################ wasm and/or aot ################
 ################ wasm and/or aot ################
 include(ExternalProject)
 include(ExternalProject)

+ 11 - 0
samples/linking/import-memory/CMakeLists.txt

@@ -0,0 +1,11 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
+add_executable(import_memory main.c ${UNCOMMON_SHARED_SOURCE})
+target_link_libraries(import_memory PRIVATE vmlib)
+
+add_test(NAME Test_import_memory
+  COMMAND ./import-memory/import_memory
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..
+)

+ 10 - 6
samples/linking/raw/main.c → samples/linking/import-memory/main.c

@@ -44,10 +44,13 @@ main(int argc, char *argv_main[])
 
 
     /* import type */
     /* import type */
     int32_t import_count = wasm_runtime_get_import_count(module);
     int32_t import_count = wasm_runtime_get_import_count(module);
+    if (import_count < 0)
+        goto unload_module;
+
     wasm_import_t import_type = { 0 };
     wasm_import_t import_type = { 0 };
     int32_t import_memory_index = -1;
     int32_t import_memory_index = -1;
-    for (int i = 0; i < import_count; i++) {
-        wasm_runtime_get_import_type(module, i, &import_type);
+    for (int32_t i = 0; i < import_count; i++) {
+        wasm_runtime_get_import_type(module, (uint32_t)i, &import_type);
         if (import_type.kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
         if (import_type.kind == WASM_IMPORT_EXPORT_KIND_MEMORY) {
             import_memory_index = i;
             import_memory_index = i;
             break;
             break;
@@ -76,6 +79,7 @@ main(int argc, char *argv_main[])
 
 
     /* wasm instance */
     /* wasm instance */
     InstantiationArgs inst_args = {
     InstantiationArgs inst_args = {
+        .default_stack_size = 65536,
         .imports = import_list,
         .imports = import_list,
         .import_count = 10,
         .import_count = 10,
     };
     };
@@ -83,7 +87,9 @@ main(int argc, char *argv_main[])
         module, &inst_args, error_buf, sizeof(error_buf));
         module, &inst_args, error_buf, sizeof(error_buf));
     if (!inst) {
     if (!inst) {
         printf("Instantiate wasm file failed: %s\n", error_buf);
         printf("Instantiate wasm file failed: %s\n", error_buf);
-        goto destroy_memory;
+        wasm_runtime_destroy_memory(module, memory);
+        memory = NULL;
+        goto unload_module;
     }
     }
 
 
     /* export function */
     /* export function */
@@ -94,7 +100,7 @@ main(int argc, char *argv_main[])
         goto destroy_inst;
         goto destroy_inst;
     }
     }
 
 
-    wasm_exec_env_t exec_env = wasm_runtime_create_exec_env(inst, 8192);
+    wasm_exec_env_t exec_env = wasm_runtime_create_exec_env(inst, 65536);
     if (!exec_env) {
     if (!exec_env) {
         printf("Create wasm execution environment failed.\n");
         printf("Create wasm execution environment failed.\n");
         goto destroy_inst;
         goto destroy_inst;
@@ -112,8 +118,6 @@ destroy_exec_env:
     wasm_runtime_destroy_exec_env(exec_env);
     wasm_runtime_destroy_exec_env(exec_env);
 destroy_inst:
 destroy_inst:
     wasm_runtime_deinstantiate(inst);
     wasm_runtime_deinstantiate(inst);
-destroy_memory:
-    wasm_runtime_destroy_memory(module, memory);
 unload_module:
 unload_module:
     wasm_runtime_unload(module);
     wasm_runtime_unload(module);
 release_file_buffer:
 release_file_buffer:

+ 11 - 0
samples/linking/import-table/CMakeLists.txt

@@ -0,0 +1,11 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
+add_executable(import_table main.c ${UNCOMMON_SHARED_SOURCE})
+target_link_libraries(import_table PRIVATE vmlib)
+
+add_test(NAME Test_import_table
+  COMMAND ./import-table/import_table
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..
+)

+ 113 - 0
samples/linking/import-table/main.c

@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include "wasm_export.h"
+#include "bh_read_file.h"
+
+int
+main(int argc, char *argv_main[])
+{
+    int exit_code = EXIT_FAILURE;
+
+    /* runtime */
+    if (!wasm_runtime_init()) {
+        printf("Init runtime failed.\n");
+        return EXIT_FAILURE;
+    }
+
+    wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE);
+
+    /* wasm module file */
+    char *buffer;
+    uint32 buf_size;
+#if WASM_ENABLE_AOT != 0
+    printf("Loading AOT file...\n");
+    buffer = bh_read_file_to_buffer("import_table.aot", &buf_size);
+#else
+    printf("Loading WASM file...\n");
+    buffer = bh_read_file_to_buffer("import_table.wasm", &buf_size);
+#endif
+    if (!buffer) {
+        printf("Open wasm file failed.\n");
+        goto destroy_runtime;
+    }
+
+    /* wasm module */
+    char error_buf[128];
+    wasm_module_t module = wasm_runtime_load((uint8 *)buffer, buf_size,
+                                             error_buf, sizeof(error_buf));
+    if (!module) {
+        printf("Load wasm file failed: %s\n", error_buf);
+        goto release_file_buffer;
+    }
+
+    /* import type */
+    int32_t import_count = wasm_runtime_get_import_count(module);
+    if (import_count < 0)
+        goto unload_module;
+
+    wasm_import_t import_type = { 0 };
+    int32_t import_table_index = -1;
+    for (int32_t i = 0; i < import_count; i++) {
+        wasm_runtime_get_import_type(module, (uint32_t)i, &import_type);
+        if (import_type.kind == WASM_IMPORT_EXPORT_KIND_TABLE) {
+            import_table_index = i;
+            break;
+        }
+    }
+
+    if (import_table_index == -1) {
+        printf("No memory import found.\n");
+        goto unload_module;
+    }
+
+    /* host table */
+    wasm_table_type_t table_type = import_type.u.table_type;
+    wasm_table_inst_t *table = wasm_runtime_create_table(module, table_type);
+    if (!table) {
+        printf("Create table failed.\n");
+        goto unload_module;
+    }
+
+    /* import list */
+    WASMExternInstance import_list[10] = { 0 };
+    import_list[import_table_index].module_name = "host";
+    import_list[import_table_index].field_name = "__indirect_function_table";
+    import_list[import_table_index].kind = WASM_IMPORT_EXPORT_KIND_TABLE;
+    import_list[import_table_index].u.table = table;
+
+    /* wasm instance */
+    InstantiationArgs inst_args = {
+        .imports = import_list,
+        .import_count = 10,
+    };
+    wasm_module_inst_t inst = wasm_runtime_instantiate_ex(
+        module, &inst_args, error_buf, sizeof(error_buf));
+    if (!inst) {
+        printf("Instantiate wasm file failed: %s\n", error_buf);
+        goto destroy_table;
+    }
+
+    /* export function */
+    if (!wasm_application_execute_main(inst, 0, NULL)) {
+        const char *exception = wasm_runtime_get_exception(inst);
+        printf("call wasm function main() failed. %s\n", exception);
+        goto destroy_inst;
+    }
+
+    exit_code = EXIT_SUCCESS;
+
+destroy_inst:
+    wasm_runtime_deinstantiate(inst);
+destroy_table:
+    wasm_runtime_destroy_table(module, table);
+unload_module:
+    wasm_runtime_unload(module);
+release_file_buffer:
+    wasm_runtime_free(buffer);
+destroy_runtime:
+    wasm_runtime_destroy();
+
+    return exit_code;
+}

+ 0 - 6
samples/linking/raw/CMakeLists.txt

@@ -1,6 +0,0 @@
-# Copyright (C) 2019 Intel Corporation.  All rights reserved.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
-add_executable(raw main.c ${UNCOMMON_SHARED_SOURCE})
-target_link_libraries(raw PRIVATE vmlib)

+ 17 - 0
samples/linking/wasm/CMakeLists.txt

@@ -22,6 +22,14 @@ target_link_options(import_memory
 set_target_properties(import_memory PROPERTIES SUFFIX .wasm)
 set_target_properties(import_memory PROPERTIES SUFFIX .wasm)
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_memory.wasm DESTINATION .)
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_memory.wasm DESTINATION .)
 
 
+add_executable(import_table import_table.c)
+target_link_options(import_table
+  PRIVATE
+    LINKER:--import-table
+)
+set_target_properties(import_table PROPERTIES SUFFIX .wasm)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_table.wasm DESTINATION .)
+
 if(WAMR_BUILD_AOT EQUAL 1)
 if(WAMR_BUILD_AOT EQUAL 1)
   add_custom_target (
   add_custom_target (
     import_memory_aot
     import_memory_aot
@@ -31,5 +39,14 @@ if(WAMR_BUILD_AOT EQUAL 1)
     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
   )
   )
   install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_memory.aot DESTINATION .)
   install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_memory.aot DESTINATION .)
+
+  add_custom_target(
+    import_table_aot
+    ALL
+    DEPENDS ${WAMRC_BIN} import_table
+    COMMAND ${WAMRC_BIN} -o import_table.aot import_table.wasm
+    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+  )
+  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/import_table.aot DESTINATION .)
 endif()
 endif()
 
 

+ 40 - 0
samples/linking/wasm/import_table.c

@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+add(int a, int b)
+{
+    return a + b;
+}
+
+int
+subtract(int a, int b)
+{
+    return a - b;
+}
+
+int
+main()
+{
+    int (*operation)(int, int);
+
+    operation = add;
+    int result = operation(5, 3);
+    printf("Result of addition: %d\n", operation(5, 3));
+    assert(result == 8 && "Addition failed");
+
+    operation = subtract;
+    result = operation(5, 3);
+    printf("Result of subtraction: %d\n", operation(5, 3));
+    assert(result == 2 && "Subtraction failed");
+
+    return EXIT_SUCCESS;
+}

+ 3 - 0
tests/wamr-test-suites/spec-test-script/runtest.py

@@ -1148,6 +1148,9 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = '
         cmd.append("--format=object")
         cmd.append("--format=object")
     elif output == 'ir':
     elif output == 'ir':
         cmd.append("--format=llvmir-opt")
         cmd.append("--format=llvmir-opt")
+    
+    if opts.multi_module:
+        cmd.append("--enable-multi-module")
 
 
     # disable llvm link time optimization as it might convert
     # disable llvm link time optimization as it might convert
     # code of tail call into code of dead loop, and stack overflow
     # code of tail call into code of dead loop, and stack overflow

+ 9 - 1
tests/wamr-test-suites/test_wamr.sh

@@ -829,11 +829,19 @@ function build_wamrc()
     fi
     fi
 
 
     echo "Build wamrc for spec test under aot compile type"
     echo "Build wamrc for spec test under aot compile type"
+
+    local EXTRA_COMPILE_FLAGS=""
+    EXTRA_COMPILE_FLAGS+=" -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}"
+
+    if [[ ${ENABLE_DEBUG_VERSION} == 1 ]]; then
+        EXTRA_COMPILE_FLAGS+=" -DCMAKE_BUILD_TYPE=Debug"
+    fi
+
     cd ${WAMR_DIR}/wamr-compiler \
     cd ${WAMR_DIR}/wamr-compiler \
         && ./${BUILD_LLVM_SH} \
         && ./${BUILD_LLVM_SH} \
         && if [ -d build ]; then rm -r build/*; else mkdir build; fi \
         && if [ -d build ]; then rm -r build/*; else mkdir build; fi \
         && cd build \
         && cd build \
-        && cmake .. -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE} \
+        && cmake ${EXTRA_COMPILE_FLAGS} ..  \
         && make -j 4
         && make -j 4
 }
 }
 
 

+ 5 - 0
wamr-compiler/main.c

@@ -207,6 +207,8 @@ print_help()
 #endif
 #endif
     printf("  --mllvm=<option>          Add the LLVM command line option\n");
     printf("  --mllvm=<option>          Add the LLVM command line option\n");
     printf("  --enable-shared-heap      Enable shared heap feature\n");
     printf("  --enable-shared-heap      Enable shared heap feature\n");
+    printf("  --enable-multi-module     Enable multi-module(loader linking) feature. By default, it is \n");
+    printf("                            instantiation linking\n");
     printf("  -v=n                      Set log verbose level (0 to 5, default is 2), larger with more log\n");
     printf("  -v=n                      Set log verbose level (0 to 5, default is 2), larger with more log\n");
     printf("  --version                 Show version information\n");
     printf("  --version                 Show version information\n");
     printf("Examples: wamrc -o test.aot test.wasm\n");
     printf("Examples: wamrc -o test.aot test.wasm\n");
@@ -651,6 +653,9 @@ main(int argc, char *argv[])
         else if (!strcmp(argv[0], "--enable-shared-heap")) {
         else if (!strcmp(argv[0], "--enable-shared-heap")) {
             option.enable_shared_heap = true;
             option.enable_shared_heap = true;
         }
         }
+        else if (!strcmp(argv[0], "--enable-multi-module")) {
+            option.enable_multi_module = true;
+        }
         else if (!strcmp(argv[0], "--version")) {
         else if (!strcmp(argv[0], "--version")) {
             uint32 major, minor, patch;
             uint32 major, minor, patch;
             wasm_runtime_get_version(&major, &minor, &patch);
             wasm_runtime_get_version(&major, &minor, &patch);