Merge pull request #577 from bytecodealliance/dev/fast_jit

Refine fast jit backend translation of IR lookupswitch (#1264)
This commit is contained in:
Wenyong Huang 2022-07-08 12:37:10 +08:00 committed by GitHub
commit 8dc9520f75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -278,8 +278,10 @@ local_log2l(uint64 data)
/* Jmp type */ /* Jmp type */
typedef enum JmpType { typedef enum JmpType {
JMP_DST_LABEL, /* jmp to dst label */ JMP_DST_LABEL_REL, /* jmp to dst label with relative addr */
JMP_END_OF_CALLBC, /* jmp to end of CALLBC */ JMP_DST_LABEL_ABS, /* jmp to dst label with absolute addr */
JMP_END_OF_CALLBC, /* jmp to end of CALLBC */
JMP_LOOKUPSWITCH_BASE, /* LookupSwitch table base addr */
} JmpType; } JmpType;
/** /**
@ -336,7 +338,7 @@ jmp_from_label_to_label(x86::Assembler &a, bh_list *jmp_info_list,
if (!node) if (!node)
return false; return false;
node->type = JMP_DST_LABEL; node->type = JMP_DST_LABEL_REL;
node->label_src = label_src; node->label_src = label_src;
node->dst_info.label_dst = label_dst; node->dst_info.label_dst = label_dst;
node->offset = a.code()->sectionById(0)->buffer().size() + 2; node->offset = a.code()->sectionById(0)->buffer().size() + 2;
@ -373,7 +375,7 @@ cmp_r_and_jmp_label(JitCompContext *cc, x86::Assembler &a,
if (!node) if (!node)
return false; return false;
node->type = JMP_DST_LABEL; node->type = JMP_DST_LABEL_REL;
node->label_src = label_src; node->label_src = label_src;
node->dst_info.label_dst = jit_reg_no(r1); node->dst_info.label_dst = jit_reg_no(r1);
node->offset = a.code()->sectionById(0)->buffer().size() + 2; node->offset = a.code()->sectionById(0)->buffer().size() + 2;
@ -5446,33 +5448,95 @@ lookupswitch_r(JitCompContext *cc, x86::Assembler &a, bh_list *jmp_info_list,
{ {
JmpInfo *node; JmpInfo *node;
Imm imm; Imm imm;
x86::Mem m;
uint32 i; uint32 i;
int32 label_dst; int32 label_dst = 0;
char *stream;
for (i = 0; i < opnd->match_pairs_num; i++) { if (opnd->match_pairs_num < 10) {
imm.setValue(opnd->match_pairs[i].value); /* For small count of branches, it is better to compare
a.cmp(regs_i32[reg_no], imm); the key with branch value and jump one by one */
for (i = 0; i < opnd->match_pairs_num; i++) {
imm.setValue(opnd->match_pairs[i].value);
a.cmp(regs_i32[reg_no], imm);
label_dst = jit_reg_no(opnd->match_pairs[i].target); node = (JmpInfo *)jit_malloc(sizeof(JmpInfo));
imm.setValue(label_dst); if (!node)
GOTO_FAIL;
node->type = JMP_DST_LABEL_REL;
node->label_src = label_src;
node->dst_info.label_dst = jit_reg_no(opnd->match_pairs[i].target);
node->offset = a.code()->sectionById(0)->buffer().size() + 2;
bh_list_insert(jmp_info_list, node);
imm.setValue(INT32_MAX);
a.je(imm);
}
if (opnd->default_target) {
label_dst = jit_reg_no(opnd->default_target);
if (!(is_last_insn
&& label_is_neighboring(cc, label_src, label_dst)))
JMP_TO_LABEL(label_dst, label_src);
}
}
else {
/* For bigger count of branches, use indirect jump */
/* unsigned extend to rsi */
a.mov(regs_i32[REG_I32_FREE_IDX], regs_i32[reg_no]);
imm.setValue(opnd->match_pairs_num);
a.cmp(regs_i64[REG_I64_FREE_IDX], imm);
/* Jump to default label if rsi >= br_count */
stream = (char *)a.code()->sectionById(0)->buffer().data()
+ a.code()->sectionById(0)->buffer().size();
imm.setValue(INT32_MAX);
a.jb(imm);
*(uint32 *)(stream + 2) = 6;
node = (JmpInfo *)jit_calloc(sizeof(JmpInfo));
if (!node)
goto fail;
node->type = JMP_DST_LABEL_REL;
node->label_src = label_src;
node->dst_info.label_dst = jit_reg_no(opnd->default_target);
node->offset = a.code()->sectionById(0)->buffer().size() + 2;
bh_list_insert(jmp_info_list, node);
imm.setValue(INT32_MAX);
a.jmp(imm);
node = (JmpInfo *)jit_malloc(sizeof(JmpInfo)); node = (JmpInfo *)jit_malloc(sizeof(JmpInfo));
if (!node) if (!node)
GOTO_FAIL; GOTO_FAIL;
node->type = JMP_DST_LABEL; node->type = JMP_LOOKUPSWITCH_BASE;
node->label_src = label_src;
node->dst_info.label_dst = label_dst;
node->offset = a.code()->sectionById(0)->buffer().size() + 2; node->offset = a.code()->sectionById(0)->buffer().size() + 2;
bh_list_insert(jmp_info_list, node); bh_list_insert(jmp_info_list, node);
a.je(imm); /* LookupSwitch table base addr */
} imm.setValue(INT64_MAX);
a.mov(regs_i64[reg_no], imm);
if (opnd->default_target) { /* jmp *(base_addr + rsi * 8) */
label_dst = jit_reg_no(opnd->default_target); m = x86::ptr(regs_i64[reg_no], regs_i64[REG_I64_FREE_IDX], 3);
if (!(is_last_insn && label_is_neighboring(cc, label_src, label_dst))) a.jmp(m);
JMP_TO_LABEL(label_dst, label_src);
/* Store each dst label absolute address */
for (i = 0; i < opnd->match_pairs_num; i++) {
node = (JmpInfo *)jit_malloc(sizeof(JmpInfo));
if (!node)
GOTO_FAIL;
node->type = JMP_DST_LABEL_ABS;
node->dst_info.label_dst = jit_reg_no(opnd->match_pairs[i].target);
node->offset = a.code()->sectionById(0)->buffer().size();
bh_list_insert(jmp_info_list, node);
a.embedUInt64(UINT64_MAX);
}
} }
return true; return true;
@ -5806,7 +5870,8 @@ patch_jmp_info_list(JitCompContext *cc, bh_list *jmp_info_list)
stream = (char *)cc->jitted_addr_begin + jmp_info->offset; stream = (char *)cc->jitted_addr_begin + jmp_info->offset;
if (jmp_info->type == JMP_DST_LABEL) { if (jmp_info->type == JMP_DST_LABEL_REL) {
/* Jmp with relative address */
reg_dst = reg_dst =
jit_reg_new(JIT_REG_KIND_L32, jmp_info->dst_info.label_dst); jit_reg_new(JIT_REG_KIND_L32, jmp_info->dst_info.label_dst);
*(int32 *)stream = *(int32 *)stream =
@ -5814,10 +5879,21 @@ patch_jmp_info_list(JitCompContext *cc, bh_list *jmp_info_list)
- (uintptr_t)stream) - (uintptr_t)stream)
- 4; - 4;
} }
else if (jmp_info->type == JMP_DST_LABEL_ABS) {
/* Jmp with absolute address */
reg_dst =
jit_reg_new(JIT_REG_KIND_L32, jmp_info->dst_info.label_dst);
*(uintptr_t *)stream =
(uintptr_t)*jit_annl_jitted_addr(cc, reg_dst);
}
else if (jmp_info->type == JMP_END_OF_CALLBC) { else if (jmp_info->type == JMP_END_OF_CALLBC) {
/* 7 is the size of mov and jmp instruction */ /* 7 is the size of mov and jmp instruction */
*(uintptr_t *)stream = (uintptr_t)stream + sizeof(uintptr_t) + 7; *(uintptr_t *)stream = (uintptr_t)stream + sizeof(uintptr_t) + 7;
} }
else if (jmp_info->type == JMP_LOOKUPSWITCH_BASE) {
/* 11 is the size of 8-byte addr and 3-byte jmp instruction */
*(uintptr_t *)stream = (uintptr_t)stream + 11;
}
jmp_info = jmp_info_next; jmp_info = jmp_info_next;
} }