Support table64 extension in classic-interp and AOT running modes (#3811)

Add table64 extension(in Memory64 proposal) support in classic-interp
and AOT running modes, currently still use uint32 to represent table's
initial and maximum size to keep AOT ABI unchanged.
This commit is contained in:
TianlongLiang
2024-10-11 21:14:56 +08:00
committed by GitHub
parent 2b5e2d9c2c
commit 36d438051e
16 changed files with 922 additions and 175 deletions

View File

@ -511,9 +511,9 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
#endif
#if WASM_ENABLE_MEMORY64 != 0
#define PUSH_MEM_OFFSET(value) \
#define COND_PUSH_TEMPLATE(cond, value) \
do { \
if (is_memory64) { \
if (cond) { \
PUT_I64_TO_ADDR(frame_sp, value); \
frame_sp += 2; \
} \
@ -521,8 +521,11 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
*(int32 *)frame_sp++ = (int32)(value); \
} \
} while (0)
#define PUSH_MEM_OFFSET(value) COND_PUSH_TEMPLATE(is_memory64, value)
#define PUSH_TBL_ELEM_IDX(value) COND_PUSH_TEMPLATE(is_table64, value)
#else
#define PUSH_MEM_OFFSET(value) PUSH_I32(value)
#define PUSH_TBL_ELEM_IDX(value) PUSH_I32(value)
#endif
#define PUSH_PAGE_COUNT(value) PUSH_MEM_OFFSET(value)
@ -558,8 +561,10 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
#if WASM_ENABLE_MEMORY64 != 0
#define POP_MEM_OFFSET() (is_memory64 ? POP_I64() : POP_I32())
#define POP_TBL_ELEM_IDX() (is_table64 ? POP_I64() : POP_I32())
#else
#define POP_MEM_OFFSET() POP_I32()
#define POP_TBL_ELEM_IDX() POP_I32()
#endif
#define POP_PAGE_COUNT() POP_MEM_OFFSET()
@ -1562,7 +1567,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint8 opcode;
uint32 i, depth, cond, count, fidx, tidx, lidx, frame_size = 0;
uint32 all_cell_num = 0;
int32 val;
tbl_elem_idx_t val;
uint8 *else_addr, *end_addr, *maddr = NULL;
uint32 local_idx, local_offset, global_idx;
uint8 local_type, *global_addr;
@ -1602,6 +1607,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* TODO: multi-memories for now assuming the memory idx type is consistent
* across multi-memories */
bool is_memory64 = false;
bool is_table64 = false;
if (memory)
is_memory64 = memory->is_memory64;
#endif
@ -2315,7 +2321,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/**
* type check. compiler will make sure all like
* (call_indirect (type $x) (i32.const 1))
* (call_indirect (type $x) (it.const 1))
* the function type has to be defined in the module also
* no matter it is used or not
*/
@ -2334,9 +2340,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* clang-format on */
tbl_inst = wasm_get_table_inst(module, tbl_idx);
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = tbl_inst->is_table64;
#endif
val = POP_I32();
if ((uint32)val >= tbl_inst->cur_size) {
val = POP_TBL_ELEM_IDX();
if (val >= tbl_inst->cur_size) {
wasm_set_exception(module, "undefined element");
goto got_exception;
}
@ -2482,15 +2491,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_TABLE_GET)
{
uint32 tbl_idx, elem_idx;
uint32 tbl_idx;
tbl_elem_idx_t elem_idx;
WASMTableInstance *tbl_inst;
read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
bh_assert(tbl_idx < module->table_count);
tbl_inst = wasm_get_table_inst(module, tbl_idx);
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = tbl_inst->is_table64;
#endif
elem_idx = POP_I32();
elem_idx = POP_TBL_ELEM_IDX();
if (elem_idx >= tbl_inst->cur_size) {
wasm_set_exception(module, "out of bounds table access");
goto got_exception;
@ -2507,20 +2520,24 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_TABLE_SET)
{
WASMTableInstance *tbl_inst;
uint32 tbl_idx, elem_idx;
uint32 tbl_idx;
tbl_elem_idx_t elem_idx;
table_elem_type_t elem_val;
read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
bh_assert(tbl_idx < module->table_count);
tbl_inst = wasm_get_table_inst(module, tbl_idx);
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = tbl_inst->is_table64;
#endif
#if WASM_ENABLE_GC == 0
elem_val = POP_I32();
#else
elem_val = POP_REF();
#endif
elem_idx = POP_I32();
elem_idx = POP_TBL_ELEM_IDX();
if (elem_idx >= tbl_inst->cur_size) {
wasm_set_exception(module, "out of bounds table access");
goto got_exception;
@ -4616,13 +4633,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_MEMORY_GROW)
{
uint32 mem_idx, delta, prev_page_count;
uint32 mem_idx, prev_page_count;
mem_offset_t delta;
read_leb_memidx(frame_ip, frame_ip_end, mem_idx);
prev_page_count = memory->cur_page_count;
delta = (uint32)POP_PAGE_COUNT();
delta = POP_PAGE_COUNT();
if (!wasm_enlarge_memory_with_idx(module, delta, mem_idx)) {
if (
#if WASM_ENABLE_MEMORY64 != 0
delta > UINT32_MAX ||
#endif
!wasm_enlarge_memory_with_idx(module, (uint32)delta,
mem_idx)) {
/* failed to memory.grow, return -1 */
PUSH_PAGE_COUNT(-1);
}
@ -5778,8 +5801,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
case WASM_OP_TABLE_INIT:
{
uint32 tbl_idx, elem_idx;
uint32 n, s, d;
uint32 tbl_idx;
tbl_elem_idx_t elem_idx, d;
uint32 n, s;
WASMTableInstance *tbl_inst;
table_elem_type_t *table_elems;
InitializerExpression *tbl_seg_init_values = NULL,
@ -5793,10 +5817,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
bh_assert(tbl_idx < module->module->table_count);
tbl_inst = wasm_get_table_inst(module, tbl_idx);
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = tbl_inst->is_table64;
#endif
n = (uint32)POP_I32();
s = (uint32)POP_I32();
d = (uint32)POP_I32();
d = (tbl_elem_idx_t)POP_TBL_ELEM_IDX();
if (!bh_bitmap_get_bit(module->e->common.elem_dropped,
elem_idx)) {
@ -5809,8 +5836,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
.value_count;
}
if (offset_len_out_of_bounds(s, n, tbl_seg_len)
|| offset_len_out_of_bounds(d, n,
/* TODO: memory64 current implementation of table64
* still assumes the max table size UINT32_MAX
*/
if (
#if WASM_ENABLE_MEMORY64 != 0
d > UINT32_MAX ||
#endif
offset_len_out_of_bounds(s, n, tbl_seg_len)
|| offset_len_out_of_bounds((uint32)d, n,
tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
@ -5864,7 +5898,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
case WASM_OP_TABLE_COPY:
{
uint32 src_tbl_idx, dst_tbl_idx;
uint32 n, s, d;
tbl_elem_idx_t n, s, d;
WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx);
@ -5877,14 +5911,29 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx);
n = (uint32)POP_I32();
s = (uint32)POP_I32();
d = (uint32)POP_I32();
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = src_tbl_inst->is_table64
&& dst_tbl_inst->is_table64;
#endif
n = (tbl_elem_idx_t)POP_TBL_ELEM_IDX();
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = src_tbl_inst->is_table64;
#endif
s = (tbl_elem_idx_t)POP_TBL_ELEM_IDX();
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = dst_tbl_inst->is_table64;
#endif
d = (tbl_elem_idx_t)POP_TBL_ELEM_IDX();
if (offset_len_out_of_bounds(d, n,
if (
#if WASM_ENABLE_MEMORY64 != 0
n > UINT32_MAX || s > UINT32_MAX || d > UINT32_MAX
||
#endif
offset_len_out_of_bounds((uint32)d, (uint32)n,
dst_tbl_inst->cur_size)
|| offset_len_out_of_bounds(
s, n, src_tbl_inst->cur_size)) {
(uint32)s, (uint32)n, src_tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
@ -5907,28 +5956,37 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
case WASM_OP_TABLE_GROW:
{
WASMTableInstance *tbl_inst;
uint32 tbl_idx, n, orig_tbl_sz;
uint32 tbl_idx, orig_tbl_sz;
tbl_elem_idx_t n;
table_elem_type_t init_val;
read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
bh_assert(tbl_idx < module->table_count);
tbl_inst = wasm_get_table_inst(module, tbl_idx);
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = tbl_inst->is_table64;
#endif
orig_tbl_sz = tbl_inst->cur_size;
n = POP_I32();
n = POP_TBL_ELEM_IDX();
#if WASM_ENABLE_GC == 0
init_val = POP_I32();
#else
init_val = POP_REF();
#endif
if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) {
PUSH_I32(-1);
if (
#if WASM_ENABLE_MEMORY64 != 0
n > UINT32_MAX ||
#endif
!wasm_enlarge_table(module, tbl_idx, (uint32)n,
init_val)) {
PUSH_TBL_ELEM_IDX(-1);
}
else {
PUSH_I32(orig_tbl_sz);
PUSH_TBL_ELEM_IDX(orig_tbl_sz);
}
break;
}
@ -5941,13 +5999,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
bh_assert(tbl_idx < module->table_count);
tbl_inst = wasm_get_table_inst(module, tbl_idx);
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = tbl_inst->is_table64;
#endif
PUSH_I32(tbl_inst->cur_size);
PUSH_TBL_ELEM_IDX(tbl_inst->cur_size);
break;
}
case WASM_OP_TABLE_FILL:
{
uint32 tbl_idx, n;
uint32 tbl_idx;
tbl_elem_idx_t n, elem_idx;
WASMTableInstance *tbl_inst;
table_elem_type_t fill_val;
@ -5955,24 +6017,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
bh_assert(tbl_idx < module->table_count);
tbl_inst = wasm_get_table_inst(module, tbl_idx);
#if WASM_ENABLE_MEMORY64 != 0
is_table64 = tbl_inst->is_table64;
#endif
n = POP_I32();
n = POP_TBL_ELEM_IDX();
#if WASM_ENABLE_GC == 0
fill_val = POP_I32();
#else
fill_val = POP_REF();
#endif
i = POP_I32();
elem_idx = POP_TBL_ELEM_IDX();
if (offset_len_out_of_bounds(i, n,
if (
#if WASM_ENABLE_MEMORY64 != 0
n > UINT32_MAX || elem_idx > UINT32_MAX ||
#endif
offset_len_out_of_bounds((uint32)elem_idx,
(uint32)n,
tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
}
for (; n != 0; i++, n--) {
tbl_inst->elems[i] = fill_val;
for (; n != 0; elem_idx++, n--) {
tbl_inst->elems[elem_idx] = fill_val;
}
break;
}