Refine Fast JIT accessing memory/table instance and global data (#1623)
Some offsets can be directly gotten at the compilation stage after the interp/AOT module instance refactoring PR was merged, so as to reduce some unnecessary load instructions and improve the Fast JIT performance: - Access fields of wasm memory instance structure - Access fields of wasm table instance structure - Access the global data
This commit is contained in:
@ -459,7 +459,7 @@ jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx,
|
||||
JitReg elem_idx, native_ret, argv, arg_regs[6];
|
||||
JitFrame *jit_frame = cc->jit_frame;
|
||||
JitReg tbl_size, offset, offset_i32;
|
||||
JitReg func_import, func_idx, tbl_data, func_count;
|
||||
JitReg func_import, func_idx, tbl_elems, func_count;
|
||||
JitReg func_type_indexes, func_type_idx, fast_jit_func_ptrs;
|
||||
JitReg offset1_i32, offset1, func_type_idx1, res;
|
||||
JitReg import_func_ptrs, jitted_code_idx, jitted_code;
|
||||
@ -488,8 +488,8 @@ jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx,
|
||||
GEN_INSN(SHL, offset, elem_idx, NEW_CONST(I32, 2));
|
||||
}
|
||||
func_idx = jit_cc_new_reg_I32(cc);
|
||||
tbl_data = get_table_data_reg(jit_frame, tbl_idx);
|
||||
GEN_INSN(LDI32, func_idx, tbl_data, offset);
|
||||
tbl_elems = get_table_elems_reg(jit_frame, tbl_idx);
|
||||
GEN_INSN(LDI32, func_idx, tbl_elems, offset);
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, func_idx, NEW_CONST(I32, -1));
|
||||
if (!jit_emit_exception(cc, EXCE_UNINITIALIZED_ELEMENT, JIT_OP_BEQ,
|
||||
|
||||
@ -136,14 +136,17 @@ check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes)
|
||||
/* ---------- check ---------- */
|
||||
/* 1. shortcut if the memory size is 0 */
|
||||
if (0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) {
|
||||
JitReg memory_inst, cur_mem_page_count;
|
||||
JitReg module_inst, cur_page_count;
|
||||
uint32 cur_page_count_offset =
|
||||
(uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
|
||||
+ (uint32)offsetof(WASMMemoryInstance, cur_page_count);
|
||||
|
||||
/* if (cur_mem_page_count == 0) goto EXCEPTION */
|
||||
memory_inst = get_memory_inst_reg(cc->jit_frame, mem_idx);
|
||||
cur_mem_page_count = jit_cc_new_reg_I32(cc);
|
||||
GEN_INSN(LDI32, cur_mem_page_count, memory_inst,
|
||||
NEW_CONST(I32, offsetof(WASMMemoryInstance, cur_page_count)));
|
||||
GEN_INSN(CMP, cc->cmp_reg, cur_mem_page_count, NEW_CONST(I32, 0));
|
||||
module_inst = get_module_inst_reg(cc->jit_frame);
|
||||
cur_page_count = jit_cc_new_reg_I32(cc);
|
||||
GEN_INSN(LDI32, cur_page_count, module_inst,
|
||||
NEW_CONST(I32, cur_page_count_offset));
|
||||
GEN_INSN(CMP, cc->cmp_reg, cur_page_count, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
JIT_OP_BEQ, cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
@ -493,15 +496,17 @@ fail:
|
||||
bool
|
||||
jit_compile_op_memory_size(JitCompContext *cc, uint32 mem_idx)
|
||||
{
|
||||
JitReg mem_inst, res;
|
||||
JitReg module_inst, cur_page_count;
|
||||
uint32 cur_page_count_offset =
|
||||
(uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
|
||||
+ (uint32)offsetof(WASMMemoryInstance, cur_page_count);
|
||||
|
||||
mem_inst = get_memory_inst_reg(cc->jit_frame, mem_idx);
|
||||
module_inst = get_module_inst_reg(cc->jit_frame);
|
||||
cur_page_count = jit_cc_new_reg_I32(cc);
|
||||
GEN_INSN(LDI32, cur_page_count, module_inst,
|
||||
NEW_CONST(I32, cur_page_count_offset));
|
||||
|
||||
res = jit_cc_new_reg_I32(cc);
|
||||
GEN_INSN(LDI32, res, mem_inst,
|
||||
NEW_CONST(I32, offsetof(WASMMemoryInstance, cur_page_count)));
|
||||
|
||||
PUSH_I32(res);
|
||||
PUSH_I32(cur_page_count);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
@ -511,14 +516,18 @@ fail:
|
||||
bool
|
||||
jit_compile_op_memory_grow(JitCompContext *cc, uint32 mem_idx)
|
||||
{
|
||||
JitReg memory_inst, grow_res, res;
|
||||
JitReg module_inst, grow_res, res;
|
||||
JitReg prev_page_count, inc_page_count, args[2];
|
||||
|
||||
/* Get current page count */
|
||||
memory_inst = get_memory_inst_reg(cc->jit_frame, mem_idx);
|
||||
uint32 cur_page_count_offset =
|
||||
(uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
|
||||
+ (uint32)offsetof(WASMMemoryInstance, cur_page_count);
|
||||
|
||||
module_inst = get_module_inst_reg(cc->jit_frame);
|
||||
prev_page_count = jit_cc_new_reg_I32(cc);
|
||||
GEN_INSN(LDI32, prev_page_count, memory_inst,
|
||||
NEW_CONST(I32, offsetof(WASMMemoryInstance, cur_page_count)));
|
||||
GEN_INSN(LDI32, prev_page_count, module_inst,
|
||||
NEW_CONST(I32, cur_page_count_offset));
|
||||
|
||||
/* Call wasm_enlarge_memory */
|
||||
POP_I32(inc_page_count);
|
||||
|
||||
@ -30,7 +30,7 @@ jit_compile_op_elem_drop(JitCompContext *cc, uint32 tbl_seg_idx)
|
||||
bool
|
||||
jit_compile_op_table_get(JitCompContext *cc, uint32 tbl_idx)
|
||||
{
|
||||
JitReg elem_idx, tbl_sz, tbl_data, elem_idx_long, offset, res;
|
||||
JitReg elem_idx, tbl_sz, tbl_elems, elem_idx_long, offset, res;
|
||||
|
||||
POP_I32(elem_idx);
|
||||
|
||||
@ -48,8 +48,8 @@ jit_compile_op_table_get(JitCompContext *cc, uint32 tbl_idx)
|
||||
GEN_INSN(MUL, offset, elem_idx_long, NEW_CONST(I64, sizeof(uint32)));
|
||||
|
||||
res = jit_cc_new_reg_I32(cc);
|
||||
tbl_data = get_table_data_reg(cc->jit_frame, tbl_idx);
|
||||
GEN_INSN(LDI32, res, tbl_data, offset);
|
||||
tbl_elems = get_table_elems_reg(cc->jit_frame, tbl_idx);
|
||||
GEN_INSN(LDI32, res, tbl_elems, offset);
|
||||
PUSH_I32(res);
|
||||
|
||||
return true;
|
||||
@ -60,7 +60,7 @@ fail:
|
||||
bool
|
||||
jit_compile_op_table_set(JitCompContext *cc, uint32 tbl_idx)
|
||||
{
|
||||
JitReg elem_idx, elem_val, tbl_sz, tbl_data, elem_idx_long, offset;
|
||||
JitReg elem_idx, elem_val, tbl_sz, tbl_elems, elem_idx_long, offset;
|
||||
|
||||
POP_I32(elem_val);
|
||||
POP_I32(elem_idx);
|
||||
@ -78,8 +78,8 @@ jit_compile_op_table_set(JitCompContext *cc, uint32 tbl_idx)
|
||||
offset = jit_cc_new_reg_I64(cc);
|
||||
GEN_INSN(MUL, offset, elem_idx_long, NEW_CONST(I64, sizeof(uint32)));
|
||||
|
||||
tbl_data = get_table_data_reg(cc->jit_frame, tbl_idx);
|
||||
GEN_INSN(STI32, elem_val, tbl_data, offset);
|
||||
tbl_elems = get_table_elems_reg(cc->jit_frame, tbl_idx);
|
||||
GEN_INSN(STI32, elem_val, tbl_elems, offset);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
|
||||
@ -180,15 +180,32 @@ get_global_type(const WASMModule *module, uint32 global_idx)
|
||||
static uint32
|
||||
get_global_data_offset(const WASMModule *module, uint32 global_idx)
|
||||
{
|
||||
uint32 module_inst_struct_size =
|
||||
(uint32)offsetof(WASMModuleInstance, global_table_data.bytes);
|
||||
uint32 mem_inst_size =
|
||||
(uint32)sizeof(WASMMemoryInstance)
|
||||
* (module->import_memory_count + module->memory_count);
|
||||
uint32 global_base_offset;
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
/* If the module dosen't have memory, reserve one mem_info space
|
||||
with empty content to align with llvm jit compiler */
|
||||
if (mem_inst_size == 0)
|
||||
mem_inst_size = (uint32)sizeof(WASMMemoryInstance);
|
||||
#endif
|
||||
|
||||
/* Size of module inst and memory instances */
|
||||
global_base_offset = module_inst_struct_size + mem_inst_size;
|
||||
|
||||
if (global_idx < module->import_global_count) {
|
||||
const WASMGlobalImport *import_global =
|
||||
&((module->import_globals + global_idx)->u.global);
|
||||
return import_global->data_offset;
|
||||
return global_base_offset + import_global->data_offset;
|
||||
}
|
||||
else {
|
||||
const WASMGlobal *global =
|
||||
module->globals + (global_idx - module->import_global_count);
|
||||
return global->data_offset;
|
||||
return global_base_offset + global->data_offset;
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,6 +221,7 @@ jit_compile_op_get_global(JitCompContext *cc, uint32 global_idx)
|
||||
|
||||
data_offset = get_global_data_offset(cc->cur_wasm_module, global_idx);
|
||||
global_type = get_global_type(cc->cur_wasm_module, global_idx);
|
||||
|
||||
switch (global_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
@ -212,28 +230,28 @@ jit_compile_op_get_global(JitCompContext *cc, uint32 global_idx)
|
||||
#endif
|
||||
{
|
||||
value = jit_cc_new_reg_I32(cc);
|
||||
GEN_INSN(LDI32, value, get_global_data_reg(cc->jit_frame),
|
||||
GEN_INSN(LDI32, value, get_module_inst_reg(cc->jit_frame),
|
||||
NEW_CONST(I32, data_offset));
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_I64:
|
||||
{
|
||||
value = jit_cc_new_reg_I64(cc);
|
||||
GEN_INSN(LDI64, value, get_global_data_reg(cc->jit_frame),
|
||||
GEN_INSN(LDI64, value, get_module_inst_reg(cc->jit_frame),
|
||||
NEW_CONST(I32, data_offset));
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F32:
|
||||
{
|
||||
value = jit_cc_new_reg_F32(cc);
|
||||
GEN_INSN(LDF32, value, get_global_data_reg(cc->jit_frame),
|
||||
GEN_INSN(LDF32, value, get_module_inst_reg(cc->jit_frame),
|
||||
NEW_CONST(I32, data_offset));
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F64:
|
||||
{
|
||||
value = jit_cc_new_reg_F64(cc);
|
||||
GEN_INSN(LDF64, value, get_global_data_reg(cc->jit_frame),
|
||||
GEN_INSN(LDF64, value, get_module_inst_reg(cc->jit_frame),
|
||||
NEW_CONST(I32, data_offset));
|
||||
break;
|
||||
}
|
||||
@ -264,6 +282,7 @@ jit_compile_op_set_global(JitCompContext *cc, uint32 global_idx,
|
||||
|
||||
data_offset = get_global_data_offset(cc->cur_wasm_module, global_idx);
|
||||
global_type = get_global_type(cc->cur_wasm_module, global_idx);
|
||||
|
||||
switch (global_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
@ -285,28 +304,28 @@ jit_compile_op_set_global(JitCompContext *cc, uint32 global_idx,
|
||||
JIT_OP_BGTU, cc->cmp_reg, NULL)))
|
||||
goto fail;
|
||||
}
|
||||
GEN_INSN(STI32, value, get_global_data_reg(cc->jit_frame),
|
||||
GEN_INSN(STI32, value, get_module_inst_reg(cc->jit_frame),
|
||||
NEW_CONST(I32, data_offset));
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_I64:
|
||||
{
|
||||
POP_I64(value);
|
||||
GEN_INSN(STI64, value, get_global_data_reg(cc->jit_frame),
|
||||
GEN_INSN(STI64, value, get_module_inst_reg(cc->jit_frame),
|
||||
NEW_CONST(I32, data_offset));
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F32:
|
||||
{
|
||||
POP_F32(value);
|
||||
GEN_INSN(STF32, value, get_global_data_reg(cc->jit_frame),
|
||||
GEN_INSN(STF32, value, get_module_inst_reg(cc->jit_frame),
|
||||
NEW_CONST(I32, data_offset));
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F64:
|
||||
{
|
||||
POP_F64(value);
|
||||
GEN_INSN(STF64, value, get_global_data_reg(cc->jit_frame),
|
||||
GEN_INSN(STF64, value, get_module_inst_reg(cc->jit_frame),
|
||||
NEW_CONST(I32, data_offset));
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user