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

Add table type API support (#3515)

Add `wasm_runtime_get_export_table_inst` and `wasm_table_get_func_inst`,
and related wasm_table_type_get_xxx APIs.
Benbuck Nason 1 год назад
Родитель
Сommit
3746534010

+ 20 - 19
core/iwasm/aot/aot_loader.c

@@ -1330,24 +1330,25 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
 
     /* keep sync with aot_emit_table_info() aot_emit_aot_file */
     for (i = 0; i < module->import_table_count; i++, import_table++) {
-        read_uint8(buf, buf_end, import_table->elem_type);
-        read_uint8(buf, buf_end, import_table->table_flags);
-        read_uint8(buf, buf_end, import_table->possible_grow);
+        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.possible_grow);
 #if WASM_ENABLE_GC != 0
-        if (wasm_is_type_multi_byte_type(import_table->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);
         }
 #endif
-        read_uint32(buf, buf_end, import_table->table_init_size);
-        read_uint32(buf, buf_end, import_table->table_max_size);
+        read_uint32(buf, buf_end, import_table->table_type.init_size);
+        read_uint32(buf, buf_end, import_table->table_type.max_size);
 #if WASM_ENABLE_GC != 0
-        if (wasm_is_type_multi_byte_type(import_table->elem_type)) {
+        if (wasm_is_type_multi_byte_type(import_table->table_type.elem_type)) {
             read_uint32(buf, buf_end, ref_type.ref_ht_common.heap_type);
 
-            ref_type.ref_type = import_table->elem_type;
+            ref_type.ref_type = import_table->table_type.elem_type;
             /* TODO: check ref_type */
-            if (!(import_table->elem_ref_type = wasm_reftype_set_insert(
-                      module->ref_type_set, &ref_type))) {
+            if (!(import_table->table_type.elem_ref_type =
+                      wasm_reftype_set_insert(module->ref_type_set,
+                                              &ref_type))) {
                 set_error_buf(error_buf, error_buf_size,
                               "insert ref type to hash set failed");
                 return false;
@@ -1383,23 +1384,23 @@ load_table_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
 
     /* Create each table data segment */
     for (i = 0; i < module->table_count; i++, table++) {
-        read_uint8(buf, buf_end, table->elem_type);
-        read_uint8(buf, buf_end, table->table_flags);
-        read_uint8(buf, buf_end, table->possible_grow);
+        read_uint8(buf, buf_end, table->table_type.elem_type);
+        read_uint8(buf, buf_end, table->table_type.flags);
+        read_uint8(buf, buf_end, table->table_type.possible_grow);
 #if WASM_ENABLE_GC != 0
-        if (wasm_is_type_multi_byte_type(table->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);
         }
 #endif
-        read_uint32(buf, buf_end, table->table_init_size);
-        read_uint32(buf, buf_end, table->table_max_size);
+        read_uint32(buf, buf_end, table->table_type.init_size);
+        read_uint32(buf, buf_end, table->table_type.max_size);
 #if WASM_ENABLE_GC != 0
-        if (wasm_is_type_multi_byte_type(table->elem_type)) {
+        if (wasm_is_type_multi_byte_type(table->table_type.elem_type)) {
             read_uint32(buf, buf_end, ref_type.ref_ht_common.heap_type);
 
-            ref_type.ref_type = table->elem_type;
+            ref_type.ref_type = table->table_type.elem_type;
             /* TODO: check ref_type */
-            if (!(table->elem_ref_type = wasm_reftype_set_insert(
+            if (!(table->table_type.elem_ref_type = wasm_reftype_set_insert(
                       module->ref_type_set, &ref_type))) {
                 set_error_buf(error_buf, error_buf_size,
                               "insert ref type to hash set failed");

+ 109 - 24
core/iwasm/aot/aot_runtime.c

@@ -618,23 +618,23 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
     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_init_size;
+            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;
 #if WASM_ENABLE_GC != 0
-            tbl_inst->elem_type = module->tables[i].elem_type;
             tbl_inst->elem_ref_type.elem_ref_type =
-                module->tables[i].elem_ref_type;
+                module->tables[i].table_type.elem_ref_type;
 #endif
         }
         else {
             AOTTable *table = module->tables + (i - module->import_table_count);
-            tbl_inst->cur_size = table->table_init_size;
+            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;
 #if WASM_ENABLE_GC != 0
-            tbl_inst->elem_type = module->tables[i].elem_type;
             tbl_inst->elem_ref_type.elem_ref_type =
-                module->tables[i].elem_ref_type;
+                module->tables[i].table_type.elem_ref_type;
 #endif
         }
 
@@ -1183,6 +1183,75 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
     return true;
 }
 
+AOTFunctionInstance *
+aot_get_function_instance(AOTModuleInstance *module_inst, uint32 func_idx)
+{
+    AOTModule *module = (AOTModule *)module_inst->module;
+    AOTModuleInstanceExtra *extra = (AOTModuleInstanceExtra *)module_inst->e;
+    AOTFunctionInstance *export_funcs =
+        (AOTFunctionInstance *)module_inst->export_functions;
+    uint32 i;
+
+    /* export functions are pre-instantiated */
+    for (i = 0; i < module_inst->export_func_count; i++) {
+        if (export_funcs[i].func_index == func_idx)
+            return &export_funcs[i];
+    }
+
+    exception_lock(module_inst);
+
+    /* allocate functions array if needed */
+    if (!extra->functions) {
+        uint64 func_count =
+            ((uint64)module->import_func_count + module->func_count);
+        uint64 total_size = func_count * (uint64)sizeof(AOTFunctionInstance *);
+
+        if ((func_count == 0)
+            || !(extra->functions = runtime_malloc(total_size, NULL, 0))) {
+            exception_unlock(module_inst);
+            return NULL;
+        }
+
+        extra->function_count = func_count;
+    }
+
+    /* instantiate function if needed */
+    bh_assert(func_idx < extra->function_count);
+    if (!extra->functions[func_idx]) {
+        AOTFunctionInstance *function = (AOTFunctionInstance *)runtime_malloc(
+            sizeof(AOTFunctionInstance), NULL, 0);
+        if (!function) {
+            exception_unlock(module_inst);
+            return NULL;
+        }
+
+        if (func_idx < module->import_func_count) {
+            /* instantiate function from import section */
+            function->is_import_func = true;
+            function->func_name = module->import_funcs[func_idx].func_name;
+            function->func_index = func_idx;
+            function->u.func_import = &module->import_funcs[func_idx];
+        }
+        else {
+            /* instantiate non-import function */
+            uint32 ftype_index =
+                module->func_type_indexes[func_idx - module->import_func_count];
+            function->is_import_func = false;
+            function->func_index = func_idx;
+            function->u.func.func_type =
+                (AOTFuncType *)module->types[ftype_index];
+            function->u.func.func_ptr =
+                module->func_ptrs[func_idx - module->import_func_count];
+        }
+
+        extra->functions[func_idx] = function;
+    }
+
+    exception_unlock(module_inst);
+
+    return extra->functions[func_idx];
+}
+
 static bool
 init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module,
                        char *error_buf, uint32 error_buf_size)
@@ -1490,6 +1559,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
 #if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0
     WASMModuleInstanceExtraCommon *common;
 #endif
+    AOTModuleInstanceExtra *extra = NULL;
     const uint32 module_inst_struct_size =
         offsetof(AOTModuleInstance, global_table_data.bytes);
     const uint64 module_inst_mem_inst_size =
@@ -1543,14 +1613,13 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     module_inst->module = (void *)module;
     module_inst->e =
         (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
+    extra = (AOTModuleInstanceExtra *)module_inst->e;
 
 #if WASM_ENABLE_GC != 0
     /* Initialize gc heap first since it may be used when initializing
        globals and others */
     if (!is_sub_inst) {
         uint32 gc_heap_size = wasm_runtime_get_gc_heap_size_default();
-        AOTModuleInstanceExtra *extra =
-            (AOTModuleInstanceExtra *)module_inst->e;
 
         if (gc_heap_size < GC_HEAP_SIZE_MIN)
             gc_heap_size = GC_HEAP_SIZE_MIN;
@@ -1570,8 +1639,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
 #endif
 
 #if WASM_ENABLE_MULTI_MODULE != 0
-    ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list =
-        &((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list_head;
+    extra->sub_module_inst_list = &extra->sub_module_inst_list_head;
     ret = wasm_runtime_sub_module_instantiate(
         (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst,
         stack_size, heap_size, max_memory_pages, error_buf, error_buf_size);
@@ -1587,7 +1655,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         goto fail;
 
 #if WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_REF_TYPES != 0
-    common = &((AOTModuleInstanceExtra *)module_inst->e)->common;
+    common = &extra->common;
 #endif
 #if WASM_ENABLE_BULK_MEMORY != 0
     if (module->mem_init_data_count > 0) {
@@ -1682,7 +1750,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
 #endif
     module_inst->default_wasm_stack_size = stack_size;
 
-    ((AOTModuleInstanceExtra *)module_inst->e)->stack_sizes =
+    extra->stack_sizes =
         aot_get_data_section_addr(module, AOT_STACK_SIZES_SECTION_NAME, NULL);
 
 #if WASM_ENABLE_PERF_PROFILING != 0
@@ -1885,8 +1953,8 @@ destroy_c_api_frames(Vector *frames)
 void
 aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
 {
-    WASMModuleInstanceExtraCommon *common =
-        &((AOTModuleInstanceExtra *)module_inst->e)->common;
+    AOTModuleInstanceExtra *extra = (AOTModuleInstanceExtra *)module_inst->e;
+    WASMModuleInstanceExtraCommon *common = &extra->common;
     if (module_inst->exec_env_singleton) {
         /* wasm_exec_env_destroy will call
            wasm_cluster_wait_for_all_except_self to wait for other
@@ -1923,6 +1991,16 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
     if (module_inst->export_functions)
         wasm_runtime_free(module_inst->export_functions);
 
+    if (extra->functions) {
+        uint32 func_idx;
+        for (func_idx = 0; func_idx < extra->function_count; ++func_idx) {
+            if (extra->functions[func_idx]) {
+                wasm_runtime_free(extra->functions[func_idx]);
+            }
+        }
+        wasm_runtime_free(extra->functions);
+    }
+
     if (module_inst->func_ptrs)
         wasm_runtime_free(module_inst->func_ptrs);
 
@@ -1934,12 +2012,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
 
 #if WASM_ENABLE_GC != 0
     if (!is_sub_inst) {
-        AOTModuleInstanceExtra *extra =
-            (AOTModuleInstanceExtra *)module_inst->e;
-        if (extra->common.gc_heap_handle)
-            mem_allocator_destroy(extra->common.gc_heap_handle);
-        if (extra->common.gc_heap_pool)
-            wasm_runtime_free(extra->common.gc_heap_pool);
+        if (common->gc_heap_handle)
+            mem_allocator_destroy(common->gc_heap_handle);
+        if (common->gc_heap_pool)
+            wasm_runtime_free(common->gc_heap_pool);
     }
 #endif
 
@@ -2021,7 +2097,9 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
             void (*invoke_native)(void *func_ptr, void *exec_env, uint32 *argv,
                                   uint32 *argv_ret) =
                 func_type->quick_aot_entry;
+            exec_env->attachment = attachment;
             invoke_native(func_ptr, exec_env, argv, argv_ret);
+            exec_env->attachment = NULL;
             ret = !aot_copy_exception(module_inst, NULL);
         }
         else
@@ -2099,6 +2177,7 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
                   unsigned argc, uint32 argv[])
 {
     AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+    AOTModule *module = (AOTModule *)module_inst->module;
     AOTFuncType *func_type = function->is_import_func
                                  ? function->u.func_import->func_type
                                  : function->u.func.func_type;
@@ -2108,6 +2187,7 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
     void *func_ptr = function->is_import_func
                          ? function->u.func_import->func_ptr_linked
                          : function->u.func.func_ptr;
+    void *attachment = NULL;
 #if WASM_ENABLE_MULTI_MODULE != 0
     bh_list *sub_module_list_node = NULL;
     const char *sub_inst_name = NULL;
@@ -2167,6 +2247,10 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
        hw bound check is enabled */
 #endif
 
+    if (function->func_index < module->import_func_count) {
+        attachment = function->u.func_import->attachment;
+    }
+
     /* Set exec env, so it can be later retrieved from instance */
     module_inst->cur_exec_env = exec_env;
 
@@ -2217,7 +2301,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
 #endif
 
         ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
-                                     func_type, NULL, NULL, argv1, argc, argv);
+                                     func_type, NULL, attachment, argv1, argc,
+                                     argv);
 
         if (!ret) {
 #ifdef AOT_STACK_FRAME_DEBUG
@@ -2286,8 +2371,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
         }
 #endif
 
-        ret = invoke_native_internal(exec_env, func_ptr, func_type, NULL, NULL,
-                                     argv, argc, argv);
+        ret = invoke_native_internal(exec_env, func_ptr, func_type, NULL,
+                                     attachment, argv, argc, argv);
 
         if (aot_copy_exception(module_inst, NULL)) {
 #ifdef AOT_STACK_FRAME_DEBUG
@@ -2888,8 +2973,8 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
         /* Call native function */
         import_func = aot_module->import_funcs + func_idx;
         signature = import_func->signature;
+        attachment = import_func->attachment;
         if (import_func->call_conv_raw) {
-            attachment = import_func->attachment;
             ret = wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type,
                                                  signature, attachment, argv,
                                                  argc, argv);

+ 13 - 0
core/iwasm/aot/aot_runtime.h

@@ -104,6 +104,8 @@ typedef struct AOTFunctionInstance {
 typedef struct AOTModuleInstanceExtra {
     DefPointer(const uint32 *, stack_sizes);
     WASMModuleInstanceExtraCommon common;
+    AOTFunctionInstance **functions;
+    uint32 function_count;
 #if WASM_ENABLE_MULTI_MODULE != 0
     bh_list sub_module_inst_list_head;
     bh_list *sub_module_inst_list;
@@ -507,6 +509,17 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst);
 AOTFunctionInstance *
 aot_lookup_function(const AOTModuleInstance *module_inst, const char *name);
 
+/**
+ * Get a function in the AOT module instance.
+ *
+ * @param module_inst the module instance
+ * @param func_idx the index of the function
+ *
+ * @return the function instance found
+ */
+AOTFunctionInstance *
+aot_get_function_instance(AOTModuleInstance *module_inst, uint32_t func_idx);
+
 /**
  * Call the given AOT function of a AOT module instance with
  * arguments.

+ 8 - 8
core/iwasm/common/wasm_c_api.c

@@ -2620,9 +2620,9 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
                        - import_memory_count);
                 module_name_rt = import->u.names.module_name;
                 field_name_rt = import->u.names.field_name;
-                elem_type_rt = import->u.table.elem_type;
-                min_size = import->u.table.init_size;
-                max_size = import->u.table.max_size;
+                elem_type_rt = import->u.table.table_type.elem_type;
+                min_size = import->u.table.table_type.init_size;
+                max_size = import->u.table.table_type.max_size;
             }
 #endif
 
@@ -2634,9 +2634,9 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
                        - import_memory_count);
                 module_name_rt = import->module_name;
                 field_name_rt = import->table_name;
-                elem_type_rt = import->elem_type;
-                min_size = import->table_init_size;
-                max_size = import->table_max_size;
+                elem_type_rt = import->table_type.elem_type;
+                min_size = import->table_type.init_size;
+                max_size = import->table_type.max_size;
             }
 #endif
 
@@ -4195,13 +4195,13 @@ wasm_table_size(const wasm_table_t *table)
         if (table->table_idx_rt < module_aot->import_table_count) {
             AOTImportTable *table_aot =
                 module_aot->import_tables + table->table_idx_rt;
-            return table_aot->table_init_size;
+            return table_aot->table_type.init_size;
         }
         else {
             AOTTable *table_aot =
                 module_aot->tables
                 + (table->table_idx_rt - module_aot->import_table_count);
-            return table_aot->table_init_size;
+            return table_aot->table_type.init_size;
         }
     }
 #endif

+ 173 - 15
core/iwasm/common/wasm_runtime_common.c

@@ -1966,6 +1966,118 @@ wasm_runtime_get_export_global_inst(WASMModuleInstanceCommon *const module_inst,
     return false;
 }
 
+bool
+wasm_runtime_get_export_table_inst(WASMModuleInstanceCommon *const module_inst,
+                                   char const *name,
+                                   wasm_table_inst_t *table_inst)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        const WASMModuleInstance *wasm_module_inst =
+            (const WASMModuleInstance *)module_inst;
+        const WASMModule *wasm_module = wasm_module_inst->module;
+        uint32 i;
+        for (i = 0; i < wasm_module->export_count; i++) {
+            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;
+            }
+        }
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT) {
+        const AOTModuleInstance *aot_module_inst =
+            (AOTModuleInstance *)module_inst;
+        const AOTModule *aot_module = (AOTModule *)aot_module_inst->module;
+        uint32 i;
+        for (i = 0; i < aot_module->export_count; i++) {
+            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;
+            }
+        }
+    }
+#endif
+
+    return false;
+}
+
+WASMFunctionInstanceCommon *
+wasm_table_get_func_inst(struct WASMModuleInstanceCommon *const module_inst,
+                         const wasm_table_inst_t *table_inst, uint32_t idx)
+{
+    if (!table_inst) {
+        bh_assert(0);
+        return NULL;
+    }
+
+    if (idx >= table_inst->cur_size) {
+        bh_assert(0);
+        return NULL;
+    }
+
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        const WASMModuleInstance *wasm_module_inst =
+            (const WASMModuleInstance *)module_inst;
+        table_elem_type_t tbl_elem_val =
+            ((table_elem_type_t *)table_inst->elems)[idx];
+        if (tbl_elem_val == NULL_REF) {
+            return NULL;
+        }
+
+#if WASM_ENABLE_GC == 0
+        uint32 func_idx = (uint32)tbl_elem_val;
+#else
+        uint32 func_idx =
+            wasm_func_obj_get_func_idx_bound((WASMFuncObjectRef)tbl_elem_val);
+#endif
+
+        bh_assert(func_idx < wasm_module_inst->e->function_count);
+        return wasm_module_inst->e->functions + func_idx;
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT) {
+        AOTModuleInstance *aot_module_inst = (AOTModuleInstance *)module_inst;
+        uint32 func_idx;
+        table_elem_type_t tbl_elem_val =
+            ((table_elem_type_t *)table_inst->elems)[idx];
+        if (tbl_elem_val == NULL_REF) {
+            return NULL;
+        }
+
+#if WASM_ENABLE_GC == 0
+        func_idx = (uint32)tbl_elem_val;
+#else
+        func_idx =
+            wasm_func_obj_get_func_idx_bound((WASMFuncObjectRef)tbl_elem_val);
+#endif
+
+        return aot_get_function_instance(aot_module_inst, func_idx);
+    }
+#endif
+
+    return NULL;
+}
+
 void *
 wasm_runtime_get_function_attachment(WASMExecEnv *exec_env)
 {
@@ -3899,6 +4011,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
             import_type->name = aot_import_table->table_name;
             import_type->kind = WASM_IMPORT_EXPORT_KIND_TABLE;
             import_type->linked = false;
+            import_type->u.table_type =
+                (WASMTableType *)&aot_import_table->table_type;
             return;
         }
 
@@ -3946,6 +4060,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
                 import_type->linked = false; /* not supported */
+                import_type->u.table_type =
+                    (WASMTableType *)&wasm_import->u.table.table_type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
                 import_type->linked = false; /* not supported */
@@ -4030,6 +4146,11 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
                          .type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
+                export_type->u.table_type =
+                    &aot_module
+                         ->tables[aot_export->index
+                                  - aot_module->import_table_count]
+                         .table_type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
                 export_type->u.memory_type =
@@ -4071,6 +4192,11 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
                          .type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
+                export_type->u.table_type =
+                    &wasm_module
+                         ->tables[wasm_export->index
+                                  - wasm_module->import_table_count]
+                         .table_type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
                 export_type->u.memory_type =
@@ -4212,6 +4338,38 @@ wasm_memory_type_get_max_page_count(WASMMemoryType *const memory_type)
     return memory_type->max_page_count;
 }
 
+wasm_valkind_t
+wasm_table_type_get_elem_kind(WASMTableType *const table_type)
+{
+    bh_assert(table_type);
+
+    return val_type_to_val_kind(table_type->elem_type);
+}
+
+bool
+wasm_table_type_get_shared(WASMTableType *const table_type)
+{
+    bh_assert(table_type);
+
+    return (table_type->flags & 2) ? true : false;
+}
+
+uint32
+wasm_table_type_get_init_size(WASMTableType *const table_type)
+{
+    bh_assert(table_type);
+
+    return table_type->init_size;
+}
+
+uint32
+wasm_table_type_get_max_size(WASMTableType *const table_type)
+{
+    bh_assert(table_type);
+
+    return table_type->max_size;
+}
+
 bool
 wasm_runtime_register_natives(const char *module_name,
                               NativeSymbol *native_symbols,
@@ -6178,7 +6336,7 @@ aot_mark_all_externrefs(AOTModuleInstance *module_inst)
 
     for (i = 0; i < module->table_count; i++) {
         table_inst = module_inst->tables[i];
-        if ((table + i)->elem_type == VALUE_TYPE_EXTERNREF) {
+        if ((table + i)->table_type.elem_type == VALUE_TYPE_EXTERNREF) {
             while (j < table_inst->cur_size) {
                 mark_externref(table_inst->elems[j++]);
             }
@@ -6374,22 +6532,22 @@ wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
         if (table_idx < module->import_table_count) {
             WASMTableImport *import_table =
                 &((module->import_tables + table_idx)->u.table);
-            *out_elem_type = import_table->elem_type;
+            *out_elem_type = import_table->table_type.elem_type;
 #if WASM_ENABLE_GC != 0
-            *out_ref_type = import_table->elem_ref_type;
+            *out_ref_type = import_table->table_type.elem_ref_type;
 #endif
-            *out_min_size = import_table->init_size;
-            *out_max_size = import_table->max_size;
+            *out_min_size = import_table->table_type.init_size;
+            *out_max_size = import_table->table_type.max_size;
         }
         else {
             WASMTable *table =
                 module->tables + (table_idx - module->import_table_count);
-            *out_elem_type = table->elem_type;
+            *out_elem_type = table->table_type.elem_type;
 #if WASM_ENABLE_GC != 0
-            *out_ref_type = table->elem_ref_type;
+            *out_ref_type = table->table_type.elem_ref_type;
 #endif
-            *out_min_size = table->init_size;
-            *out_max_size = table->max_size;
+            *out_min_size = table->table_type.init_size;
+            *out_max_size = table->table_type.max_size;
         }
         return true;
     }
@@ -6401,22 +6559,22 @@ wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
 
         if (table_idx < module->import_table_count) {
             AOTImportTable *import_table = module->import_tables + table_idx;
-            *out_elem_type = import_table->elem_type;
+            *out_elem_type = import_table->table_type.elem_type;
 #if WASM_ENABLE_GC != 0
             *out_ref_type = NULL; /* TODO */
 #endif
-            *out_min_size = import_table->table_init_size;
-            *out_max_size = import_table->table_max_size;
+            *out_min_size = import_table->table_type.init_size;
+            *out_max_size = import_table->table_type.max_size;
         }
         else {
             AOTTable *table =
                 module->tables + (table_idx - module->import_table_count);
-            *out_elem_type = table->elem_type;
+            *out_elem_type = table->table_type.elem_type;
 #if WASM_ENABLE_GC != 0
             *out_ref_type = NULL; /* TODO */
 #endif
-            *out_min_size = table->table_init_size;
-            *out_max_size = table->table_max_size;
+            *out_min_size = table->table_type.init_size;
+            *out_max_size = table->table_type.max_size;
         }
         return true;
     }

+ 24 - 22
core/iwasm/compilation/aot.c

@@ -599,34 +599,36 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
         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].elem_type =
-                    module->import_tables[i].u.table.elem_type;
-                comp_data->tables[i].table_flags =
-                    module->import_tables[i].u.table.flags;
-                comp_data->tables[i].table_init_size =
-                    module->import_tables[i].u.table.init_size;
-                comp_data->tables[i].table_max_size =
-                    module->import_tables[i].u.table.max_size;
+                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].elem_ref_type =
-                    module->import_tables[i].u.table.elem_ref_type;
+                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].possible_grow =
-                    module->import_tables[i].u.table.possible_grow;
+                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].elem_type = module->tables[j].elem_type;
-                comp_data->tables[i].table_flags = module->tables[j].flags;
-                comp_data->tables[i].table_init_size =
-                    module->tables[j].init_size;
-                comp_data->tables[i].table_max_size =
-                    module->tables[j].max_size;
-                comp_data->tables[i].possible_grow =
-                    module->tables[j].possible_grow;
+                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].elem_ref_type =
-                    module->tables[j].elem_ref_type;
+                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.

+ 9 - 28
core/iwasm/compilation/aot.h

@@ -48,6 +48,8 @@ typedef WASMArrayType AOTArrayType;
 typedef WASMExport AOTExport;
 typedef WASMMemory AOTMemory;
 typedef WASMMemoryType AOTMemoryType;
+typedef WASMTableType AOTTableType;
+typedef WASMTable AOTTable;
 
 #if WASM_ENABLE_DEBUG_AOT != 0
 typedef void *dwarf_extractor_handle_t;
@@ -110,32 +112,9 @@ typedef struct AOTMemInitData {
 typedef struct AOTImportTable {
     char *module_name;
     char *table_name;
-    uint8 elem_type;
-    uint8 table_flags;
-    bool possible_grow;
-    uint32 table_init_size;
-    uint32 table_max_size;
-#if WASM_ENABLE_GC != 0
-    WASMRefType *elem_ref_type;
-#endif
+    AOTTableType table_type;
 } AOTImportTable;
 
-/**
- * Table
- */
-typedef struct AOTTable {
-    uint8 elem_type;
-    uint8 table_flags;
-    bool possible_grow;
-    uint32 table_init_size;
-    uint32 table_max_size;
-#if WASM_ENABLE_GC != 0
-    WASMRefType *elem_ref_type;
-    /* init expr for the whole table */
-    InitializerExpression init_expr;
-#endif
-} AOTTable;
-
 /**
  * A segment of table init data
  */
@@ -359,11 +338,12 @@ aot_get_imp_tbl_data_slots(const AOTImportTable *tbl, bool is_jit_mode)
 {
 #if WASM_ENABLE_MULTI_MODULE != 0
     if (is_jit_mode)
-        return tbl->table_max_size;
+        return tbl->table_type.max_size;
 #else
     (void)is_jit_mode;
 #endif
-    return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
+    return tbl->table_type.possible_grow ? tbl->table_type.max_size
+                                         : tbl->table_type.init_size;
 }
 
 static inline uint32
@@ -371,11 +351,12 @@ 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_max_size;
+        return tbl->table_type.max_size;
 #else
     (void)is_jit_mode;
 #endif
-    return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
+    return tbl->table_type.possible_grow ? tbl->table_type.max_size
+                                         : tbl->table_type.init_size;
 }
 
 #ifdef __cplusplus

+ 33 - 27
core/iwasm/compilation/aot_emit_aot_file.c

@@ -383,11 +383,11 @@ get_import_table_size(const AOTCompContext *comp_ctx,
      * | import_table_count
      * ------------------------------
      * |                   | U8 elem_type
-     * |                   | U8 table_flags
+     * |                   | U8 flags
      * |                   | U8 possible_grow
      * | AOTImportTable[N] | U8 elem_ref_type.nullable (for GC only)
-     * |                   | U32 table_init_size
-     * |                   | U32 table_max_size
+     * |                   | U32 init_size
+     * |                   | U32 max_size
      * |                   | U32 elem_ref_type.heap_type (for GC only)
      * ------------------------------
      */
@@ -397,7 +397,8 @@ get_import_table_size(const AOTCompContext *comp_ctx,
     for (i = 0; i < comp_data->import_table_count; i++) {
         size += sizeof(uint32) * 3;
 #if WASM_ENABLE_GC != 0
-        if (comp_ctx->enable_gc && comp_data->import_tables[i].elem_ref_type)
+        if (comp_ctx->enable_gc
+            && comp_data->import_tables[i].table_type.elem_ref_type)
             size += sizeof(uint32);
 #endif
     }
@@ -412,11 +413,11 @@ get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data)
      * | table_count
      * ------------------------------
      * |             | U8 elem_type
-     * |             | U8 table_flags
+     * |             | U8 flags
      * |             | U8 possible_grow
      * | AOTTable[N] | U8 elem_ref_type.nullable (for GC only)
-     * |             | U32 table_init_size
-     * |             | U32 table_max_size
+     * |             | U32 init_size
+     * |             | U32 max_size
      * |             | U32 elem_ref_type.heap_type (for GC only)
      * |             | N   init_expr (for GC only)
      * ------------------------------
@@ -428,7 +429,7 @@ get_table_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data)
         size += sizeof(uint32) * 3;
 #if WASM_ENABLE_GC != 0
         if (comp_ctx->enable_gc) {
-            if (comp_data->tables[i].elem_ref_type) {
+            if (comp_data->tables[i].table_type.elem_ref_type) {
                 size += sizeof(uint32);
             }
             size += get_init_expr_size(comp_ctx, comp_data,
@@ -1955,13 +1956,14 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
          * 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].elem_type);
-        EMIT_U8(comp_data->import_tables[i].table_flags);
-        EMIT_U8(comp_data->import_tables[i].possible_grow);
+        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);
 #if WASM_ENABLE_GC != 0
-        if (comp_ctx->enable_gc && comp_data->import_tables[i].elem_ref_type) {
+        if (comp_ctx->enable_gc
+            && comp_data->import_tables[i].table_type.elem_ref_type) {
             EMIT_U8(comp_data->import_tables[i]
-                        .elem_ref_type->ref_ht_common.nullable);
+                        .table_type.elem_ref_type->ref_ht_common.nullable);
         }
         else
 #endif
@@ -1969,14 +1971,15 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
             /* emit one placeholder to keep the same size */
             EMIT_U8(0);
         }
-        EMIT_U32(comp_data->import_tables[i].table_init_size);
-        EMIT_U32(comp_data->import_tables[i].table_max_size);
+        EMIT_U32(comp_data->import_tables[i].table_type.init_size);
+        EMIT_U32(comp_data->import_tables[i].table_type.max_size);
 #if WASM_ENABLE_GC != 0
-        if (comp_ctx->enable_gc && comp_data->import_tables[i].elem_ref_type) {
+        if (comp_ctx->enable_gc
+            && comp_data->import_tables[i].table_type.elem_ref_type) {
             bh_assert(wasm_is_type_multi_byte_type(
                 comp_data->import_tables[i].elem_type));
             EMIT_U32(comp_data->import_tables[i]
-                         .elem_ref_type->ref_ht_common.heap_type);
+                         .table_type.elem_ref_type->ref_ht_common.heap_type);
         }
 #endif
     }
@@ -1985,12 +1988,14 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     EMIT_U32(comp_data->table_count);
     /* Emit table items */
     for (i = 0; i < comp_data->table_count; i++) {
-        EMIT_U8(comp_data->tables[i].elem_type);
-        EMIT_U8(comp_data->tables[i].table_flags);
-        EMIT_U8(comp_data->tables[i].possible_grow);
+        EMIT_U8(comp_data->tables[i].table_type.elem_type);
+        EMIT_U8(comp_data->tables[i].table_type.flags);
+        EMIT_U8(comp_data->tables[i].table_type.possible_grow);
 #if WASM_ENABLE_GC != 0
-        if (comp_ctx->enable_gc && comp_data->tables[i].elem_ref_type) {
-            EMIT_U8(comp_data->tables[i].elem_ref_type->ref_ht_common.nullable);
+        if (comp_ctx->enable_gc
+            && comp_data->tables[i].table_type.elem_ref_type) {
+            EMIT_U8(comp_data->tables[i]
+                        .table_type.elem_ref_type->ref_ht_common.nullable);
         }
         else
 #endif
@@ -1998,15 +2003,16 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
             /* emit one placeholder to keep the same size */
             EMIT_U8(0);
         }
-        EMIT_U32(comp_data->tables[i].table_init_size);
-        EMIT_U32(comp_data->tables[i].table_max_size);
+        EMIT_U32(comp_data->tables[i].table_type.init_size);
+        EMIT_U32(comp_data->tables[i].table_type.max_size);
 #if WASM_ENABLE_GC != 0
         if (comp_ctx->enable_gc) {
-            if (comp_data->tables[i].elem_ref_type) {
+            if (comp_data->tables[i].table_type.elem_ref_type) {
                 bh_assert(wasm_is_type_multi_byte_type(
                     comp_data->tables[i].elem_type));
-                EMIT_U32(comp_data->tables[i]
-                             .elem_ref_type->ref_ht_common.heap_type);
+                EMIT_U32(
+                    comp_data->tables[i]
+                        .table_type.elem_ref_type->ref_ht_common.heap_type);
             }
             if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
                                     &comp_data->tables[i].init_expr)) {

+ 10 - 6
core/iwasm/fast-jit/jit_frontend.c

@@ -76,11 +76,12 @@ jit_frontend_get_table_inst_offset(const WASMModule *module, uint32 tbl_idx)
 
         offset += (uint32)offsetof(WASMTableInstance, elems);
 #if WASM_ENABLE_MULTI_MODULE != 0
-        offset += (uint32)sizeof(uint32) * import_table->max_size;
+        offset += (uint32)sizeof(uint32) * import_table->table_type.max_size;
 #else
         offset += (uint32)sizeof(uint32)
-                  * (import_table->possible_grow ? import_table->max_size
-                                                 : import_table->init_size);
+                  * (import_table->table_type.possible_grow
+                         ? import_table->table_type.max_size
+                         : import_table->table_type.init_size);
 #endif
 
         i++;
@@ -97,10 +98,13 @@ jit_frontend_get_table_inst_offset(const WASMModule *module, uint32 tbl_idx)
 
         offset += (uint32)offsetof(WASMTableInstance, elems);
 #if WASM_ENABLE_MULTI_MODULE != 0
-        offset += (uint32)sizeof(table_elem_type_t) * table->max_size;
+        offset +=
+            (uint32)sizeof(table_elem_type_t) * table->table_type.max_size;
 #else
-        offset += (uint32)sizeof(table_elem_type_t)
-                  * (table->possible_grow ? table->max_size : table->init_size);
+        offset +=
+            (uint32)sizeof(table_elem_type_t)
+            * (table->table_type.possible_grow ? table->table_type.max_size
+                                               : table->table_type.init_size);
 #endif
 
         i++;

+ 82 - 0
core/iwasm/include/wasm_export.h

@@ -75,6 +75,9 @@ typedef enum {
 struct WASMFuncType;
 typedef struct WASMFuncType *wasm_func_type_t;
 
+struct WASMTableType;
+typedef struct WASMTableType *wasm_table_type_t;
+
 struct WASMGlobalType;
 typedef struct WASMGlobalType *wasm_global_type_t;
 
@@ -89,6 +92,7 @@ typedef struct wasm_import_t {
     bool linked;
     union {
         wasm_func_type_t func_type;
+        wasm_table_type_t table_type;
         wasm_global_type_t global_type;
         wasm_memory_type_t memory_type;
     } u;
@@ -99,6 +103,7 @@ typedef struct wasm_export_t {
     wasm_import_export_kind_t kind;
     union {
         wasm_func_type_t func_type;
+        wasm_table_type_t table_type;
         wasm_global_type_t global_type;
         wasm_memory_type_t memory_type;
     } u;
@@ -295,6 +300,15 @@ typedef struct wasm_global_inst_t {
     void *global_data;
 } wasm_global_inst_t;
 
+/* Table instance*/
+typedef struct wasm_table_inst_t {
+    wasm_valkind_t elem_kind;
+    uint32_t cur_size;
+    uint32_t max_size;
+    /* represents the elements of the table, for internal use only */
+    void *elems;
+} wasm_table_inst_t;
+
 typedef enum {
     WASM_LOG_LEVEL_FATAL = 0,
     WASM_LOG_LEVEL_ERROR = 1,
@@ -1386,6 +1400,46 @@ wasm_memory_type_get_init_page_count(const wasm_memory_type_t memory_type);
 WASM_RUNTIME_API_EXTERN uint32_t
 wasm_memory_type_get_max_page_count(const wasm_memory_type_t memory_type);
 
+/**
+ * Get the element kind for a table type
+ *
+ * @param table_type the table type
+ *
+ * @return the element kind
+ */
+WASM_RUNTIME_API_EXTERN wasm_valkind_t
+wasm_table_type_get_elem_kind(const wasm_table_type_t table_type);
+
+/**
+ * Get the sharing setting for a table type
+ *
+ * @param table_type the table type
+ *
+ * @return true if shared, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_table_type_get_shared(const wasm_table_type_t table_type);
+
+/**
+ * Get the initial size for a table type
+ *
+ * @param table_type the table type
+ *
+ * @return the initial table size
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_table_type_get_init_size(const wasm_table_type_t table_type);
+
+/**
+ * Get the maximum size for a table type
+ *
+ * @param table_type the table type
+ *
+ * @return the maximum table size
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_table_type_get_max_size(const wasm_table_type_t table_type);
+
 /**
  * Register native functions with same module name
  *
@@ -1472,6 +1526,34 @@ wasm_runtime_get_export_global_inst(const wasm_module_inst_t module_inst,
                                     const char *name,
                                     wasm_global_inst_t *global_inst);
 
+/**
+ * Get an export table instance
+ *
+ * @param module_inst the module instance
+ * @param name the export table name
+ * @param table_inst location to store the table instance
+ *
+ * @return true if success, false otherwise
+ *
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_get_export_table_inst(const wasm_module_inst_t module_inst,
+                                   const char *name,
+                                   wasm_table_inst_t *table_inst);
+
+/**
+ * Get a function instance from a table.
+ *
+ * @param module_inst the module instance
+ * @param table_inst the table instance
+ * @param idx the index in the table
+ *
+ * @return the function instance if successful, NULL otherwise
+ */
+WASM_RUNTIME_API_EXTERN wasm_function_inst_t
+wasm_table_get_func_inst(const wasm_module_inst_t module_inst,
+                         const wasm_table_inst_t *table_inst, uint32_t idx);
+
 /**
  * Get attachment of native function from execution environment
  *

+ 9 - 12
core/iwasm/interpreter/wasm.h

@@ -480,11 +480,11 @@ typedef void *WASMString;
 #endif /* end of WASM_ENABLE_STRINGREF != 0 */
 #endif /* end of WASM_ENABLE_GC != 0 */
 
-typedef struct WASMTable {
+typedef struct WASMTableType {
     uint8 elem_type;
     /**
      * 0: no max size and not shared
-     * 1: hax max size
+     * 1: has max size
      * 2: shared
      */
     uint8 flags;
@@ -494,6 +494,12 @@ typedef struct WASMTable {
     uint32 max_size;
 #if WASM_ENABLE_GC != 0
     WASMRefType *elem_ref_type;
+#endif
+} WASMTableType;
+
+typedef struct WASMTable {
+    WASMTableType table_type;
+#if WASM_ENABLE_GC != 0
     /* init expr for the whole table */
     InitializerExpression init_expr;
 #endif
@@ -517,16 +523,7 @@ typedef struct WASMMemory {
 typedef struct WASMTableImport {
     char *module_name;
     char *field_name;
-    /* 0: no max size, 1: has max size */
-    uint8 elem_type;
-    uint8 flags;
-    bool possible_grow;
-    uint32 init_size;
-    /* specified if (flags & 1), else it is 0x10000 */
-    uint32 max_size;
-#if WASM_ENABLE_GC != 0
-    WASMRefType *elem_ref_type;
-#endif
+    WASMTableType table_type;
 #if WASM_ENABLE_MULTI_MODULE != 0
     WASMModule *import_module;
     WASMTable *import_table_linked;

+ 51 - 42
core/iwasm/interpreter/wasm_loader.c

@@ -2364,10 +2364,11 @@ wasm_loader_resolve_table(const char *module_name, const char *table_name,
     else {
         table = &(module->tables[export->index - module->import_table_count]);
     }
-    if (table->init_size < init_size || table->max_size > max_size) {
+    if (table->table_type.init_size < init_size
+        || table->table_type.max_size > max_size) {
         LOG_DEBUG("%s,%s failed type check(%d-%d), expected(%d-%d)",
-                  module_name, table_name, table->init_size, table->max_size,
-                  init_size, max_size);
+                  module_name, table_name, table->table_type.init_size,
+                  table->table_type.max_size, init_size, max_size);
         set_error_buf(error_buf, error_buf_size, "incompatible import type");
         return NULL;
     }
@@ -2652,7 +2653,7 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
     }
     declare_elem_type = ref_type.ref_type;
     if (need_ref_type_map) {
-        if (!(table->elem_ref_type =
+        if (!(table->table_type.elem_ref_type =
                   reftype_set_insert(parent_module->ref_type_set, &ref_type,
                                      error_buf, error_buf_size))) {
             return false;
@@ -2660,7 +2661,7 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
     }
 #if TRACE_WASM_LOADER != 0
     os_printf("import table type: ");
-    wasm_dump_value_type(declare_elem_type, table->elem_ref_type);
+    wasm_dump_value_type(declare_elem_type, table->table_type.elem_ref_type);
     os_printf("\n");
 #endif
 #endif /* end of WASM_ENABLE_GC == 0 */
@@ -2702,10 +2703,10 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
         }
 
         /* reset with linked table limit */
-        declare_elem_type = linked_table->elem_type;
-        declare_init_size = linked_table->init_size;
-        declare_max_size = linked_table->max_size;
-        declare_max_size_flag = linked_table->flags;
+        declare_elem_type = linked_table->table_type.elem_type;
+        declare_init_size = linked_table->table_type.init_size;
+        declare_max_size = linked_table->table_type.max_size;
+        declare_max_size_flag = linked_table->table_type.flags;
         table->import_table_linked = linked_table;
         table->import_module = sub_module;
     }
@@ -2735,13 +2736,13 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
     }
 
     /* now we believe all declaration are ok */
-    table->elem_type = declare_elem_type;
-    table->init_size = declare_init_size;
-    table->flags = declare_max_size_flag;
-    table->max_size = declare_max_size;
+    table->table_type.elem_type = declare_elem_type;
+    table->table_type.init_size = declare_init_size;
+    table->table_type.flags = declare_max_size_flag;
+    table->table_type.max_size = declare_max_size;
 
 #if WASM_ENABLE_WAMR_COMPILER != 0
-    if (table->elem_type == VALUE_TYPE_EXTERNREF)
+    if (table->table_type.elem_type == VALUE_TYPE_EXTERNREF)
         parent_module->is_ref_types_used = true;
 #endif
     (void)parent_module;
@@ -3141,10 +3142,10 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
 #if WASM_ENABLE_GC == 0
     CHECK_BUF(p, p_end, 1);
     /* 0x70 or 0x6F */
-    table->elem_type = read_uint8(p);
-    if (VALUE_TYPE_FUNCREF != table->elem_type
+    table->table_type.elem_type = read_uint8(p);
+    if (VALUE_TYPE_FUNCREF != table->table_type.elem_type
 #if WASM_ENABLE_REF_TYPES != 0
-        && VALUE_TYPE_EXTERNREF != table->elem_type
+        && VALUE_TYPE_EXTERNREF != table->table_type.elem_type
 #endif
     ) {
         set_error_buf(error_buf, error_buf_size, "incompatible import type");
@@ -3156,9 +3157,9 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
                             error_buf_size)) {
         return false;
     }
-    table->elem_type = ref_type.ref_type;
+    table->table_type.elem_type = ref_type.ref_type;
     if (need_ref_type_map) {
-        if (!(table->elem_ref_type =
+        if (!(table->table_type.elem_ref_type =
                   reftype_set_insert(module->ref_type_set, &ref_type, error_buf,
                                      error_buf_size))) {
             return false;
@@ -3166,20 +3167,21 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
     }
 #if TRACE_WASM_LOADER != 0
     os_printf("table type: ");
-    wasm_dump_value_type(table->elem_type, table->elem_ref_type);
+    wasm_dump_value_type(table->table_type.elem_type,
+                         table->table_type.elem_ref_type);
     os_printf("\n");
 #endif
 #endif /* end of WASM_ENABLE_GC == 0 */
 
     p_org = p;
-    read_leb_uint32(p, p_end, table->flags);
+    read_leb_uint32(p, p_end, table->table_type.flags);
 #if WASM_ENABLE_SHARED_MEMORY == 0
     if (p - p_org > 1) {
         set_error_buf(error_buf, error_buf_size,
                       "integer representation too long");
         return false;
     }
-    if (table->flags > 1) {
+    if (table->table_type.flags > 1) {
         set_error_buf(error_buf, error_buf_size, "integer too large");
         return false;
     }
@@ -3188,29 +3190,31 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
         set_error_buf(error_buf, error_buf_size, "invalid limits flags");
         return false;
     }
-    if (table->flags == 2) {
+    if (table->table_type.flags == 2) {
         set_error_buf(error_buf, error_buf_size, "tables cannot be shared");
         return false;
     }
-    if (table->flags > 1) {
+    if (table->table_type.flags > 1) {
         set_error_buf(error_buf, error_buf_size, "invalid limits flags");
         return false;
     }
 #endif
 
-    read_leb_uint32(p, p_end, table->init_size);
+    read_leb_uint32(p, p_end, table->table_type.init_size);
 
-    if (table->flags) {
-        read_leb_uint32(p, p_end, table->max_size);
-        if (!check_table_max_size(table->init_size, table->max_size, error_buf,
+    if (table->table_type.flags) {
+        read_leb_uint32(p, p_end, table->table_type.max_size);
+        if (!check_table_max_size(table->table_type.init_size,
+                                  table->table_type.max_size, error_buf,
                                   error_buf_size))
             return false;
     }
 
-    adjust_table_max_size(table->init_size, table->flags, &table->max_size);
+    adjust_table_max_size(table->table_type.init_size, table->table_type.flags,
+                          &table->table_type.max_size);
 
 #if WASM_ENABLE_WAMR_COMPILER != 0
-    if (table->elem_type == VALUE_TYPE_EXTERNREF)
+    if (table->table_type.elem_type == VALUE_TYPE_EXTERNREF)
         module->is_ref_types_used = true;
 #endif
 
@@ -3915,8 +3919,9 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 #if WASM_ENABLE_GC != 0
             if (has_init) {
                 if (!load_init_expr(module, &p, p_end, &table->init_expr,
-                                    table->elem_type, table->elem_ref_type,
-                                    error_buf, error_buf_size))
+                                    table->table_type.elem_type,
+                                    table->table_type.elem_ref_type, error_buf,
+                                    error_buf_size))
                     return false;
                 if (table->init_expr.init_expr_type >= INIT_EXPR_TYPE_STRUCT_NEW
                     && table->init_expr.init_expr_type
@@ -3928,7 +3933,8 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                 }
             }
             else {
-                if (wasm_is_reftype_htref_non_nullable(table->elem_type)) {
+                if (wasm_is_reftype_htref_non_nullable(
+                        table->table_type.elem_type)) {
                     set_error_buf(
                         error_buf, error_buf_size,
                         "type mismatch: non-nullable table without init expr");
@@ -3938,7 +3944,7 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 #endif /* end of WASM_ENABLE_GC != 0 */
 
 #if WASM_ENABLE_WAMR_COMPILER != 0
-            if (table->elem_type == VALUE_TYPE_EXTERNREF)
+            if (table->table_type.elem_type == VALUE_TYPE_EXTERNREF)
                 module->is_ref_types_used = true;
 #endif
         }
@@ -4311,9 +4317,10 @@ check_table_elem_type(WASMModule *module, uint32 table_index,
 
     if (table_index < module->import_table_count)
         table_declared_elem_type =
-            module->import_tables[table_index].u.table.elem_type;
+            module->import_tables[table_index].u.table.table_type.elem_type;
     else
-        table_declared_elem_type = (module->tables + table_index)->elem_type;
+        table_declared_elem_type =
+            (module->tables + table_index)->table_type.elem_type;
 
     if (table_declared_elem_type == type_from_elem_seg)
         return true;
@@ -10804,23 +10811,25 @@ get_table_elem_type(const WASMModule *module, uint32 table_idx,
 
     if (table_idx < module->import_table_count) {
         if (p_elem_type)
-            *p_elem_type = module->import_tables[table_idx].u.table.elem_type;
+            *p_elem_type =
+                module->import_tables[table_idx].u.table.table_type.elem_type;
 #if WASM_ENABLE_GC != 0
         if (p_ref_type)
             *((WASMRefType **)p_ref_type) =
-                module->import_tables[table_idx].u.table.elem_ref_type;
+                module->import_tables[table_idx]
+                    .u.table.table_type.elem_ref_type;
 #endif
     }
     else {
         if (p_elem_type)
             *p_elem_type =
                 module->tables[module->import_table_count + table_idx]
-                    .elem_type;
+                    .table_type.elem_type;
 #if WASM_ENABLE_GC != 0
         if (p_ref_type)
             *((WASMRefType **)p_ref_type) =
                 module->tables[module->import_table_count + table_idx]
-                    .elem_ref_type;
+                    .table_type.elem_ref_type;
 #endif
     }
     return true;
@@ -14878,13 +14887,13 @@ re_scan:
                         if (opcode1 == WASM_OP_TABLE_GROW) {
                             if (table_idx < module->import_table_count) {
                                 module->import_tables[table_idx]
-                                    .u.table.possible_grow = true;
+                                    .u.table.table_type.possible_grow = true;
                             }
                             else {
                                 module
                                     ->tables[table_idx
                                              - module->import_table_count]
-                                    .possible_grow = true;
+                                    .table_type.possible_grow = true;
                             }
                         }
 

+ 20 - 18
core/iwasm/interpreter/wasm_mini_loader.c

@@ -695,10 +695,10 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
         !((declare_max_size_flag & 1) && declare_init_size > declare_max_size));
 
     /* now we believe all declaration are ok */
-    table->elem_type = declare_elem_type;
-    table->init_size = declare_init_size;
-    table->flags = declare_max_size_flag;
-    table->max_size = declare_max_size;
+    table->table_type.elem_type = declare_elem_type;
+    table->table_type.init_size = declare_init_size;
+    table->table_type.flags = declare_max_size_flag;
+    table->table_type.max_size = declare_max_size;
     return true;
 }
 
@@ -805,26 +805,27 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMTable *table,
 
     CHECK_BUF(p, p_end, 1);
     /* 0x70 or 0x6F */
-    table->elem_type = read_uint8(p);
-    bh_assert((VALUE_TYPE_FUNCREF == table->elem_type)
+    table->table_type.elem_type = read_uint8(p);
+    bh_assert((VALUE_TYPE_FUNCREF == table->table_type.elem_type)
 #if WASM_ENABLE_REF_TYPES != 0
-              || VALUE_TYPE_EXTERNREF == table->elem_type
+              || VALUE_TYPE_EXTERNREF == table->table_type.elem_type
 #endif
     );
 
     p_org = p;
-    read_leb_uint32(p, p_end, table->flags);
+    read_leb_uint32(p, p_end, table->table_type.flags);
     bh_assert(p - p_org <= 1);
-    bh_assert(table->flags <= 1);
+    bh_assert(table->table_type.flags <= 1);
     (void)p_org;
 
-    read_leb_uint32(p, p_end, table->init_size);
-    if (table->flags == 1) {
-        read_leb_uint32(p, p_end, table->max_size);
-        bh_assert(table->init_size <= table->max_size);
+    read_leb_uint32(p, p_end, table->table_type.init_size);
+    if (table->table_type.flags == 1) {
+        read_leb_uint32(p, p_end, table->table_type.max_size);
+        bh_assert(table->table_type.init_size <= table->table_type.max_size);
     }
 
-    adjust_table_max_size(table->init_size, table->flags, &table->max_size);
+    adjust_table_max_size(table->table_type.init_size, table->table_type.flags,
+                          &table->table_type.max_size);
 
     *p_buf = p;
     return true;
@@ -2515,11 +2516,12 @@ get_table_elem_type(const WASMModule *module, uint32 table_idx,
 
     if (p_elem_type) {
         if (table_idx < module->import_table_count)
-            *p_elem_type = module->import_tables[table_idx].u.table.elem_type;
+            *p_elem_type =
+                module->import_tables[table_idx].u.table.table_type.elem_type;
         else
             *p_elem_type =
                 module->tables[module->import_table_count + table_idx]
-                    .elem_type;
+                    .table_type.elem_type;
     }
     return true;
 }
@@ -7917,13 +7919,13 @@ re_scan:
                         if (opcode1 == WASM_OP_TABLE_GROW) {
                             if (table_idx < module->import_table_count) {
                                 module->import_tables[table_idx]
-                                    .u.table.possible_grow = true;
+                                    .u.table.table_type.possible_grow = true;
                             }
                             else {
                                 module
                                     ->tables[table_idx
                                              - module->import_table_count]
-                                    .possible_grow = true;
+                                    .table_type.possible_grow = true;
                             }
                         }
 

+ 25 - 20
core/iwasm/interpreter/wasm_runtime.c

@@ -533,9 +533,9 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
 #endif
         {
             /* in order to save memory, alloc resource as few as possible */
-            max_size_fixed = import->u.table.possible_grow
-                                 ? import->u.table.max_size
-                                 : import->u.table.init_size;
+            max_size_fixed = import->u.table.table_type.possible_grow
+                                 ? import->u.table.table_type.max_size
+                                 : import->u.table.table_type.init_size;
 
             /* it is a built-in table, every module has its own */
             total_size = offsetof(WASMTableInstance, elems);
@@ -556,8 +556,8 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
 #if WASM_ENABLE_MULTI_MODULE != 0
         *table_linked = table_inst_linked;
         if (table_inst_linked != NULL) {
-#if WASM_ENABLE_GC != 0
             table->elem_type = table_inst_linked->elem_type;
+#if WASM_ENABLE_GC != 0
             table->elem_ref_type = table_inst_linked->elem_ref_type;
 #endif
             table->cur_size = table_inst_linked->cur_size;
@@ -566,11 +566,12 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
         else
 #endif
         {
+            table->elem_type = import->u.table.table_type.elem_type;
 #if WASM_ENABLE_GC != 0
-            table->elem_type = import->u.table.elem_type;
-            table->elem_ref_type.elem_ref_type = import->u.table.elem_ref_type;
+            table->elem_ref_type.elem_ref_type =
+                import->u.table.table_type.elem_ref_type;
 #endif
-            table->cur_size = import->u.table.init_size;
+            table->cur_size = import->u.table.table_type.init_size;
             table->max_size = max_size_fixed;
         }
 
@@ -587,11 +588,11 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
         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].max_size;
+        max_size_fixed = module->tables[i].table_type.max_size;
 #else
-        max_size_fixed = module->tables[i].possible_grow
-                             ? module->tables[i].max_size
-                             : module->tables[i].init_size;
+        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 */
@@ -610,11 +611,12 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
         /* For GC, all elements have already been set to NULL_REF (0) as
            uninitialized elements */
 #endif
+        table->elem_type = module->tables[i].table_type.elem_type;
 #if WASM_ENABLE_GC != 0
-        table->elem_type = module->tables[i].elem_type;
-        table->elem_ref_type.elem_ref_type = module->tables[i].elem_ref_type;
+        table->elem_ref_type.elem_ref_type =
+            module->tables[i].table_type.elem_ref_type;
 #endif
-        table->cur_size = module->tables[i].init_size;
+        table->cur_size = module->tables[i].table_type.init_size;
         table->max_size = max_size_fixed;
 
         table = (WASMTableInstance *)((uint8 *)table + (uint32)total_size);
@@ -2164,23 +2166,26 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
         WASMTableImport *import_table = &module->import_tables[i].u.table;
         table_size += offsetof(WASMTableInstance, elems);
 #if WASM_ENABLE_MULTI_MODULE != 0
-        table_size +=
-            (uint64)sizeof(table_elem_type_t) * import_table->max_size;
+        table_size += (uint64)sizeof(table_elem_type_t)
+                      * import_table->table_type.max_size;
 #else
         table_size += (uint64)sizeof(table_elem_type_t)
-                      * (import_table->possible_grow ? import_table->max_size
-                                                     : import_table->init_size);
+                      * (import_table->table_type.possible_grow
+                             ? import_table->table_type.max_size
+                             : import_table->table_type.init_size);
 #endif
     }
     for (i = 0; i < module->table_count; i++) {
         WASMTable *table = module->tables + i;
         table_size += offsetof(WASMTableInstance, elems);
 #if WASM_ENABLE_MULTI_MODULE != 0
-        table_size += (uint64)sizeof(table_elem_type_t) * table->max_size;
+        table_size +=
+            (uint64)sizeof(table_elem_type_t) * table->table_type.max_size;
 #else
         table_size +=
             (uint64)sizeof(table_elem_type_t)
-            * (table->possible_grow ? table->max_size : table->init_size);
+            * (table->table_type.possible_grow ? table->table_type.max_size
+                                               : table->table_type.init_size);
 #endif
     }
     total_size += table_size;

+ 4 - 4
test-tools/aot-analyzer/src/main.cc

@@ -291,8 +291,8 @@ DumpDetails(AoTFile *aot)
 #endif
         printf("    init_size:%5u    max_size:%5u    "
                "module_name: %s    table_name: %s\n",
-               table.table_init_size, table.table_max_size, table.module_name,
-               table.table_name);
+               table.table_type.init_size, table.table_type.max_size,
+               table.module_name, table.table_type.name);
     }
     printf("\n");
 
@@ -352,8 +352,8 @@ DumpDetails(AoTFile *aot)
 #else
         dump_value_type(table.elem_type);
 #endif
-        printf("    init_size:%5u    max_size:%5u\n", table.table_init_size,
-               table.table_max_size);
+        printf("    init_size:%5u    max_size:%5u\n",
+               table.table_type.init_size, table.table_type.max_size);
     }
     printf("\n\n");