Refine read leb int wasm loader of fast interpreter (#4017)

This commit is contained in:
Wenyong Huang
2025-01-14 17:43:29 +08:00
committed by GitHub
parent 946430f15e
commit 9c3807e124
2 changed files with 262 additions and 102 deletions

View File

@ -6048,6 +6048,86 @@ fail:
} \
} while (0)
#if WASM_ENABLE_FAST_INTERP == 0
#define pb_read_leb_uint32 read_leb_uint32
#define pb_read_leb_int32 read_leb_int32
#define pb_read_leb_int64 read_leb_int64
#define pb_read_leb_memarg read_leb_memarg
#define pb_read_leb_mem_offset read_leb_mem_offset
#define pb_read_leb_memidx read_leb_memidx
#else
/* Read leb without malformed format check */
static uint64
read_leb_quick(uint8 **p_buf, uint32 maxbits, bool sign)
{
uint8 *buf = *p_buf;
uint64 result = 0, byte = 0;
uint32 shift = 0;
do {
byte = *buf++;
result |= ((byte & 0x7f) << shift);
shift += 7;
} while (byte & 0x80);
if (sign && (shift < maxbits) && (byte & 0x40)) {
/* Sign extend */
result |= (~((uint64)0)) << shift;
}
*p_buf = buf;
return result;
}
#define pb_read_leb_uint32(p, p_end, res) \
do { \
if (!loader_ctx->p_code_compiled) \
/* Enable format check in the first scan */ \
read_leb_uint32(p, p_end, res); \
else \
/* Disable format check in the second scan */ \
res = (uint32)read_leb_quick(&p, 32, false); \
} while (0)
#define pb_read_leb_int32(p, p_end, res) \
do { \
if (!loader_ctx->p_code_compiled) \
/* Enable format check in the first scan */ \
read_leb_int32(p, p_end, res); \
else \
/* Disable format check in the second scan */ \
res = (int32)read_leb_quick(&p, 32, true); \
} while (0)
#define pb_read_leb_int64(p, p_end, res) \
do { \
if (!loader_ctx->p_code_compiled) \
/* Enable format check in the first scan */ \
read_leb_int64(p, p_end, res); \
else \
/* Disable format check in the second scan */ \
res = (int64)read_leb_quick(&p, 64, true); \
} while (0)
#if WASM_ENABLE_MULTI_MEMORY != 0
#define pb_read_leb_memarg read_leb_memarg
#else
#define pb_read_leb_memarg pb_read_leb_uint32
#endif
#if WASM_ENABLE_MEMORY64 != 0
#define pb_read_leb_mem_offset read_leb_mem_offset
#else
#define pb_read_leb_mem_offset pb_read_leb_uint32
#endif
#define pb_read_leb_memidx pb_read_leb_uint32
#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */
static bool
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
uint32 cur_func_idx, char *error_buf,
@ -6195,7 +6275,7 @@ re_scan:
int32 type_index;
/* Resolve the leb128 encoded type index as block type */
p--;
read_leb_int32(p, p_end, type_index);
pb_read_leb_int32(p, p_end, type_index);
bh_assert((uint32)type_index < module->type_count);
block_type.is_value_type = false;
block_type.u.type = module->types[type_index];
@ -6508,7 +6588,7 @@ re_scan:
uint32 j;
#endif
read_leb_uint32(p, p_end, count);
pb_read_leb_uint32(p, p_end, count);
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, count);
#endif
@ -6517,7 +6597,7 @@ re_scan:
/* Get each depth and check it */
p_org = p;
for (i = 0; i <= count; i++) {
read_leb_uint32(p, p_end, depth);
pb_read_leb_uint32(p, p_end, depth);
bh_assert(loader_ctx->csp_num > 0);
bh_assert(loader_ctx->csp_num - 1 >= depth);
(void)depth;
@ -6615,7 +6695,7 @@ re_scan:
uint32 func_idx;
int32 idx;
read_leb_uint32(p, p_end, func_idx);
pb_read_leb_uint32(p, p_end, func_idx);
#if WASM_ENABLE_FAST_INTERP != 0
/* we need to emit func_idx before arguments */
emit_uint32(loader_ctx, func_idx);
@ -6688,10 +6768,10 @@ re_scan:
bh_assert(module->import_table_count + module->table_count > 0);
read_leb_uint32(p, p_end, type_idx);
pb_read_leb_uint32(p, p_end, type_idx);
#if WASM_ENABLE_REF_TYPES != 0
read_leb_uint32(p, p_end, table_idx);
pb_read_leb_uint32(p, p_end, table_idx);
#else
CHECK_BUF(p, p_end, 1);
table_idx = read_uint8(p);
@ -6931,7 +7011,7 @@ re_scan:
uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled;
#endif
read_leb_uint32(p, p_end, vec_len);
pb_read_leb_uint32(p, p_end, vec_len);
if (vec_len != 1) {
/* typed select must have exactly one result */
set_error_buf(error_buf, error_buf_size,
@ -7006,7 +7086,7 @@ re_scan:
uint8 decl_ref_type;
uint32 table_idx;
read_leb_uint32(p, p_end, table_idx);
pb_read_leb_uint32(p, p_end, table_idx);
if (!get_table_elem_type(module, table_idx, &decl_ref_type,
error_buf, error_buf_size))
goto fail;
@ -7100,7 +7180,7 @@ re_scan:
case WASM_OP_REF_FUNC:
{
uint32 func_idx = 0;
read_leb_uint32(p, p_end, func_idx);
pb_read_leb_uint32(p, p_end, func_idx);
if (!check_function_index(module, func_idx, error_buf,
error_buf_size)) {
@ -7317,7 +7397,7 @@ re_scan:
case WASM_OP_GET_GLOBAL:
{
p_org = p - 1;
read_leb_uint32(p, p_end, global_idx);
pb_read_leb_uint32(p, p_end, global_idx);
bh_assert(global_idx < global_count);
global_type = global_idx < module->import_global_count
@ -7351,7 +7431,7 @@ re_scan:
bool is_mutable = false;
p_org = p - 1;
read_leb_uint32(p, p_end, global_idx);
pb_read_leb_uint32(p, p_end, global_idx);
bh_assert(global_idx < global_count);
is_mutable = global_idx < module->import_global_count
@ -7448,8 +7528,8 @@ re_scan:
}
#endif
CHECK_MEMORY();
read_leb_memarg(p, p_end, align); /* align */
read_leb_mem_offset(p, p_end, mem_offset); /* offset */
pb_read_leb_memarg(p, p_end, align); /* align */
pb_read_leb_mem_offset(p, p_end, mem_offset); /* offset */
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, mem_offset);
#endif
@ -7510,7 +7590,7 @@ re_scan:
case WASM_OP_MEMORY_SIZE:
CHECK_MEMORY();
read_leb_memidx(p, p_end, memidx);
pb_read_leb_memidx(p, p_end, memidx);
check_memidx(module, memidx);
PUSH_PAGE_COUNT();
@ -7522,7 +7602,7 @@ re_scan:
case WASM_OP_MEMORY_GROW:
CHECK_MEMORY();
read_leb_memidx(p, p_end, memidx);
pb_read_leb_memidx(p, p_end, memidx);
check_memidx(module, memidx);
POP_AND_PUSH(mem_offset_type, mem_offset_type);
@ -7537,7 +7617,7 @@ re_scan:
break;
case WASM_OP_I32_CONST:
read_leb_int32(p, p_end, i32_const);
pb_read_leb_int32(p, p_end, i32_const);
#if WASM_ENABLE_FAST_INTERP != 0
skip_label();
disable_emit = true;
@ -7555,7 +7635,7 @@ re_scan:
break;
case WASM_OP_I64_CONST:
read_leb_int64(p, p_end, i64_const);
pb_read_leb_int64(p, p_end, i64_const);
#if WASM_ENABLE_FAST_INTERP != 0
skip_label();
disable_emit = true;
@ -7837,7 +7917,7 @@ re_scan:
{
uint32 opcode1;
read_leb_uint32(p, p_end, opcode1);
pb_read_leb_uint32(p, p_end, opcode1);
#if WASM_ENABLE_FAST_INTERP != 0
emit_byte(loader_ctx, ((uint8)opcode1));
#endif
@ -7862,11 +7942,11 @@ re_scan:
case WASM_OP_MEMORY_INIT:
{
CHECK_MEMORY();
read_leb_uint32(p, p_end, segment_index);
pb_read_leb_uint32(p, p_end, segment_index);
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, segment_index);
#endif
read_leb_memidx(p, p_end, memidx);
pb_read_leb_memidx(p, p_end, memidx);
check_memidx(module, memidx);
bh_assert(segment_index < module->data_seg_count);
@ -7882,7 +7962,7 @@ re_scan:
}
case WASM_OP_DATA_DROP:
{
read_leb_uint32(p, p_end, segment_index);
pb_read_leb_uint32(p, p_end, segment_index);
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, segment_index);
#endif
@ -7898,9 +7978,9 @@ re_scan:
CHECK_MEMORY();
CHECK_BUF(p, p_end, sizeof(int16));
/* check both src and dst memory index */
read_leb_memidx(p, p_end, memidx);
pb_read_leb_memidx(p, p_end, memidx);
check_memidx(module, memidx);
read_leb_memidx(p, p_end, memidx);
pb_read_leb_memidx(p, p_end, memidx);
check_memidx(module, memidx);
POP_MEM_OFFSET();
@ -7914,7 +7994,7 @@ re_scan:
case WASM_OP_MEMORY_FILL:
{
CHECK_MEMORY();
read_leb_memidx(p, p_end, memidx);
pb_read_leb_memidx(p, p_end, memidx);
check_memidx(module, memidx);
POP_MEM_OFFSET();
@ -7932,8 +8012,8 @@ re_scan:
uint8 seg_ref_type, tbl_ref_type;
uint32 table_seg_idx, table_idx;
read_leb_uint32(p, p_end, table_seg_idx);
read_leb_uint32(p, p_end, table_idx);
pb_read_leb_uint32(p, p_end, table_seg_idx);
pb_read_leb_uint32(p, p_end, table_idx);
if (!get_table_elem_type(module, table_idx,
&tbl_ref_type, error_buf,
@ -7968,7 +8048,7 @@ re_scan:
case WASM_OP_ELEM_DROP:
{
uint32 table_seg_idx;
read_leb_uint32(p, p_end, table_seg_idx);
pb_read_leb_uint32(p, p_end, table_seg_idx);
if (!get_table_seg_elem_type(module, table_seg_idx,
NULL, error_buf,
error_buf_size))
@ -7984,13 +8064,13 @@ re_scan:
uint32 src_tbl_idx, dst_tbl_idx, src_tbl_idx_type,
dst_tbl_idx_type, min_tbl_idx_type;
read_leb_uint32(p, p_end, src_tbl_idx);
pb_read_leb_uint32(p, p_end, src_tbl_idx);
if (!get_table_elem_type(module, src_tbl_idx,
&src_ref_type, error_buf,
error_buf_size))
goto fail;
read_leb_uint32(p, p_end, dst_tbl_idx);
pb_read_leb_uint32(p, p_end, dst_tbl_idx);
if (!get_table_elem_type(module, dst_tbl_idx,
&dst_ref_type, error_buf,
error_buf_size))
@ -8037,7 +8117,7 @@ re_scan:
{
uint32 table_idx;
read_leb_uint32(p, p_end, table_idx);
pb_read_leb_uint32(p, p_end, table_idx);
/* TODO: shall we create a new function to check
table idx instead of using below function? */
if (!get_table_elem_type(module, table_idx, NULL,
@ -8062,7 +8142,7 @@ re_scan:
uint8 decl_ref_type;
uint32 table_idx;
read_leb_uint32(p, p_end, table_idx);
pb_read_leb_uint32(p, p_end, table_idx);
if (!get_table_elem_type(module, table_idx,
&decl_ref_type, error_buf,
error_buf_size))
@ -8114,15 +8194,15 @@ re_scan:
{
uint32 opcode1;
read_leb_uint32(p, p_end, opcode1);
pb_read_leb_uint32(p, p_end, opcode1);
#if WASM_ENABLE_FAST_INTERP != 0
emit_byte(loader_ctx, opcode1);
#endif
if (opcode1 != WASM_OP_ATOMIC_FENCE) {
CHECK_MEMORY();
read_leb_uint32(p, p_end, align); /* align */
read_leb_mem_offset(p, p_end, mem_offset); /* offset */
pb_read_leb_uint32(p, p_end, align); /* align */
pb_read_leb_mem_offset(p, p_end, mem_offset); /* offset */
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, mem_offset);
#endif