Implement interpreter hw bound check (#1309)

Implement boundary check with hardware trap for interpreter on
64-bit platforms:
- To improve the performance of interpreter and Fast JIT
- To prepare for multi-tier compilation for the feature

Linux/MacOS/Windows 64-bit are enabled.
This commit is contained in:
Wenyong Huang
2022-07-22 11:05:40 +08:00
committed by GitHub
parent 32c94161d1
commit fd5030e02e
8 changed files with 591 additions and 101 deletions

View File

@ -24,6 +24,7 @@ typedef float64 CellType_F64;
#define BR_TABLE_TMP_BUF_LEN 32
#ifndef OS_ENABLE_HW_BOUND_CHECK
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
@ -45,6 +46,18 @@ typedef float64 CellType_F64;
else \
goto out_of_bounds; \
} while (0)
#else
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
maddr = memory->memory_data + offset1; \
} while (0)
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
do { \
maddr = memory->memory_data + (uint32)(start); \
} while (0)
#endif
#define CHECK_ATOMIC_MEMORY_ACCESS() \
do { \
@ -1006,10 +1019,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMInterpFrame *prev_frame)
{
WASMMemoryInstance *memory = module->default_memory;
uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0;
uint8 *global_data = module->global_data;
#ifndef OS_ENABLE_HW_BOUND_CHECK
uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0;
uint32 linear_mem_size =
memory ? num_bytes_per_page * memory->cur_page_count : 0;
#endif
WASMType **wasm_types = module->module->types;
WASMGlobalInstance *globals = module->globals, *global;
uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
@ -1959,8 +1974,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
PUSH_I32(prev_page_count);
/* update memory instance ptr and memory size */
memory = module->default_memory;
#ifndef OS_ENABLE_HW_BOUND_CHECK
linear_mem_size =
num_bytes_per_page * memory->cur_page_count;
#endif
}
(void)reserved;
@ -2988,11 +3005,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
seg_len = (uint64)module->module->data_segments[segment]
->data_length;
data = module->module->data_segments[segment]->data;
#ifndef OS_ENABLE_HW_BOUND_CHECK
if (offset + bytes > seg_len)
goto out_of_bounds;
bh_memcpy_s(maddr, linear_mem_size - addr,
data + offset, (uint32)bytes);
#else
bh_memcpy_s(maddr, (uint32)bytes, data + offset,
(uint32)bytes);
#endif
break;
}
case WASM_OP_DATA_DROP:
@ -3019,8 +3041,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
/* allowing the destination and source to overlap */
#ifndef OS_ENABLE_HW_BOUND_CHECK
bh_memmove_s(mdst, linear_mem_size - dst, msrc, len);
#else
bh_memmove_s(mdst, len, msrc, len);
#endif
break;
}
case WASM_OP_MEMORY_FILL:
@ -3681,8 +3706,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* update memory instance ptr and memory size */
memory = module->default_memory;
#ifndef OS_ENABLE_HW_BOUND_CHECK
if (memory)
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
#endif
if (wasm_get_exception(module))
goto got_exception;
}
@ -3759,8 +3786,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
goto got_exception;
#endif
#ifndef OS_ENABLE_HW_BOUND_CHECK
out_of_bounds:
wasm_set_exception(module, "out of bounds memory access");
#endif
got_exception:
#if WASM_ENABLE_DEBUG_INTERP != 0
@ -3808,11 +3837,13 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
}
argc = function->param_cell_num;
#ifndef OS_ENABLE_HW_BOUND_CHECK
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
"native stack overflow");
return;
}
#endif
if (!(frame =
ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame *)prev_frame)))