mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-15 08:48:33 +00:00
Refine fe translate op br_if and br_table (#1263)
Refine fast jit frontend translation of opcode br_if and br_table: for br_if, no need to clear jit frame after handling new basic block, so as to re-use registers of current basic block, for br_table, no need to create a new basic block to jump if there is no parameters/results to copy to new block, just jumping to current existing basic block.
This commit is contained in:
parent
a9658c245f
commit
9c2bdd1b83
|
@ -449,9 +449,24 @@ handle_op_end(JitCompContext *cc, uint8 **p_frame_ip, bool is_block_polymorphic)
|
||||||
incoming_insn = block->incoming_insns_for_end_bb;
|
incoming_insn = block->incoming_insns_for_end_bb;
|
||||||
while (incoming_insn) {
|
while (incoming_insn) {
|
||||||
insn = incoming_insn->insn;
|
insn = incoming_insn->insn;
|
||||||
bh_assert(insn->opcode == JIT_OP_JMP || insn->opcode == JIT_OP_BNE);
|
bh_assert(insn->opcode == JIT_OP_JMP || insn->opcode == JIT_OP_BNE
|
||||||
*(jit_insn_opnd(insn, incoming_insn->opnd_idx)) =
|
|| insn->opcode == JIT_OP_LOOKUPSWITCH);
|
||||||
jit_basic_block_label(block->basic_block_end);
|
if (insn->opcode == JIT_OP_JMP || insn->opcode == JIT_OP_BNE) {
|
||||||
|
*(jit_insn_opnd(insn, incoming_insn->opnd_idx)) =
|
||||||
|
jit_basic_block_label(block->basic_block_end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Patch LOOKUPSWITCH INSN */
|
||||||
|
JitOpndLookupSwitch *opnd = jit_insn_opndls(insn);
|
||||||
|
if (incoming_insn->opnd_idx < opnd->match_pairs_num) {
|
||||||
|
opnd->match_pairs[incoming_insn->opnd_idx].target =
|
||||||
|
jit_basic_block_label(block->basic_block_end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opnd->default_target =
|
||||||
|
jit_basic_block_label(block->basic_block_end);
|
||||||
|
}
|
||||||
|
}
|
||||||
incoming_insn = incoming_insn->next;
|
incoming_insn = incoming_insn->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,13 +750,41 @@ jit_compile_op_end(JitCompContext *cc, uint8 **p_frame_ip)
|
||||||
return handle_op_end(cc, p_frame_ip, false);
|
return handle_op_end(cc, p_frame_ip, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether need to copy arities when jumping from current block
|
||||||
|
to the dest block */
|
||||||
|
static bool
|
||||||
|
check_copy_arities(const JitBlock *block_dst, JitFrame *jit_frame)
|
||||||
|
{
|
||||||
|
JitValueSlot *frame_sp_src = NULL;
|
||||||
|
|
||||||
|
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
||||||
|
frame_sp_src =
|
||||||
|
jit_frame->sp
|
||||||
|
- wasm_get_cell_num(block_dst->param_types, block_dst->param_count);
|
||||||
|
/* There are parameters to copy and the src/dst addr are different */
|
||||||
|
return (block_dst->param_count > 0
|
||||||
|
&& block_dst->frame_sp_begin != frame_sp_src)
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
frame_sp_src = jit_frame->sp
|
||||||
|
- wasm_get_cell_num(block_dst->result_types,
|
||||||
|
block_dst->result_count);
|
||||||
|
/* There are results to copy and the src/dst addr are different */
|
||||||
|
return (block_dst->result_count > 0
|
||||||
|
&& block_dst->frame_sp_begin != frame_sp_src)
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
handle_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
|
handle_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
|
||||||
{
|
{
|
||||||
JitFrame *jit_frame;
|
JitFrame *jit_frame;
|
||||||
JitBlock *block_dst, *block;
|
JitBlock *block_dst, *block;
|
||||||
JitReg frame_sp_dst;
|
JitReg frame_sp_dst;
|
||||||
JitValueSlot *frame_sp_src = NULL;
|
|
||||||
JitInsn *insn;
|
JitInsn *insn;
|
||||||
bool copy_arities;
|
bool copy_arities;
|
||||||
uint32 offset;
|
uint32 offset;
|
||||||
|
@ -758,19 +801,9 @@ handle_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
|
||||||
|
|
||||||
jit_frame = cc->jit_frame;
|
jit_frame = cc->jit_frame;
|
||||||
|
|
||||||
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
/* Only opy parameters or results when their count > 0 and
|
||||||
frame_sp_src =
|
the src/dst addr are different */
|
||||||
jit_frame->sp
|
copy_arities = check_copy_arities(block_dst, jit_frame);
|
||||||
- wasm_get_cell_num(block_dst->param_types, block_dst->param_count);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
frame_sp_src = jit_frame->sp
|
|
||||||
- wasm_get_cell_num(block_dst->result_types,
|
|
||||||
block_dst->result_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only copy parameters or results when the src/dst addr are different */
|
|
||||||
copy_arities = (block_dst->frame_sp_begin != frame_sp_src) ? true : false;
|
|
||||||
|
|
||||||
if (copy_arities) {
|
if (copy_arities) {
|
||||||
frame_sp_dst = jit_cc_new_reg_ptr(cc);
|
frame_sp_dst = jit_cc_new_reg_ptr(cc);
|
||||||
|
@ -832,15 +865,51 @@ jit_compile_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
|
||||||
&& handle_next_reachable_block(cc, p_frame_ip);
|
&& handle_next_reachable_block(cc, p_frame_ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JitFrame *
|
||||||
|
jit_frame_clone(const JitFrame *jit_frame)
|
||||||
|
{
|
||||||
|
JitFrame *jit_frame_cloned;
|
||||||
|
uint32 max_locals = jit_frame->max_locals;
|
||||||
|
uint32 max_stacks = jit_frame->max_stacks;
|
||||||
|
uint32 total_size;
|
||||||
|
|
||||||
|
total_size = (uint32)(offsetof(JitFrame, lp)
|
||||||
|
+ sizeof(*jit_frame->lp) * (max_locals + max_stacks));
|
||||||
|
|
||||||
|
jit_frame_cloned = jit_calloc(total_size);
|
||||||
|
if (jit_frame_cloned) {
|
||||||
|
bh_memcpy_s(jit_frame_cloned, total_size, jit_frame, total_size);
|
||||||
|
jit_frame_cloned->sp =
|
||||||
|
jit_frame_cloned->lp + (jit_frame->sp - jit_frame->lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jit_frame_cloned;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
jit_frame_copy(JitFrame *jit_frame_dst, const JitFrame *jit_frame_src)
|
||||||
|
{
|
||||||
|
uint32 max_locals = jit_frame_src->max_locals;
|
||||||
|
uint32 max_stacks = jit_frame_src->max_stacks;
|
||||||
|
uint32 total_size;
|
||||||
|
|
||||||
|
total_size =
|
||||||
|
(uint32)(offsetof(JitFrame, lp)
|
||||||
|
+ sizeof(*jit_frame_src->lp) * (max_locals + max_stacks));
|
||||||
|
bh_memcpy_s(jit_frame_dst, total_size, jit_frame_src, total_size);
|
||||||
|
jit_frame_dst->sp =
|
||||||
|
jit_frame_dst->lp + (jit_frame_src->sp - jit_frame_src->lp);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
|
jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
|
||||||
{
|
{
|
||||||
JitFrame *jit_frame;
|
JitFrame *jit_frame, *jit_frame_cloned;
|
||||||
JitBlock *block_dst;
|
JitBlock *block_dst;
|
||||||
JitReg cond;
|
JitReg cond;
|
||||||
JitBasicBlock *cur_basic_block, *if_basic_block = NULL;
|
JitBasicBlock *cur_basic_block, *if_basic_block = NULL;
|
||||||
JitValueSlot *frame_sp_src;
|
|
||||||
JitInsn *insn;
|
JitInsn *insn;
|
||||||
|
bool copy_arities;
|
||||||
|
|
||||||
if (!(block_dst = get_target_block(cc, br_depth))) {
|
if (!(block_dst = get_target_block(cc, br_depth))) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -853,18 +922,11 @@ jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
|
||||||
cur_basic_block = cc->cur_basic_block;
|
cur_basic_block = cc->cur_basic_block;
|
||||||
gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
|
gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
|
||||||
|
|
||||||
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
/* Only opy parameters or results when their count > 0 and
|
||||||
frame_sp_src =
|
the src/dst addr are different */
|
||||||
jit_frame->sp
|
copy_arities = check_copy_arities(block_dst, jit_frame);
|
||||||
- wasm_get_cell_num(block_dst->param_types, block_dst->param_count);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
frame_sp_src = jit_frame->sp
|
|
||||||
- wasm_get_cell_num(block_dst->result_types,
|
|
||||||
block_dst->result_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block_dst->frame_sp_begin == frame_sp_src) {
|
if (!copy_arities) {
|
||||||
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
||||||
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))
|
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))
|
||||||
|| !GEN_INSN(
|
|| !GEN_INSN(
|
||||||
|
@ -899,11 +961,26 @@ jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
|
||||||
SET_BUILDER_POS(if_basic_block);
|
SET_BUILDER_POS(if_basic_block);
|
||||||
SET_BB_BEGIN_BCIP(if_basic_block, *p_frame_ip - 1);
|
SET_BB_BEGIN_BCIP(if_basic_block, *p_frame_ip - 1);
|
||||||
|
|
||||||
clear_values(cc->jit_frame);
|
/* Clone current jit frame to a new jit fame */
|
||||||
if (!handle_op_br(cc, br_depth, p_frame_ip))
|
if (!(jit_frame_cloned = jit_frame_clone(jit_frame))) {
|
||||||
|
jit_set_last_error(cc, "allocate memory failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* continue processing opcodes after BR_IF */
|
/* Clear current jit frame so that the registers
|
||||||
|
in the new basic block will be loaded again */
|
||||||
|
clear_values(jit_frame);
|
||||||
|
if (!handle_op_br(cc, br_depth, p_frame_ip)) {
|
||||||
|
jit_free(jit_frame_cloned);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore the jit frame so that the registers can
|
||||||
|
be used again in current basic block */
|
||||||
|
jit_frame_copy(jit_frame, jit_frame_cloned);
|
||||||
|
jit_free(jit_frame_cloned);
|
||||||
|
|
||||||
|
/* Continue processing opcodes after BR_IF */
|
||||||
SET_BUILDER_POS(cur_basic_block);
|
SET_BUILDER_POS(cur_basic_block);
|
||||||
return true;
|
return true;
|
||||||
fail:
|
fail:
|
||||||
|
@ -939,9 +1016,51 @@ jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count,
|
||||||
|
|
||||||
for (i = 0, opnd = jit_insn_opndls(insn); i < br_count + 1; i++) {
|
for (i = 0, opnd = jit_insn_opndls(insn); i < br_count + 1; i++) {
|
||||||
JitBasicBlock *basic_block = NULL;
|
JitBasicBlock *basic_block = NULL;
|
||||||
|
JitBlock *block_dst;
|
||||||
|
bool copy_arities;
|
||||||
|
|
||||||
/* TODO: refine the code */
|
if (!(block_dst = get_target_block(cc, br_depths[i]))) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only opy parameters or results when their count > 0 and
|
||||||
|
the src/dst addr are different */
|
||||||
|
copy_arities = check_copy_arities(block_dst, cc->jit_frame);
|
||||||
|
|
||||||
|
if (!copy_arities) {
|
||||||
|
/* No need to create new basic block, direclty jump to
|
||||||
|
the existing basic block when no need to copy arities */
|
||||||
|
if (i == br_count) {
|
||||||
|
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
||||||
|
opnd->default_target =
|
||||||
|
jit_basic_block_label(block_dst->basic_block_entry);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bh_assert(!block_dst->basic_block_end);
|
||||||
|
if (!jit_block_add_incoming_insn(block_dst, insn, i)) {
|
||||||
|
jit_set_last_error(cc, "add incoming insn failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opnd->match_pairs[i].value = i;
|
||||||
|
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
||||||
|
opnd->match_pairs[i].target =
|
||||||
|
jit_basic_block_label(block_dst->basic_block_entry);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bh_assert(!block_dst->basic_block_end);
|
||||||
|
if (!jit_block_add_incoming_insn(block_dst, insn, i)) {
|
||||||
|
jit_set_last_error(cc, "add incoming insn failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create new basic block when need to copy arities */
|
||||||
CREATE_BASIC_BLOCK(basic_block);
|
CREATE_BASIC_BLOCK(basic_block);
|
||||||
SET_BB_BEGIN_BCIP(basic_block, *p_frame_ip - 1);
|
SET_BB_BEGIN_BCIP(basic_block, *p_frame_ip - 1);
|
||||||
|
|
||||||
|
@ -959,7 +1078,7 @@ jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go to next aviable block */
|
/* Search next available block to handle */
|
||||||
return handle_next_reachable_block(cc, p_frame_ip);
|
return handle_next_reachable_block(cc, p_frame_ip);
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user