56
56
#define JIT_OP_MOD_REG (JIT_CLS_ALU | JIT_SRC_REG | 0x90)
57
57
58
58
#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
60
62
#if defined(__x86_64__ )
61
63
#define JUMP_LOC jump_loc + 2
62
64
/* 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);
242
244
243
245
static inline void offset_map_insert (struct jit_state * state , int32_t target_pc )
244
246
{
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 );
247
249
map_entry -> pc = target_pc ;
248
250
map_entry -> offset = state -> offset ;
249
251
}
@@ -353,7 +355,7 @@ static inline void emit_jump_target_address(struct jit_state *state,
353
355
int32_t target_pc )
354
356
{
355
357
struct jump * jump = & state -> jumps [state -> n_jumps ++ ];
356
- assert (state -> n_jumps < MAX_INSNS );
358
+ assert (state -> n_jumps < MAX_JUMPS );
357
359
jump -> offset_loc = state -> offset ;
358
360
jump -> target_pc = target_pc ;
359
361
emit4 (state , 0 );
@@ -555,7 +557,7 @@ static inline void emit_jump_target_offset(struct jit_state *state,
555
557
uint32_t jump_state_offset )
556
558
{
557
559
struct jump * jump = & state -> jumps [state -> n_jumps ++ ];
558
- assert (state -> n_jumps < MAX_INSNS );
560
+ assert (state -> n_jumps < MAX_JUMPS );
559
561
jump -> offset_loc = jump_loc ;
560
562
jump -> target_offset = jump_state_offset ;
561
563
}
@@ -933,7 +935,7 @@ static inline void emit_jmp(struct jit_state *state, uint32_t target_pc)
933
935
emit_jump_target_address (state , target_pc );
934
936
#elif defined(__aarch64__ )
935
937
struct jump * jump = & state -> jumps [state -> n_jumps ++ ];
936
- assert (state -> n_jumps < MAX_INSNS );
938
+ assert (state -> n_jumps < MAX_JUMPS );
937
939
jump -> offset_loc = state -> offset ;
938
940
jump -> target_pc = target_pc ;
939
941
emit_a64 (state , UBR_B );
@@ -1349,7 +1351,7 @@ void parse_branch_history_table(struct jit_state *state, rv_insn_t *ir)
1349
1351
if (bt -> times [max_idx ] < bt -> times [i ])
1350
1352
max_idx = i ;
1351
1353
}
1352
- if (bt -> PC [max_idx ]) {
1354
+ if (bt -> PC [max_idx ] && bt -> times [ max_idx ] >= IN_JUMP_THRESHOLD ) {
1353
1355
emit_load_imm (state , register_map [0 ], bt -> PC [max_idx ]);
1354
1356
emit_cmp32 (state , temp_reg , register_map [0 ]);
1355
1357
uint32_t jump_loc = state -> offset ;
@@ -1511,7 +1513,7 @@ static void resolve_jumps(struct jit_state *state)
1511
1513
#endif
1512
1514
else {
1513
1515
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 ++ ) {
1515
1517
if (jump .target_pc == state -> offset_map [i ].pc ) {
1516
1518
target_loc = state -> offset_map [i ].offset ;
1517
1519
break ;
@@ -1533,27 +1535,26 @@ static void resolve_jumps(struct jit_state *state)
1533
1535
1534
1536
static void translate_chained_block (struct jit_state * state ,
1535
1537
riscv_t * rv ,
1536
- block_t * block ,
1537
- set_t * set )
1538
+ block_t * block )
1538
1539
{
1539
- if (set_has (set , block -> pc_start ))
1540
+ if (set_has (& state -> set , block -> pc_start ))
1540
1541
return ;
1541
1542
1542
- set_add (set , block -> pc_start );
1543
+ set_add (& state -> set , block -> pc_start );
1543
1544
offset_map_insert (state , block -> pc_start );
1544
1545
translate (state , rv , block );
1545
1546
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 )) {
1547
1548
block_t * block1 =
1548
1549
cache_get (rv -> block_cache , ir -> branch_untaken -> pc , false);
1549
1550
if (block1 -> translatable )
1550
- translate_chained_block (state , rv , block1 , set );
1551
+ translate_chained_block (state , rv , block1 );
1551
1552
}
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 )) {
1553
1554
block_t * block1 =
1554
1555
cache_get (rv -> block_cache , ir -> branch_taken -> pc , false);
1555
1556
if (block1 -> translatable )
1556
- translate_chained_block (state , rv , block1 , set );
1557
+ translate_chained_block (state , rv , block1 );
1557
1558
}
1558
1559
branch_history_table_t * bt = ir -> branch_table ;
1559
1560
if (bt ) {
@@ -1564,26 +1565,31 @@ static void translate_chained_block(struct jit_state *state,
1564
1565
if (bt -> times [max_idx ] < bt -> times [i ])
1565
1566
max_idx = i ;
1566
1567
}
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 ])) {
1568
1570
block_t * block1 =
1569
1571
cache_get (rv -> block_cache , bt -> PC [max_idx ], false);
1570
1572
if (block1 && block1 -> translatable )
1571
- translate_chained_block (state , rv , block1 , set );
1573
+ translate_chained_block (state , rv , block1 );
1572
1574
}
1573
1575
}
1574
1576
}
1575
1577
1576
1578
uint32_t jit_translate (riscv_t * rv , block_t * block )
1577
1579
{
1578
1580
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 ));
1582
1590
state -> n_jumps = 0 ;
1583
1591
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 );
1587
1593
if (state -> offset == state -> size ) {
1588
1594
printf ("Target buffer too small\n" );
1589
1595
goto out ;
@@ -1606,10 +1612,12 @@ struct jit_state *jit_state_init(size_t size)
1606
1612
#endif
1607
1613
,
1608
1614
-1 , 0 );
1615
+ state -> n_blocks = 0 ;
1609
1616
assert (state -> buf != MAP_FAILED );
1617
+ set_reset (& state -> set );
1610
1618
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 ));
1613
1621
return state ;
1614
1622
}
1615
1623
0 commit comments