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.
This commit is contained in:
Benbuck Nason
2024-06-18 23:50:46 -07:00
committed by GitHub
parent 72f74b7b51
commit 3746534010
15 changed files with 590 additions and 245 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;