Skip to content

Commit 2935d30

Browse files
authored
Merge pull request #378 from qwe661234/save_code_cache
Avoid generating machine code repeatly for same basic block
2 parents 2671ffd + 8be2b88 commit 2935d30

File tree

2 files changed

+37
-27
lines changed

2 files changed

+37
-27
lines changed

src/jit.c

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@
5656
#define JIT_OP_MOD_REG (JIT_CLS_ALU | JIT_SRC_REG | 0x90)
5757

5858
#define STACK_SIZE 512
59-
#define MAX_INSNS 1024
59+
#define MAX_JUMPS 1024
60+
#define MAX_BLOCKS 8192
61+
#define IN_JUMP_THRESHOLD 256
6062
#if defined(__x86_64__)
6163
#define JUMP_LOC jump_loc + 2
6264
/* Special values for target_pc in struct jump */
@@ -242,8 +244,8 @@ static inline void emit_load_imm(struct jit_state *state, int dst, int64_t imm);
242244

243245
static inline void offset_map_insert(struct jit_state *state, int32_t target_pc)
244246
{
245-
struct offset_map *map_entry = &state->offset_map[state->n_insn++];
246-
assert(state->n_insn < MAX_INSNS);
247+
struct offset_map *map_entry = &state->offset_map[state->n_blocks++];
248+
assert(state->n_blocks < MAX_BLOCKS);
247249
map_entry->pc = target_pc;
248250
map_entry->offset = state->offset;
249251
}
@@ -353,7 +355,7 @@ static inline void emit_jump_target_address(struct jit_state *state,
353355
int32_t target_pc)
354356
{
355357
struct jump *jump = &state->jumps[state->n_jumps++];
356-
assert(state->n_jumps < MAX_INSNS);
358+
assert(state->n_jumps < MAX_JUMPS);
357359
jump->offset_loc = state->offset;
358360
jump->target_pc = target_pc;
359361
emit4(state, 0);
@@ -555,7 +557,7 @@ static inline void emit_jump_target_offset(struct jit_state *state,
555557
uint32_t jump_state_offset)
556558
{
557559
struct jump *jump = &state->jumps[state->n_jumps++];
558-
assert(state->n_jumps < MAX_INSNS);
560+
assert(state->n_jumps < MAX_JUMPS);
559561
jump->offset_loc = jump_loc;
560562
jump->target_offset = jump_state_offset;
561563
}
@@ -933,7 +935,7 @@ static inline void emit_jmp(struct jit_state *state, uint32_t target_pc)
933935
emit_jump_target_address(state, target_pc);
934936
#elif defined(__aarch64__)
935937
struct jump *jump = &state->jumps[state->n_jumps++];
936-
assert(state->n_jumps < MAX_INSNS);
938+
assert(state->n_jumps < MAX_JUMPS);
937939
jump->offset_loc = state->offset;
938940
jump->target_pc = target_pc;
939941
emit_a64(state, UBR_B);
@@ -1349,7 +1351,7 @@ void parse_branch_history_table(struct jit_state *state, rv_insn_t *ir)
13491351
if (bt->times[max_idx] < bt->times[i])
13501352
max_idx = i;
13511353
}
1352-
if (bt->PC[max_idx]) {
1354+
if (bt->PC[max_idx] && bt->times[max_idx] >= IN_JUMP_THRESHOLD) {
13531355
emit_load_imm(state, register_map[0], bt->PC[max_idx]);
13541356
emit_cmp32(state, temp_reg, register_map[0]);
13551357
uint32_t jump_loc = state->offset;
@@ -1511,7 +1513,7 @@ static void resolve_jumps(struct jit_state *state)
15111513
#endif
15121514
else {
15131515
target_loc = jump.offset_loc + sizeof(uint32_t);
1514-
for (int i = 0; i < state->n_insn; i++) {
1516+
for (int i = 0; i < state->n_blocks; i++) {
15151517
if (jump.target_pc == state->offset_map[i].pc) {
15161518
target_loc = state->offset_map[i].offset;
15171519
break;
@@ -1533,27 +1535,26 @@ static void resolve_jumps(struct jit_state *state)
15331535

15341536
static void translate_chained_block(struct jit_state *state,
15351537
riscv_t *rv,
1536-
block_t *block,
1537-
set_t *set)
1538+
block_t *block)
15381539
{
1539-
if (set_has(set, block->pc_start))
1540+
if (set_has(&state->set, block->pc_start))
15401541
return;
15411542

1542-
set_add(set, block->pc_start);
1543+
set_add(&state->set, block->pc_start);
15431544
offset_map_insert(state, block->pc_start);
15441545
translate(state, rv, block);
15451546
rv_insn_t *ir = block->ir_tail;
1546-
if (ir->branch_untaken && !set_has(set, ir->branch_untaken->pc)) {
1547+
if (ir->branch_untaken && !set_has(&state->set, ir->branch_untaken->pc)) {
15471548
block_t *block1 =
15481549
cache_get(rv->block_cache, ir->branch_untaken->pc, false);
15491550
if (block1->translatable)
1550-
translate_chained_block(state, rv, block1, set);
1551+
translate_chained_block(state, rv, block1);
15511552
}
1552-
if (ir->branch_taken && !set_has(set, ir->branch_taken->pc)) {
1553+
if (ir->branch_taken && !set_has(&state->set, ir->branch_taken->pc)) {
15531554
block_t *block1 =
15541555
cache_get(rv->block_cache, ir->branch_taken->pc, false);
15551556
if (block1->translatable)
1556-
translate_chained_block(state, rv, block1, set);
1557+
translate_chained_block(state, rv, block1);
15571558
}
15581559
branch_history_table_t *bt = ir->branch_table;
15591560
if (bt) {
@@ -1564,26 +1565,31 @@ static void translate_chained_block(struct jit_state *state,
15641565
if (bt->times[max_idx] < bt->times[i])
15651566
max_idx = i;
15661567
}
1567-
if (bt->PC[max_idx] && !set_has(set, bt->PC[max_idx])) {
1568+
if (bt->PC[max_idx] && bt->times[max_idx] >= IN_JUMP_THRESHOLD &&
1569+
!set_has(&state->set, bt->PC[max_idx])) {
15681570
block_t *block1 =
15691571
cache_get(rv->block_cache, bt->PC[max_idx], false);
15701572
if (block1 && block1->translatable)
1571-
translate_chained_block(state, rv, block1, set);
1573+
translate_chained_block(state, rv, block1);
15721574
}
15731575
}
15741576
}
15751577

15761578
uint32_t jit_translate(riscv_t *rv, block_t *block)
15771579
{
15781580
struct jit_state *state = rv->jit_state;
1579-
memset(state->offset_map, 0, MAX_INSNS * sizeof(struct offset_map));
1580-
memset(state->jumps, 0, MAX_INSNS * sizeof(struct jump));
1581-
state->n_insn = 0;
1581+
if (set_has(&state->set, block->pc_start)) {
1582+
for (int i = 0; i < state->n_blocks; i++) {
1583+
if (block->pc_start == state->offset_map[i].pc) {
1584+
return state->offset_map[i].offset;
1585+
}
1586+
}
1587+
__UNREACHABLE;
1588+
}
1589+
memset(state->jumps, 0, 1024 * sizeof(struct jump));
15821590
state->n_jumps = 0;
15831591
uint32_t entry_loc = state->offset;
1584-
set_t set;
1585-
set_reset(&set);
1586-
translate_chained_block(&(*state), rv, block, &set);
1592+
translate_chained_block(&(*state), rv, block);
15871593
if (state->offset == state->size) {
15881594
printf("Target buffer too small\n");
15891595
goto out;
@@ -1606,10 +1612,12 @@ struct jit_state *jit_state_init(size_t size)
16061612
#endif
16071613
,
16081614
-1, 0);
1615+
state->n_blocks = 0;
16091616
assert(state->buf != MAP_FAILED);
1617+
set_reset(&state->set);
16101618
prepare_translate(state);
1611-
state->offset_map = calloc(MAX_INSNS, sizeof(struct offset_map));
1612-
state->jumps = calloc(MAX_INSNS, sizeof(struct jump));
1619+
state->offset_map = calloc(MAX_BLOCKS, sizeof(struct offset_map));
1620+
state->jumps = calloc(MAX_JUMPS, sizeof(struct jump));
16131621
return state;
16141622
}
16151623

src/jit.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdint.h>
99

1010
#include "riscv_private.h"
11+
#include "utils.h"
1112

1213
struct jump {
1314
uint32_t offset_loc;
@@ -21,6 +22,7 @@ struct offset_map {
2122
};
2223

2324
struct jit_state {
25+
set_t set;
2426
uint8_t *buf;
2527
uint32_t offset;
2628
uint32_t stack_size;
@@ -29,7 +31,7 @@ struct jit_state {
2931
uint32_t exit_loc;
3032
uint32_t retpoline_loc;
3133
struct offset_map *offset_map;
32-
int n_insn;
34+
int n_blocks;
3335
struct jump *jumps;
3436
int n_jumps;
3537
};

0 commit comments

Comments
 (0)