Import reference-types feature (#612)
Implement spec reference-types proposal for interpreter, AOT and JIT, update documents and add sample. And upgrade AOT_CURRENT_VERSION to 3 as AOT file format and AOT module instance layout are changed. Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
@ -20,22 +20,29 @@ extern "C" {
|
||||
#define VALUE_TYPE_F32 0x7D
|
||||
#define VALUE_TYPE_F64 0x7C
|
||||
#define VALUE_TYPE_V128 0x7B
|
||||
#define VALUE_TYPE_FUNCREF 0x70
|
||||
#define VALUE_TYPE_EXTERNREF 0x6F
|
||||
#define VALUE_TYPE_VOID 0x40
|
||||
/* Used by AOT */
|
||||
#define VALUE_TYPE_I1 0x41
|
||||
/* Used by loader to represent any type of i32/i64/f32/f64 */
|
||||
#define VALUE_TYPE_ANY 0x42
|
||||
|
||||
/* Table Element Type */
|
||||
#define TABLE_ELEM_TYPE_ANY_FUNC 0x70
|
||||
|
||||
#define DEFAULT_NUM_BYTES_PER_PAGE 65536
|
||||
|
||||
#define NULL_REF (0xFFFFFFFF)
|
||||
|
||||
#define TABLE_MAX_SIZE (1024)
|
||||
|
||||
#define INIT_EXPR_TYPE_I32_CONST 0x41
|
||||
#define INIT_EXPR_TYPE_I64_CONST 0x42
|
||||
#define INIT_EXPR_TYPE_F32_CONST 0x43
|
||||
#define INIT_EXPR_TYPE_F64_CONST 0x44
|
||||
#define INIT_EXPR_TYPE_V128_CONST 0xFD
|
||||
/* = WASM_OP_REF_FUNC */
|
||||
#define INIT_EXPR_TYPE_FUNCREF_CONST 0xD2
|
||||
/* = WASM_OP_REF_NULL */
|
||||
#define INIT_EXPR_TYPE_REFNULL_CONST 0xD0
|
||||
#define INIT_EXPR_TYPE_GET_GLOBAL 0x23
|
||||
#define INIT_EXPR_TYPE_ERROR 0xff
|
||||
|
||||
@ -105,6 +112,7 @@ typedef union WASMValue {
|
||||
|
||||
typedef struct InitializerExpression {
|
||||
/* type of INIT_EXPR_TYPE_XXX */
|
||||
/* it actually is instr, in some places, requires constant only */
|
||||
uint8 init_expr_type;
|
||||
WASMValue u;
|
||||
} InitializerExpression;
|
||||
@ -124,6 +132,7 @@ typedef struct WASMTable {
|
||||
uint32 init_size;
|
||||
/* specified if (flags & 1), else it is 0x10000 */
|
||||
uint32 max_size;
|
||||
bool possible_grow;
|
||||
} WASMTable;
|
||||
|
||||
typedef struct WASMMemory {
|
||||
@ -141,6 +150,7 @@ typedef struct WASMTableImport {
|
||||
uint32 init_size;
|
||||
/* specified if (flags & 1), else it is 0x10000 */
|
||||
uint32 max_size;
|
||||
bool possible_grow;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModule *import_module;
|
||||
WASMTable *import_table_linked;
|
||||
@ -257,6 +267,12 @@ typedef struct WASMExport {
|
||||
} WASMExport;
|
||||
|
||||
typedef struct WASMTableSeg {
|
||||
/* 0 to 7 */
|
||||
uint32 mode;
|
||||
/* funcref or externref, elemkind will be considered as funcref */
|
||||
uint32 elem_type;
|
||||
bool is_dropped;
|
||||
/* optional, only for active */
|
||||
uint32 table_index;
|
||||
InitializerExpression base_offset;
|
||||
uint32 function_count;
|
||||
@ -456,6 +472,10 @@ wasm_value_type_size(uint8 value_type)
|
||||
switch (value_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
#endif
|
||||
return sizeof(int32);
|
||||
case VALUE_TYPE_I64:
|
||||
case VALUE_TYPE_F64:
|
||||
@ -475,11 +495,14 @@ wasm_value_type_cell_num(uint8 value_type)
|
||||
{
|
||||
if (value_type == VALUE_TYPE_VOID)
|
||||
return 0;
|
||||
else if (value_type == VALUE_TYPE_I32
|
||||
|| value_type == VALUE_TYPE_F32)
|
||||
else if (value_type == VALUE_TYPE_I32 || value_type == VALUE_TYPE_F32
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
|| value_type == VALUE_TYPE_FUNCREF
|
||||
|| value_type == VALUE_TYPE_EXTERNREF
|
||||
#endif
|
||||
)
|
||||
return 1;
|
||||
else if (value_type == VALUE_TYPE_I64
|
||||
|| value_type == VALUE_TYPE_F64)
|
||||
else if (value_type == VALUE_TYPE_I64 || value_type == VALUE_TYPE_F64)
|
||||
return 2;
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
else if (value_type == VALUE_TYPE_V128)
|
||||
|
||||
@ -871,7 +871,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0;
|
||||
uint8 *global_data = module->global_data;
|
||||
uint32 linear_mem_size = memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
WASMTableInstance *table = module->default_table;
|
||||
WASMType **wasm_types = module->module->types;
|
||||
WASMGlobalInstance *globals = module->globals, *global;
|
||||
uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
|
||||
@ -1099,7 +1098,8 @@ label_pop_csp_n:
|
||||
#endif
|
||||
{
|
||||
WASMType *cur_type, *cur_func_type;
|
||||
WASMTableInstance *cur_table_inst;
|
||||
WASMTableInstance *tbl_inst;
|
||||
uint32 tbl_idx;
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
opcode = *(frame_ip - 1);
|
||||
#endif
|
||||
@ -1114,41 +1114,35 @@ label_pop_csp_n:
|
||||
* no matter it is used or not
|
||||
*/
|
||||
read_leb_uint32(frame_ip, frame_ip_end, tidx);
|
||||
if (tidx >= module->module->type_count) {
|
||||
wasm_set_exception(module, "unknown type");
|
||||
goto got_exception;
|
||||
}
|
||||
bh_assert(tidx < module->module->type_count);
|
||||
cur_type = wasm_types[tidx];
|
||||
|
||||
/* to skip 0x00 here */
|
||||
frame_ip++;
|
||||
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);
|
||||
|
||||
val = POP_I32();
|
||||
|
||||
/* careful, it might be a table in another module */
|
||||
cur_table_inst = table;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (table->table_inst_linked) {
|
||||
cur_table_inst = table->table_inst_linked;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (val < 0 || val >= (int32)cur_table_inst->cur_size) {
|
||||
if (val < 0 || val >= (int32)tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "undefined element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
fidx = ((uint32*)cur_table_inst->base_addr)[val];
|
||||
fidx = ((uint32*)tbl_inst->base_addr)[val];
|
||||
if (fidx == (uint32)-1) {
|
||||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
/*
|
||||
* we might be using a table injected by host or
|
||||
* another module. In that case, we don't validate
|
||||
* the elem value while loading
|
||||
*/
|
||||
if (fidx >= module->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* always call module own functions */
|
||||
cur_func = module->functions + fidx;
|
||||
@ -1201,6 +1195,99 @@ label_pop_csp_n:
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
HANDLE_OP (WASM_OP_SELECT_T):
|
||||
{
|
||||
uint32 vec_len;
|
||||
uint8 type;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, vec_len);
|
||||
type = *frame_ip++;
|
||||
|
||||
cond = (uint32)POP_I32();
|
||||
if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) {
|
||||
frame_sp -= 2;
|
||||
if (!cond) {
|
||||
*(frame_sp - 2) = *frame_sp;
|
||||
*(frame_sp - 1) = *(frame_sp + 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
frame_sp--;
|
||||
if (!cond)
|
||||
*(frame_sp - 1) = *frame_sp;
|
||||
}
|
||||
|
||||
(void)vec_len;
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
HANDLE_OP (WASM_OP_TABLE_GET):
|
||||
{
|
||||
uint32 tbl_idx, 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);
|
||||
|
||||
elem_idx = POP_I32();
|
||||
if (elem_idx >= tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
PUSH_I32(((uint32 *)tbl_inst->base_addr)[elem_idx]);
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_TABLE_SET):
|
||||
{
|
||||
uint32 tbl_idx, elem_idx, val;
|
||||
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);
|
||||
|
||||
val = POP_I32();
|
||||
elem_idx = POP_I32();
|
||||
if (elem_idx >= tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
((uint32 *)(tbl_inst->base_addr))[elem_idx] = val;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_REF_NULL):
|
||||
{
|
||||
uint32 ref_type;
|
||||
read_leb_uint32(frame_ip, frame_ip_end, ref_type);
|
||||
PUSH_I32(NULL_REF);
|
||||
(void)ref_type;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_REF_IS_NULL):
|
||||
{
|
||||
uint32 val;
|
||||
val = POP_I32();
|
||||
PUSH_I32(val == NULL_REF ? 1 : 0);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_REF_FUNC):
|
||||
{
|
||||
uint32 func_idx;
|
||||
read_leb_uint32(frame_ip, frame_ip_end, func_idx);
|
||||
PUSH_I32(func_idx);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
#endif /* WASM_ENABLE_REF_TYPES */
|
||||
|
||||
/* variable instructions */
|
||||
HANDLE_OP (WASM_OP_GET_LOCAL):
|
||||
{
|
||||
@ -1209,6 +1296,10 @@ label_pop_csp_n:
|
||||
switch (local_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
#endif
|
||||
PUSH_I32(*(int32*)(frame_lp + local_offset));
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
@ -1240,6 +1331,10 @@ label_pop_csp_n:
|
||||
switch (local_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
#endif
|
||||
*(int32*)(frame_lp + local_offset) = POP_I32();
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
@ -1271,6 +1366,10 @@ label_pop_csp_n:
|
||||
switch (local_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
#endif
|
||||
*(int32*)(frame_lp + local_offset) = *(int32*)(frame_sp - 1);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
@ -2586,10 +2685,173 @@ label_pop_csp_n:
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_BULK_MEMORY */
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case WASM_OP_TABLE_INIT:
|
||||
{
|
||||
uint32 tbl_idx, elem_idx;
|
||||
uint64 n, s, d;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
|
||||
bh_assert(elem_idx < module->module->table_seg_count);
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
|
||||
bh_assert(tbl_idx < module->module->table_count);
|
||||
|
||||
tbl_inst = wasm_get_table_inst(module, tbl_idx);
|
||||
|
||||
n = (uint32)POP_I32();
|
||||
s = (uint32)POP_I32();
|
||||
d = (uint32)POP_I32();
|
||||
|
||||
/* TODO: what if the element is not passive? */
|
||||
|
||||
if (!n) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (n + s > module->module->table_segments[elem_idx].function_count
|
||||
|| d + n > tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
if (module->module->table_segments[elem_idx].is_dropped) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
if (!wasm_elem_is_passive(
|
||||
module->module->table_segments[elem_idx].mode)) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
bh_memcpy_s(
|
||||
(uint8 *)(tbl_inst)
|
||||
+ offsetof(WASMTableInstance, base_addr) + d * sizeof(uint32),
|
||||
(tbl_inst->cur_size - d) * sizeof(uint32),
|
||||
module->module->table_segments[elem_idx].func_indexes + s,
|
||||
n * sizeof(uint32));
|
||||
|
||||
break;
|
||||
}
|
||||
case WASM_OP_ELEM_DROP:
|
||||
{
|
||||
uint32 elem_idx;
|
||||
read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
|
||||
bh_assert(elem_idx < module->module->table_seg_count);
|
||||
|
||||
module->module->table_segments[elem_idx].is_dropped = true;
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_COPY:
|
||||
{
|
||||
uint32 src_tbl_idx, dst_tbl_idx;
|
||||
uint64 n, s, d;
|
||||
WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx);
|
||||
bh_assert(dst_tbl_idx < module->table_count);
|
||||
|
||||
dst_tbl_inst = wasm_get_table_inst(module, dst_tbl_idx);
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, src_tbl_idx);
|
||||
bh_assert(src_tbl_idx < module->table_count);
|
||||
|
||||
src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx);
|
||||
|
||||
n = (uint32)POP_I32();
|
||||
s = (uint32)POP_I32();
|
||||
d = (uint32)POP_I32();
|
||||
|
||||
if (s + n > dst_tbl_inst->cur_size
|
||||
|| d + n > src_tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
/* if s >= d, copy from front to back */
|
||||
/* if s < d, copy from back to front */
|
||||
/* merge all together */
|
||||
bh_memcpy_s(
|
||||
(uint8 *)(dst_tbl_inst) + offsetof(WASMTableInstance, base_addr)
|
||||
+ d * sizeof(uint32),
|
||||
(dst_tbl_inst->cur_size - d) * sizeof(uint32),
|
||||
(uint8 *)(src_tbl_inst) + offsetof(WASMTableInstance, base_addr)
|
||||
+ s * sizeof(uint32),
|
||||
n * sizeof(uint32));
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_GROW:
|
||||
{
|
||||
uint32 tbl_idx, n, init_val, orig_tbl_sz;
|
||||
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);
|
||||
|
||||
orig_tbl_sz = tbl_inst->cur_size;
|
||||
|
||||
n = POP_I32();
|
||||
init_val = POP_I32();
|
||||
|
||||
if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) {
|
||||
PUSH_I32(-1);
|
||||
}
|
||||
else {
|
||||
PUSH_I32(orig_tbl_sz);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_SIZE:
|
||||
{
|
||||
uint32 tbl_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);
|
||||
|
||||
PUSH_I32(tbl_inst->cur_size);
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_FILL:
|
||||
{
|
||||
uint32 tbl_idx, n, val, i;
|
||||
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);
|
||||
|
||||
n = POP_I32();
|
||||
val = POP_I32();
|
||||
i = POP_I32();
|
||||
|
||||
/* TODO: what if the element is not passive? */
|
||||
/* TODO: what if the element is dropped? */
|
||||
|
||||
if (i + n > tbl_inst->cur_size) {
|
||||
/* TODO: verify warning content */
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
for (; n != 0; i++, n--) {
|
||||
((uint32 *)(tbl_inst->base_addr))[i] = val;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_REF_TYPES */
|
||||
default:
|
||||
wasm_set_exception(module, "unsupported opcode");
|
||||
goto got_exception;
|
||||
break;
|
||||
goto got_exception;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
@ -2946,6 +3208,17 @@ label_pop_csp_n:
|
||||
#if WASM_ENABLE_TAIL_CALL == 0
|
||||
HANDLE_OP (WASM_OP_RETURN_CALL):
|
||||
HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT):
|
||||
#endif
|
||||
#if WASM_ENABLE_SHARED_MEMORY == 0
|
||||
HANDLE_OP (WASM_OP_ATOMIC_PREFIX):
|
||||
#endif
|
||||
#if WASM_ENABLE_REF_TYPES == 0
|
||||
HANDLE_OP (WASM_OP_SELECT_T):
|
||||
HANDLE_OP (WASM_OP_TABLE_GET):
|
||||
HANDLE_OP (WASM_OP_TABLE_SET):
|
||||
HANDLE_OP (WASM_OP_REF_NULL):
|
||||
HANDLE_OP (WASM_OP_REF_IS_NULL):
|
||||
HANDLE_OP (WASM_OP_REF_FUNC):
|
||||
#endif
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x14):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x15):
|
||||
@ -2953,10 +3226,7 @@ label_pop_csp_n:
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x17):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x18):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x19):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x1c):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x1d):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x1e):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x1f):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x27):
|
||||
/* Used by fast interpreter */
|
||||
HANDLE_OP (EXT_OP_SET_LOCAL_FAST_I64):
|
||||
HANDLE_OP (EXT_OP_TEE_LOCAL_FAST_I64):
|
||||
|
||||
@ -991,7 +991,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0;
|
||||
uint8 *global_data = module->global_data;
|
||||
uint32 linear_mem_size = memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
WASMTableInstance *table = module->default_table;
|
||||
WASMGlobalInstance *globals = module->globals, *global;
|
||||
uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
|
||||
WASMInterpFrame *frame = NULL;
|
||||
@ -1150,7 +1149,8 @@ recover_br_info:
|
||||
#endif
|
||||
{
|
||||
WASMType *cur_type, *cur_func_type;
|
||||
WASMTableInstance *cur_table_inst;
|
||||
WASMTableInstance *tbl_inst;
|
||||
uint32 tbl_idx;
|
||||
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
GET_OPCODE();
|
||||
@ -1160,40 +1160,36 @@ recover_br_info:
|
||||
#endif
|
||||
|
||||
tidx = read_uint32(frame_ip);
|
||||
cur_type = module->module->types[tidx];
|
||||
|
||||
tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(tbl_idx < module->table_count);
|
||||
|
||||
tbl_inst = wasm_get_table_inst(module, tbl_idx);
|
||||
|
||||
val = GET_OPERAND(uint32, I32, 0);
|
||||
frame_ip += 2;
|
||||
|
||||
if (tidx >= module->module->type_count) {
|
||||
wasm_set_exception(module, "type index is overflow");
|
||||
goto got_exception;
|
||||
}
|
||||
cur_type = module->module->types[tidx];
|
||||
|
||||
/* careful, it might be a table in another module */
|
||||
cur_table_inst = table;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (table->table_inst_linked) {
|
||||
cur_table_inst = table->table_inst_linked;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (val < 0 || val >= (int32)cur_table_inst->cur_size) {
|
||||
if (val < 0 || val >= (int32)tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "undefined element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
fidx = ((uint32*)cur_table_inst->base_addr)[val];
|
||||
fidx = ((uint32*)tbl_inst->base_addr)[val];
|
||||
if (fidx == (uint32)-1) {
|
||||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/*
|
||||
* we might be using a table injected by host or
|
||||
* another module. in that case, we don't validate
|
||||
* the elem value while loading
|
||||
*/
|
||||
if (fidx >= module->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* always call module own functions */
|
||||
cur_func = module->functions + fidx;
|
||||
@ -1252,6 +1248,70 @@ recover_br_info:
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
HANDLE_OP (WASM_OP_TABLE_GET):
|
||||
{
|
||||
uint32 tbl_idx, elem_idx;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(tbl_idx < module->table_count);
|
||||
|
||||
tbl_inst = wasm_get_table_inst(module, tbl_idx);
|
||||
|
||||
elem_idx = POP_I32();
|
||||
if (elem_idx >= tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
PUSH_I32(((uint32 *)tbl_inst->base_addr)[elem_idx]);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_TABLE_SET):
|
||||
{
|
||||
uint32 tbl_idx, elem_idx, val;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(tbl_idx < module->table_count);
|
||||
|
||||
tbl_inst = wasm_get_table_inst(module, tbl_idx);
|
||||
|
||||
val = POP_I32();
|
||||
elem_idx = POP_I32();
|
||||
if (elem_idx >= tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
((uint32 *)tbl_inst->base_addr)[elem_idx] = val;
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_REF_NULL):
|
||||
{
|
||||
PUSH_I32(NULL_REF);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_REF_IS_NULL):
|
||||
{
|
||||
uint32 val;
|
||||
val = POP_I32();
|
||||
PUSH_I32(val == NULL_REF ? 1 : 0);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP (WASM_OP_REF_FUNC):
|
||||
{
|
||||
uint32 func_idx = read_uint32(frame_ip);
|
||||
PUSH_I32(func_idx);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
#endif /* WASM_ENABLE_REF_TYPES */
|
||||
|
||||
/* variable instructions */
|
||||
HANDLE_OP (EXT_OP_SET_LOCAL_FAST):
|
||||
HANDLE_OP (EXT_OP_TEE_LOCAL_FAST):
|
||||
@ -2605,10 +2665,165 @@ recover_br_info:
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_BULK_MEMORY */
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case WASM_OP_TABLE_INIT:
|
||||
{
|
||||
uint32 tbl_idx, elem_idx;
|
||||
uint64 n, s, d;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
elem_idx = read_uint32(frame_ip);
|
||||
bh_assert(elem_idx < module->module->table_seg_count);
|
||||
|
||||
tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(tbl_idx < module->module->table_count);
|
||||
|
||||
tbl_inst = wasm_get_table_inst(module, tbl_idx);
|
||||
|
||||
n = (uint32)POP_I32();
|
||||
s = (uint32)POP_I32();
|
||||
d = (uint32)POP_I32();
|
||||
|
||||
if (!n) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (n + s > module->module->table_segments[elem_idx].function_count
|
||||
|| d + n > tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
if (module->module->table_segments[elem_idx].is_dropped) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
if (!wasm_elem_is_passive(
|
||||
module->module->table_segments[elem_idx].mode)) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
bh_memcpy_s(
|
||||
(uint8 *)tbl_inst + offsetof(WASMTableInstance, base_addr)
|
||||
+ d * sizeof(uint32),
|
||||
(tbl_inst->cur_size - d) * sizeof(uint32),
|
||||
module->module->table_segments[elem_idx].func_indexes + s,
|
||||
n * sizeof(uint32));
|
||||
break;
|
||||
}
|
||||
case WASM_OP_ELEM_DROP:
|
||||
{
|
||||
uint32 elem_idx = read_uint32(frame_ip);
|
||||
bh_assert(elem_idx < module->module->table_seg_count);
|
||||
|
||||
module->module->table_segments[elem_idx].is_dropped = true;
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_COPY:
|
||||
{
|
||||
uint32 src_tbl_idx, dst_tbl_idx;
|
||||
uint64 n, s, d;
|
||||
WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
|
||||
|
||||
dst_tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(dst_tbl_idx < module->table_count);
|
||||
|
||||
dst_tbl_inst = wasm_get_table_inst(module, dst_tbl_idx);
|
||||
|
||||
src_tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(src_tbl_idx < module->table_count);
|
||||
|
||||
src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx);
|
||||
|
||||
n = (uint32)POP_I32();
|
||||
s = (uint32)POP_I32();
|
||||
d = (uint32)POP_I32();
|
||||
|
||||
if (s + n > dst_tbl_inst->cur_size
|
||||
|| d + n > src_tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
/* if s >= d, copy from front to back */
|
||||
/* if s < d, copy from back to front */
|
||||
/* merge all together */
|
||||
bh_memcpy_s(
|
||||
(uint8 *)dst_tbl_inst + offsetof(WASMTableInstance, base_addr)
|
||||
+ d * sizeof(uint32),
|
||||
(dst_tbl_inst->cur_size - d) * sizeof(uint32),
|
||||
(uint8 *)src_tbl_inst
|
||||
+ offsetof(WASMTableInstance, base_addr) + s * sizeof(uint32),
|
||||
n * sizeof(uint32));
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_GROW:
|
||||
{
|
||||
uint32 tbl_idx, n, init_val, orig_tbl_sz;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(tbl_idx < module->table_count);
|
||||
|
||||
tbl_inst = wasm_get_table_inst(module, tbl_idx);
|
||||
|
||||
orig_tbl_sz = tbl_inst->cur_size;
|
||||
|
||||
n = POP_I32();
|
||||
init_val = POP_I32();
|
||||
|
||||
if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) {
|
||||
PUSH_I32(-1);
|
||||
} else {
|
||||
PUSH_I32(orig_tbl_sz);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_SIZE:
|
||||
{
|
||||
uint32 tbl_idx;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(tbl_idx < module->table_count);
|
||||
|
||||
tbl_inst = wasm_get_table_inst(module, tbl_idx);
|
||||
|
||||
PUSH_I32(tbl_inst->cur_size);
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_FILL:
|
||||
{
|
||||
uint32 tbl_idx, n, val, i;
|
||||
WASMTableInstance *tbl_inst;
|
||||
|
||||
tbl_idx = read_uint32(frame_ip);
|
||||
bh_assert(tbl_idx < module->table_count);
|
||||
|
||||
tbl_inst = wasm_get_table_inst(module, tbl_idx);
|
||||
|
||||
n = POP_I32();
|
||||
val = POP_I32();
|
||||
i = POP_I32();
|
||||
|
||||
if (i + n > tbl_inst->cur_size) {
|
||||
wasm_set_exception(module, "out of bounds table access");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
for (; n != 0; i++, n--) {
|
||||
((uint32 *)(tbl_inst->base_addr))[i] = val;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_REF_TYPES */
|
||||
default:
|
||||
wasm_set_exception(module, "unsupported opcode");
|
||||
goto got_exception;
|
||||
break;
|
||||
goto got_exception;
|
||||
}
|
||||
HANDLE_OP_END ();
|
||||
}
|
||||
@ -2992,16 +3207,25 @@ recover_br_info:
|
||||
HANDLE_OP (WASM_OP_RETURN_CALL):
|
||||
HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT):
|
||||
#endif
|
||||
#if WASM_ENABLE_SHARED_MEMORY == 0
|
||||
HANDLE_OP (WASM_OP_ATOMIC_PREFIX):
|
||||
#endif
|
||||
#if WASM_ENABLE_REF_TYPES == 0
|
||||
HANDLE_OP (WASM_OP_TABLE_GET):
|
||||
HANDLE_OP (WASM_OP_TABLE_SET):
|
||||
HANDLE_OP (WASM_OP_REF_NULL):
|
||||
HANDLE_OP (WASM_OP_REF_IS_NULL):
|
||||
HANDLE_OP (WASM_OP_REF_FUNC):
|
||||
#endif
|
||||
/* SELECT_T is converted to SELECT or SELECT_64 */
|
||||
HANDLE_OP (WASM_OP_SELECT_T):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x14):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x15):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x16):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x17):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x18):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x19):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x1c):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x1d):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x1e):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x1f):
|
||||
HANDLE_OP (WASM_OP_UNUSED_0x27):
|
||||
/* optimized op code */
|
||||
HANDLE_OP (WASM_OP_F32_STORE):
|
||||
HANDLE_OP (WASM_OP_F64_STORE):
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -70,6 +70,14 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
|
||||
uint8 **p_else_addr,
|
||||
uint8 **p_end_addr);
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
void
|
||||
wasm_set_ref_types_flag(bool enable);
|
||||
|
||||
bool
|
||||
wasm_get_ref_types_flag();
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -47,11 +47,11 @@ typedef enum WASMOpcode {
|
||||
/* parametric instructions */
|
||||
WASM_OP_DROP = 0x1a, /* drop */
|
||||
WASM_OP_SELECT = 0x1b, /* select */
|
||||
WASM_OP_SELECT_T = 0x1c, /* select t */
|
||||
|
||||
WASM_OP_UNUSED_0x1c = 0x1c,
|
||||
WASM_OP_UNUSED_0x1d = 0x1d,
|
||||
WASM_OP_UNUSED_0x1e = 0x1e,
|
||||
WASM_OP_UNUSED_0x1f = 0x1f,
|
||||
WASM_OP_GET_GLOBAL_64 = 0x1d,
|
||||
WASM_OP_SET_GLOBAL_64 = 0x1e,
|
||||
WASM_OP_SET_GLOBAL_AUX_STACK = 0x1f,
|
||||
|
||||
/* variable instructions */
|
||||
WASM_OP_GET_LOCAL = 0x20, /* get_local */
|
||||
@ -60,9 +60,9 @@ typedef enum WASMOpcode {
|
||||
WASM_OP_GET_GLOBAL = 0x23, /* get_global */
|
||||
WASM_OP_SET_GLOBAL = 0x24, /* set_global */
|
||||
|
||||
WASM_OP_GET_GLOBAL_64 = 0x25,
|
||||
WASM_OP_SET_GLOBAL_64 = 0x26,
|
||||
WASM_OP_SET_GLOBAL_AUX_STACK = 0x27,
|
||||
WASM_OP_TABLE_GET = 0x25, /* table.get */
|
||||
WASM_OP_TABLE_SET = 0x26, /* table.set */
|
||||
WASM_OP_UNUSED_0x27 = 0x27,
|
||||
|
||||
/* memory instructions */
|
||||
WASM_OP_I32_LOAD = 0x28, /* i32.load */
|
||||
@ -256,10 +256,16 @@ typedef enum WASMOpcode {
|
||||
EXT_OP_COPY_STACK_TOP = 0xcc,
|
||||
EXT_OP_COPY_STACK_TOP_I64 = 0xcd,
|
||||
EXT_OP_COPY_STACK_VALUES = 0xce,
|
||||
EXT_OP_BLOCK = 0xcf, /* block with blocktype */
|
||||
EXT_OP_LOOP = 0xd0, /* loop with blocktype */
|
||||
EXT_OP_IF = 0xd1, /* if with blocktype */
|
||||
WASM_OP_IMPDEP = 0xd2,
|
||||
|
||||
WASM_OP_IMPDEP = 0xcf,
|
||||
|
||||
WASM_OP_REF_NULL = 0xd0, /* ref.null */
|
||||
WASM_OP_REF_IS_NULL = 0xd1, /* ref.is_null */
|
||||
WASM_OP_REF_FUNC = 0xd2, /* ref.func */
|
||||
|
||||
EXT_OP_BLOCK = 0xd3, /* block with blocktype */
|
||||
EXT_OP_LOOP = 0xd4, /* loop with blocktype */
|
||||
EXT_OP_IF = 0xd5, /* if with blocktype */
|
||||
|
||||
/* Post-MVP extend op prefix */
|
||||
WASM_OP_MISC_PREFIX = 0xfc,
|
||||
@ -276,15 +282,16 @@ typedef enum WASMMiscEXTOpcode {
|
||||
WASM_OP_I64_TRUNC_SAT_U_F32 = 0x05,
|
||||
WASM_OP_I64_TRUNC_SAT_S_F64 = 0x06,
|
||||
WASM_OP_I64_TRUNC_SAT_U_F64 = 0x07,
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
WASM_OP_MEMORY_INIT = 0x08,
|
||||
WASM_OP_DATA_DROP = 0x09,
|
||||
WASM_OP_MEMORY_COPY = 0x0a,
|
||||
WASM_OP_MEMORY_FILL = 0x0b,
|
||||
WASM_OP_TABLE_INIT = 0x0c,
|
||||
WASM_OP_ELEM_DROP = 0x0d,
|
||||
WASM_OP_TABLE_COPY = 0x0e
|
||||
#endif
|
||||
WASM_OP_TABLE_COPY = 0x0e,
|
||||
WASM_OP_TABLE_GROW = 0x0f,
|
||||
WASM_OP_TABLE_SIZE = 0x10,
|
||||
WASM_OP_TABLE_FILL = 0x11,
|
||||
} WASMMiscEXTOpcode;
|
||||
|
||||
typedef enum WASMSimdEXTOpcode {
|
||||
@ -594,15 +601,6 @@ typedef enum WASMAtomicEXTOpcode {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Opcode prefix controlled by features */
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
#define DEF_ATOMIC_PREFIX_HANDLE(_name) \
|
||||
_name[WASM_OP_ATOMIC_PREFIX] = \
|
||||
HANDLE_OPCODE (WASM_OP_ATOMIC_PREFIX); /* 0xfe */
|
||||
#else
|
||||
#define DEF_ATOMIC_PREFIX_HANDLE(_name)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macro used to generate computed goto tables for the C interpreter.
|
||||
*/
|
||||
@ -638,18 +636,18 @@ static type _name[WASM_INSTRUCTION_NUM] = { \
|
||||
HANDLE_OPCODE (WASM_OP_UNUSED_0x19), /* 0x19 */ \
|
||||
HANDLE_OPCODE (WASM_OP_DROP), /* 0x1a */ \
|
||||
HANDLE_OPCODE (WASM_OP_SELECT), /* 0x1b */ \
|
||||
HANDLE_OPCODE (WASM_OP_UNUSED_0x1c), /* 0x1c */ \
|
||||
HANDLE_OPCODE (WASM_OP_UNUSED_0x1d), /* 0x1d */ \
|
||||
HANDLE_OPCODE (WASM_OP_UNUSED_0x1e), /* 0x1e */ \
|
||||
HANDLE_OPCODE (WASM_OP_UNUSED_0x1f), /* 0x1f */ \
|
||||
HANDLE_OPCODE (WASM_OP_SELECT_T), /* 0x1c */ \
|
||||
HANDLE_OPCODE (WASM_OP_GET_GLOBAL_64), /* 0x1d */ \
|
||||
HANDLE_OPCODE (WASM_OP_SET_GLOBAL_64), /* 0x1e */ \
|
||||
HANDLE_OPCODE (WASM_OP_SET_GLOBAL_AUX_STACK), /* 0x1f */ \
|
||||
HANDLE_OPCODE (WASM_OP_GET_LOCAL), /* 0x20 */ \
|
||||
HANDLE_OPCODE (WASM_OP_SET_LOCAL), /* 0x21 */ \
|
||||
HANDLE_OPCODE (WASM_OP_TEE_LOCAL), /* 0x22 */ \
|
||||
HANDLE_OPCODE (WASM_OP_GET_GLOBAL), /* 0x23 */ \
|
||||
HANDLE_OPCODE (WASM_OP_SET_GLOBAL), /* 0x24 */ \
|
||||
HANDLE_OPCODE (WASM_OP_GET_GLOBAL_64), /* 0x25 */ \
|
||||
HANDLE_OPCODE (WASM_OP_SET_GLOBAL_64), /* 0x26 */ \
|
||||
HANDLE_OPCODE (WASM_OP_SET_GLOBAL_AUX_STACK), /* 0x27 */ \
|
||||
HANDLE_OPCODE (WASM_OP_TABLE_GET), /* 0x25 */ \
|
||||
HANDLE_OPCODE (WASM_OP_TABLE_SET), /* 0x26 */ \
|
||||
HANDLE_OPCODE (WASM_OP_UNUSED_0x27), /* 0x27 */ \
|
||||
HANDLE_OPCODE (WASM_OP_I32_LOAD), /* 0x28 */ \
|
||||
HANDLE_OPCODE (WASM_OP_I64_LOAD), /* 0x29 */ \
|
||||
HANDLE_OPCODE (WASM_OP_F32_LOAD), /* 0x2a */ \
|
||||
@ -817,14 +815,19 @@ static type _name[WASM_INSTRUCTION_NUM] = { \
|
||||
HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP), /* 0xcc */ \
|
||||
HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP_I64), /* 0xcd */ \
|
||||
HANDLE_OPCODE (EXT_OP_COPY_STACK_VALUES), /* 0xce */ \
|
||||
HANDLE_OPCODE (EXT_OP_BLOCK), /* 0xcf */ \
|
||||
HANDLE_OPCODE (EXT_OP_LOOP), /* 0xd0 */ \
|
||||
HANDLE_OPCODE (EXT_OP_IF), /* 0xd1 */ \
|
||||
HANDLE_OPCODE (WASM_OP_IMPDEP), /* 0xd2 */ \
|
||||
HANDLE_OPCODE (WASM_OP_IMPDEP), /* 0xcf */ \
|
||||
HANDLE_OPCODE (WASM_OP_REF_NULL), /* 0xd0 */ \
|
||||
HANDLE_OPCODE (WASM_OP_REF_IS_NULL), /* 0xd1 */ \
|
||||
HANDLE_OPCODE (WASM_OP_REF_FUNC), /* 0xd2 */ \
|
||||
HANDLE_OPCODE (EXT_OP_BLOCK), /* 0xd3 */ \
|
||||
HANDLE_OPCODE (EXT_OP_LOOP), /* 0xd4 */ \
|
||||
HANDLE_OPCODE (EXT_OP_IF), /* 0xd5 */ \
|
||||
}; \
|
||||
do { \
|
||||
_name[WASM_OP_MISC_PREFIX] = \
|
||||
HANDLE_OPCODE (WASM_OP_MISC_PREFIX); /* 0xfc */ \
|
||||
DEF_ATOMIC_PREFIX_HANDLE(_name) \
|
||||
_name[WASM_OP_ATOMIC_PREFIX] = \
|
||||
HANDLE_OPCODE (WASM_OP_ATOMIC_PREFIX); /* 0xfe */ \
|
||||
} while (0)
|
||||
#endif /* end of _WASM_OPCODE_H */
|
||||
|
||||
|
||||
@ -499,9 +499,12 @@ tables_instantiate(const WASMModule *module,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* it is a built-in table */
|
||||
total_size = offsetof(WASMTableInstance, base_addr)
|
||||
+ sizeof(uint32) * (uint64)import->u.table.init_size;
|
||||
/* it is a built-in table, every module has its own */
|
||||
total_size = offsetof(WASMTableInstance, base_addr);
|
||||
total_size +=
|
||||
import->u.table.possible_grow
|
||||
? sizeof(uint32) * (uint64)import->u.table.max_size
|
||||
: sizeof(uint32) * (uint64)import->u.table.init_size;
|
||||
}
|
||||
|
||||
if (!(table = tables[table_index++] = runtime_malloc
|
||||
@ -530,8 +533,15 @@ tables_instantiate(const WASMModule *module,
|
||||
|
||||
/* instantiate tables from table section */
|
||||
for (i = 0; i < module->table_count; i++) {
|
||||
total_size = offsetof(WASMTableInstance, base_addr) +
|
||||
sizeof(uint32) * (uint64)module->tables[i].init_size;
|
||||
total_size = offsetof(WASMTableInstance, base_addr);
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* in case, a module which imports this table will grow it */
|
||||
total_size += sizeof(uint32) * (uint64)module->tables[i].max_size;
|
||||
#else
|
||||
total_size += module->tables[i].possible_grow
|
||||
? sizeof(uint32) * (uint64)module->tables[i].max_size
|
||||
: sizeof(uint32) * (uint64)module->tables[i].init_size;
|
||||
#endif
|
||||
if (!(table = tables[table_index++] = runtime_malloc
|
||||
(total_size, error_buf, error_buf_size))) {
|
||||
tables_deinstantiate(tables, table_count);
|
||||
@ -764,6 +774,11 @@ globals_instantiate(const WASMModule *module,
|
||||
&(globals[init_expr->u.global_index].initial_value),
|
||||
sizeof(globals[init_expr->u.global_index].initial_value));
|
||||
}
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
else if (init_expr->init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST) {
|
||||
global->initial_value.u32 = (uint32)NULL_REF;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
|
||||
&(init_expr->u), sizeof(init_expr->u));
|
||||
@ -1216,6 +1231,10 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
switch (global->type) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
#endif
|
||||
*(int32*)global_data = global->initial_value.i32;
|
||||
global_data += sizeof(int32);
|
||||
break;
|
||||
@ -1285,13 +1304,18 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
.initial_value.i32;
|
||||
}
|
||||
|
||||
/* check offset since length might negative */
|
||||
/* check offset */
|
||||
base_offset = (uint32)data_seg->base_offset.u.i32;
|
||||
if (base_offset > memory_size) {
|
||||
LOG_DEBUG("base_offset(%d) > memory_size(%d)", base_offset,
|
||||
memory_size);
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"out of bounds memory access");
|
||||
#else
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"data segment does not fit");
|
||||
#endif
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1300,8 +1324,13 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
if (base_offset + length > memory_size) {
|
||||
LOG_DEBUG("base_offset(%d) + length(%d) > memory_size(%d)",
|
||||
base_offset, length, memory_size);
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"out of bounds memory access");
|
||||
#else
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"data segment does not fit");
|
||||
#endif
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1314,12 +1343,23 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
/* Initialize the table data with table segment section */
|
||||
module_inst->default_table =
|
||||
module_inst->table_count ? module_inst->tables[0] : NULL;
|
||||
for (i = 0; i < module->table_seg_count; i++) {
|
||||
/* in case there is no table */
|
||||
for (i = 0; module_inst->table_count > 0 && i < module->table_seg_count;
|
||||
i++) {
|
||||
WASMTableSeg *table_seg = module->table_segments + i;
|
||||
/* has check it in loader */
|
||||
WASMTableInstance *table = module_inst->tables[table_seg->table_index];
|
||||
bh_assert(table);
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
if (table->elem_type != VALUE_TYPE_FUNCREF
|
||||
&& table->elem_type != VALUE_TYPE_EXTERNREF) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"elements segment does not fit");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32 *table_data = (uint32 *)table->base_addr;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
table_data = table->table_inst_linked
|
||||
@ -1328,11 +1368,20 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
#endif
|
||||
bh_assert(table_data);
|
||||
|
||||
/* init vec(funcidx) */
|
||||
bh_assert(table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST
|
||||
|| table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL);
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
if (!wasm_elem_is_active(table_seg->mode))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/* init vec(funcidx) or vec(expr) */
|
||||
bh_assert(
|
||||
table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
|
||||
|| table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
|| table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
|| table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST
|
||||
#endif
|
||||
);
|
||||
|
||||
if (table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
@ -1349,6 +1398,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
"elements segment does not fit");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
table_seg->base_offset.u.i32 =
|
||||
globals[table_seg->base_offset.u.global_index].initial_value.i32;
|
||||
}
|
||||
@ -1357,8 +1407,13 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
if ((uint32)table_seg->base_offset.u.i32 > table->cur_size) {
|
||||
LOG_DEBUG("base_offset(%d) > table->cur_size(%d)",
|
||||
table_seg->base_offset.u.i32, table->cur_size);
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"out of bounds table access");
|
||||
#else
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"elements segment does not fit");
|
||||
#endif
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1367,8 +1422,13 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
|
||||
if ((uint32)table_seg->base_offset.u.i32 + length > table->cur_size) {
|
||||
LOG_DEBUG("base_offset(%d) + length(%d)> table->cur_size(%d)",
|
||||
table_seg->base_offset.u.i32, length, table->cur_size);
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"out of bounds table access");
|
||||
#else
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"elements segment does not fit");
|
||||
#endif
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1510,6 +1570,10 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
||||
if (module_inst->global_data)
|
||||
wasm_runtime_free(module_inst->global_data);
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
wasm_externref_cleanup((WASMModuleInstanceCommon*)module_inst);
|
||||
#endif
|
||||
|
||||
wasm_runtime_free(module_inst);
|
||||
}
|
||||
|
||||
@ -1616,8 +1680,16 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
wasm_runtime_prepare_call_function(exec_env, func);
|
||||
#endif
|
||||
|
||||
ret = wasm_call_function(exec_env, func, argc, argv);
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
wasm_runtime_finalize_call_function(exec_env, func, ret, argv);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* don't destroy the exec_env if it's searched from the cluster */
|
||||
if (!existing_exec_env)
|
||||
@ -2025,8 +2097,47 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
bool
|
||||
wasm_enlarge_table(WASMModuleInstance *module_inst,
|
||||
uint32 table_idx, uint32 inc_entries, uint32 init_val)
|
||||
{
|
||||
uint32 entry_count, *new_table_data_start, i;
|
||||
WASMTableInstance *table_inst;
|
||||
|
||||
if (!inc_entries) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bh_assert(table_idx < module_inst->table_count);
|
||||
table_inst = wasm_get_table_inst(module_inst, table_idx);
|
||||
if (!table_inst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
entry_count = table_inst->cur_size + inc_entries;
|
||||
/* prevent from integer overflow */
|
||||
if (entry_count < table_inst->cur_size
|
||||
|| entry_count > table_inst->max_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* fill in */
|
||||
new_table_data_start =
|
||||
(uint32 *)((uint8 *)table_inst + offsetof(WASMTableInstance, base_addr))
|
||||
+ table_inst->cur_size;
|
||||
for (i = 0; i < inc_entries; ++i) {
|
||||
new_table_data_start[i] = init_val;
|
||||
}
|
||||
|
||||
table_inst->cur_size = entry_count;
|
||||
return true;
|
||||
}
|
||||
#endif /* WASM_ENABLE_REF_TYPES != 0 */
|
||||
|
||||
bool
|
||||
wasm_call_indirect(WASMExecEnv *exec_env,
|
||||
uint32_t tbl_idx,
|
||||
uint32_t element_indices,
|
||||
uint32_t argc, uint32_t argv[])
|
||||
{
|
||||
@ -2039,7 +2150,7 @@ wasm_call_indirect(WASMExecEnv *exec_env,
|
||||
(WASMModuleInstance*)exec_env->module_inst;
|
||||
bh_assert(module_inst);
|
||||
|
||||
table_inst = module_inst->default_table;
|
||||
table_inst = module_inst->tables[tbl_idx];
|
||||
if (!table_inst) {
|
||||
wasm_set_exception(module_inst, "unknown table");
|
||||
goto got_exception;
|
||||
@ -2055,7 +2166,7 @@ wasm_call_indirect(WASMExecEnv *exec_env,
|
||||
* to another module's table
|
||||
**/
|
||||
function_indices = ((uint32_t*)table_inst->base_addr)[element_indices];
|
||||
if (function_indices == 0xFFFFFFFF) {
|
||||
if (function_indices == NULL_REF) {
|
||||
wasm_set_exception(module_inst, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
@ -2247,8 +2358,16 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst,
|
||||
* module_inst->table_count;
|
||||
for (i = 0; i < module_inst->table_count; i++) {
|
||||
WASMTableInstance *table = module_inst->tables[i];
|
||||
size = offsetof(WASMTableInstance, base_addr)
|
||||
+ sizeof(uint32) * table->cur_size;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (table->table_inst_linked) {
|
||||
size = offsetof(WASMTableInstance, base_addr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
size = offsetof(WASMTableInstance, base_addr)
|
||||
+ sizeof(uint32) * table->cur_size;
|
||||
}
|
||||
mem_conspn->tables_size += size;
|
||||
}
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ struct WASMMemoryInstance {
|
||||
};
|
||||
|
||||
struct WASMTableInstance {
|
||||
/* The element type, TABLE_ELEM_TYPE_ANY_FUNC currently */
|
||||
/* The element type, VALUE_TYPE_FUNCREF/EXTERNREF currently */
|
||||
uint8 elem_type;
|
||||
/* Current size */
|
||||
uint32 cur_size;
|
||||
@ -376,6 +376,7 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count);
|
||||
|
||||
bool
|
||||
wasm_call_indirect(WASMExecEnv *exec_env,
|
||||
uint32_t tbl_idx,
|
||||
uint32_t element_indices,
|
||||
uint32_t argc, uint32_t argv[]);
|
||||
|
||||
@ -397,6 +398,45 @@ void
|
||||
wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module,
|
||||
WASMModuleInstMemConsumption *mem_conspn);
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
static inline bool
|
||||
wasm_elem_is_active(uint32 mode)
|
||||
{
|
||||
return (mode & 0x1) == 0x0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
wasm_elem_is_passive(uint32 mode)
|
||||
{
|
||||
return (mode & 0x1) == 0x1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
wasm_elem_is_declarative(uint32 mode)
|
||||
{
|
||||
return (mode & 0x3) == 0x3;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_enlarge_table(WASMModuleInstance *module_inst,
|
||||
uint32 table_idx, uint32 inc_entries, uint32 init_val);
|
||||
#endif /* WASM_ENABLE_REF_TYPES != 0 */
|
||||
|
||||
static inline WASMTableInstance *
|
||||
wasm_get_table_inst(const WASMModuleInstance *module_inst,
|
||||
const uint32 tbl_idx)
|
||||
{
|
||||
/* careful, it might be a table in another module */
|
||||
WASMTableInstance *tbl_inst = module_inst->tables[tbl_idx];
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (tbl_inst->table_inst_linked) {
|
||||
tbl_inst = tbl_inst->table_inst_linked;
|
||||
}
|
||||
#endif
|
||||
bh_assert(tbl_inst);
|
||||
return tbl_inst;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
void
|
||||
wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env);
|
||||
|
||||
Reference in New Issue
Block a user