mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-05 19:50:23 +02:00
Various fixes for as-needed emission of literal pool
This commit is contained in:
parent
568fdecc86
commit
b7f367165f
3 changed files with 68 additions and 30 deletions
|
@ -84,7 +84,7 @@ oxx9(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Simm9)
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
encode_ox19(jit_state_t *_jit, int32_t Op, int32_t Rd)
|
encode_ox19(int32_t Op, int32_t Rd)
|
||||||
{
|
{
|
||||||
uint32_t inst = Op;
|
uint32_t inst = Op;
|
||||||
inst = write_Rd_bitfield(inst, Rd);
|
inst = write_Rd_bitfield(inst, Rd);
|
||||||
|
@ -92,7 +92,7 @@ encode_ox19(jit_state_t *_jit, int32_t Op, int32_t Rd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
encode_oc19(jit_state_t *_jit, int32_t Op, int32_t Cc)
|
encode_oc19(int32_t Op, int32_t Cc)
|
||||||
{
|
{
|
||||||
uint32_t inst = Op;
|
uint32_t inst = Op;
|
||||||
inst = write_cond2_bitfield(inst, Cc);
|
inst = write_cond2_bitfield(inst, Cc);
|
||||||
|
@ -100,7 +100,7 @@ encode_oc19(jit_state_t *_jit, int32_t Op, int32_t Cc)
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
encode_o26(jit_state_t *_jit, int32_t Op)
|
encode_o26(int32_t Op)
|
||||||
{
|
{
|
||||||
uint32_t inst = Op;
|
uint32_t inst = Op;
|
||||||
return inst;
|
return inst;
|
||||||
|
@ -933,13 +933,13 @@ LDP_POS(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
B(jit_state_t *_jit)
|
B(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
return emit_jmp(_jit, encode_o26(_jit, A64_B));
|
return emit_jmp(_jit, encode_o26(A64_B));
|
||||||
}
|
}
|
||||||
|
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
BL(jit_state_t *_jit)
|
BL(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
return emit_jmp(_jit, encode_o26(_jit, A64_BL));
|
return emit_jmp(_jit, encode_o26(A64_BL));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -963,19 +963,19 @@ RET(jit_state_t *_jit)
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
B_C(jit_state_t *_jit, int32_t Cc)
|
B_C(jit_state_t *_jit, int32_t Cc)
|
||||||
{
|
{
|
||||||
return emit_jcc(_jit, encode_oc19(_jit, A64_B_C, Cc));
|
return emit_jcc(_jit, encode_oc19(A64_B_C, Cc));
|
||||||
}
|
}
|
||||||
|
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
CBZ(jit_state_t *_jit, int32_t Rd)
|
CBZ(jit_state_t *_jit, int32_t Rd)
|
||||||
{
|
{
|
||||||
return emit_jcc(_jit, encode_ox19(_jit, A64_CBZ|XS,Rd));
|
return emit_jcc(_jit, encode_ox19(A64_CBZ|XS,Rd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
CBNZ(jit_state_t *_jit, int32_t Rd)
|
CBNZ(jit_state_t *_jit, int32_t Rd)
|
||||||
{
|
{
|
||||||
return emit_jcc(_jit, encode_ox19(_jit, A64_CBNZ|XS,Rd));
|
return emit_jcc(_jit, encode_ox19(A64_CBNZ|XS,Rd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -987,14 +987,14 @@ NOP(jit_state_t *_jit)
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
movi_from_pool(jit_state_t *_jit, int32_t Rt)
|
movi_from_pool(jit_state_t *_jit, int32_t Rt)
|
||||||
{
|
{
|
||||||
return emit_load_from_pool(_jit, encode_ox19(_jit, A64_LDRI_LITERAL, Rt));
|
return emit_load_from_pool(_jit, encode_ox19(A64_LDRI_LITERAL, Rt));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
emit_veneer(jit_state_t *_jit, jit_pointer_t target)
|
emit_veneer(jit_state_t *_jit, jit_pointer_t target)
|
||||||
{
|
{
|
||||||
jit_gpr_t tmp = get_temp_gpr(_jit);
|
jit_gpr_t tmp = get_temp_gpr(_jit);
|
||||||
uint32_t inst = encode_ox19(_jit, A64_LDRI_LITERAL, jit_gpr_regno(tmp));
|
uint32_t inst = encode_ox19(A64_LDRI_LITERAL, jit_gpr_regno(tmp));
|
||||||
uint32_t *loc = _jit->pc.ui;
|
uint32_t *loc = _jit->pc.ui;
|
||||||
emit_u32(_jit, inst);
|
emit_u32(_jit, inst);
|
||||||
BR(_jit, jit_gpr_regno(tmp));
|
BR(_jit, jit_gpr_regno(tmp));
|
||||||
|
@ -2536,3 +2536,17 @@ retval_l(jit_state_t *_jit, int32_t r0)
|
||||||
{
|
{
|
||||||
movr(_jit, r0, jit_gpr_regno(_X0));
|
movr(_jit, r0, jit_gpr_regno(_X0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t*
|
||||||
|
jmp_without_veneer(jit_state_t *_jit)
|
||||||
|
{
|
||||||
|
uint32_t *loc = _jit->pc.ui;
|
||||||
|
emit_u32(_jit, encode_o26(_jit, A64_B));
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
patch_jmp_without_veneer(jit_state_t *_jit, uint32_t *loc)
|
||||||
|
{
|
||||||
|
patch_jmp_offset(loc, _jit->pc.ui - loc);
|
||||||
|
}
|
||||||
|
|
|
@ -2922,6 +2922,24 @@ retval_i(jit_state_t *_jit, int32_t r0)
|
||||||
movr(_jit, r0, jit_gpr_regno(_R0));
|
movr(_jit, r0, jit_gpr_regno(_R0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t*
|
||||||
|
jmp_without_veneer(jit_state_t *_jit)
|
||||||
|
{
|
||||||
|
uint32_t *loc = _jit->pc.ui;
|
||||||
|
emit_u16(_jit, 0);
|
||||||
|
emit_u16(_jit, 0);
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
patch_jmp_without_veneer(jit_state_t *_jit, uint32_t *loc)
|
||||||
|
{
|
||||||
|
uint8_t *pc_base = ((uint8_t *)loc) + 4;
|
||||||
|
uint8_t rsh = 1;
|
||||||
|
int32_t off = (_jit->pc.uc - pc_base) >> rsh;
|
||||||
|
write_wide_thumb(loc, THUMB2_B | encode_thumb_jump(off));
|
||||||
|
}
|
||||||
|
|
||||||
struct veneer
|
struct veneer
|
||||||
{
|
{
|
||||||
uint16_t ldr;
|
uint16_t ldr;
|
||||||
|
@ -2940,11 +2958,11 @@ static void
|
||||||
emit_veneer(jit_state_t *_jit, jit_pointer_t target)
|
emit_veneer(jit_state_t *_jit, jit_pointer_t target)
|
||||||
{
|
{
|
||||||
uint16_t thumb1_ldr = 0x4800;
|
uint16_t thumb1_ldr = 0x4800;
|
||||||
int32_t tmp = jit_gpr_regno(get_temp_gpr(_jit));
|
int32_t tmp = jit_gpr_regno(JIT_TMP1);
|
||||||
|
int32_t rd = jit_gpr_regno(_PC);
|
||||||
ASSERT(tmp < 8);
|
ASSERT(tmp < 8);
|
||||||
// Loaded addr is 4 bytes after the LDR, which is aligned, so offset is 0.
|
// Loaded addr is 4 bytes after the LDR, which is aligned, so offset is 0.
|
||||||
emit_u16(_jit, thumb1_ldr | (tmp << 8));
|
emit_u16(_jit, thumb1_ldr | (tmp << 8));
|
||||||
T1_MOV(_jit, jit_gpr_regno(_PC), tmp);
|
emit_u16(_jit, THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(tmp)<<3)|(rd&7));
|
||||||
unget_temp_gpr(_jit);
|
|
||||||
emit_u32(_jit, (uint32_t) target);
|
emit_u32(_jit, (uint32_t) target);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,8 @@ struct abi_arg_iterator;
|
||||||
#ifdef JIT_NEEDS_LITERAL_POOL
|
#ifdef JIT_NEEDS_LITERAL_POOL
|
||||||
static struct jit_literal_pool* alloc_literal_pool(jit_state_t *_jit,
|
static struct jit_literal_pool* alloc_literal_pool(jit_state_t *_jit,
|
||||||
size_t capacity);
|
size_t capacity);
|
||||||
static void clear_literal_pool(struct jit_literal_pool *pool);
|
static void reset_literal_pool(jit_state_t *_jit,
|
||||||
|
struct jit_literal_pool *pool);
|
||||||
static void grow_literal_pool(jit_state_t *_jit);
|
static void grow_literal_pool(jit_state_t *_jit);
|
||||||
static void add_literal_pool_entry(jit_state_t *_jit,
|
static void add_literal_pool_entry(jit_state_t *_jit,
|
||||||
struct jit_literal_pool_entry entry,
|
struct jit_literal_pool_entry entry,
|
||||||
|
@ -185,6 +186,9 @@ jit_begin(jit_state_t *_jit, uint8_t* buf, size_t length)
|
||||||
_jit->limit = buf + length;
|
_jit->limit = buf + length;
|
||||||
_jit->overflow = 0;
|
_jit->overflow = 0;
|
||||||
_jit->frame_size = 0;
|
_jit->frame_size = 0;
|
||||||
|
#if JIT_NEEDS_LITERAL_POOL
|
||||||
|
_jit->pool->deadline = length;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
jit_bool_t
|
jit_bool_t
|
||||||
|
@ -202,7 +206,7 @@ jit_reset(jit_state_t *_jit)
|
||||||
_jit->overflow = 0;
|
_jit->overflow = 0;
|
||||||
_jit->frame_size = 0;
|
_jit->frame_size = 0;
|
||||||
#ifdef JIT_NEEDS_LITERAL_POOL
|
#ifdef JIT_NEEDS_LITERAL_POOL
|
||||||
clear_literal_pool(_jit->pool);
|
reset_literal_pool(_jit, _jit->pool);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +244,7 @@ jit_end(jit_state_t *_jit, size_t *length)
|
||||||
_jit->overflow = 0;
|
_jit->overflow = 0;
|
||||||
_jit->frame_size = 0;
|
_jit->frame_size = 0;
|
||||||
#ifdef JIT_NEEDS_LITERAL_POOL
|
#ifdef JIT_NEEDS_LITERAL_POOL
|
||||||
clear_literal_pool(_jit->pool);
|
reset_literal_pool(_jit, _jit->pool);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return jit_address_to_function_pointer(start);
|
return jit_address_to_function_pointer(start);
|
||||||
|
@ -1226,9 +1230,10 @@ jit_load_args(jit_state_t *_jit, size_t argc, jit_operand_t args[])
|
||||||
|
|
||||||
#ifdef JIT_NEEDS_LITERAL_POOL
|
#ifdef JIT_NEEDS_LITERAL_POOL
|
||||||
static void
|
static void
|
||||||
clear_literal_pool(struct jit_literal_pool *pool)
|
reset_literal_pool(jit_state_t *_jit,
|
||||||
|
struct jit_literal_pool *pool)
|
||||||
{
|
{
|
||||||
pool->deadline = -1;
|
pool->deadline = _jit->limit - _jit->start;
|
||||||
pool->size = 0;
|
pool->size = 0;
|
||||||
pool->byte_size = 0;
|
pool->byte_size = 0;
|
||||||
memset(pool->entries, 0, sizeof(pool->entries[0]) * pool->size);
|
memset(pool->entries, 0, sizeof(pool->entries[0]) * pool->size);
|
||||||
|
@ -1245,7 +1250,7 @@ alloc_literal_pool(jit_state_t *_jit, size_t capacity)
|
||||||
sizeof (struct jit_literal_pool_entry) * capacity);
|
sizeof (struct jit_literal_pool_entry) * capacity);
|
||||||
ASSERT (ret);
|
ASSERT (ret);
|
||||||
ret->capacity = capacity;
|
ret->capacity = capacity;
|
||||||
clear_literal_pool(ret);
|
reset_literal_pool(_jit, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1270,14 +1275,12 @@ add_literal_pool_entry(jit_state_t *_jit, struct jit_literal_pool_entry entry,
|
||||||
if (_jit->pool->size == _jit->pool->capacity)
|
if (_jit->pool->size == _jit->pool->capacity)
|
||||||
grow_literal_pool (_jit);
|
grow_literal_pool (_jit);
|
||||||
|
|
||||||
max_offset <<= entry.reloc.rsh;
|
uint32_t deadline =
|
||||||
ptrdiff_t deadline =
|
|
||||||
_jit->pc.uc - _jit->start + max_offset - _jit->pool->byte_size;
|
_jit->pc.uc - _jit->start + max_offset - _jit->pool->byte_size;
|
||||||
if (_jit->pool->size == 0)
|
// Assume that we might need a uint32_t for alignment, and another
|
||||||
// Assume that we might need a uint32_t for alignment, and another
|
// to branch over the table.
|
||||||
// to branch over the table.
|
deadline -= 2 * sizeof(uint32_t);
|
||||||
_jit->pool->deadline = deadline - 2 * sizeof(uint32_t);
|
if (deadline < _jit->pool->deadline)
|
||||||
else if (deadline < _jit->pool->deadline)
|
|
||||||
_jit->pool->deadline = deadline;
|
_jit->pool->deadline = deadline;
|
||||||
|
|
||||||
// Assume that each entry takes a max of 16 bytes.
|
// Assume that each entry takes a max of 16 bytes.
|
||||||
|
@ -1325,14 +1328,17 @@ patch_pending_literal(jit_state_t *_jit, jit_reloc_t src, uint64_t value)
|
||||||
static void
|
static void
|
||||||
emit_literal_pool(jit_state_t *_jit, enum guard_pool guard)
|
emit_literal_pool(jit_state_t *_jit, enum guard_pool guard)
|
||||||
{
|
{
|
||||||
|
if (_jit->overflow)
|
||||||
|
return;
|
||||||
|
|
||||||
_jit->pool->deadline = -1;
|
_jit->pool->deadline = -1;
|
||||||
|
|
||||||
if (!_jit->pool->size)
|
if (!_jit->pool->size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
jit_reloc_t skip;
|
uint32_t *patch_loc = NULL;
|
||||||
if (guard == GUARD_NEEDED)
|
if (guard == GUARD_NEEDED)
|
||||||
skip = jit_jmp(_jit);
|
patch_loc = jmp_without_veneer(_jit);
|
||||||
|
|
||||||
// FIXME: Could de-duplicate constants.
|
// FIXME: Could de-duplicate constants.
|
||||||
for (size_t i = 0; i < _jit->pool->size; i++) {
|
for (size_t i = 0; i < _jit->pool->size; i++) {
|
||||||
|
@ -1363,8 +1369,8 @@ emit_literal_pool(jit_state_t *_jit, enum guard_pool guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guard == GUARD_NEEDED)
|
if (guard == GUARD_NEEDED)
|
||||||
jit_patch_here(_jit, skip);
|
patch_jmp_without_veneer(_jit, patch_loc);
|
||||||
|
|
||||||
clear_literal_pool(_jit->pool);
|
reset_literal_pool(_jit, _jit->pool);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue