mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-30 15:00:21 +02:00
Merge remote-tracking branch 'lightening/master'
This commit is contained in:
commit
3b707bb43d
3 changed files with 87 additions and 56 deletions
|
@ -108,11 +108,14 @@ DEFINE_ENCODER(size, 2, 22, unsigned, uint32_t)
|
||||||
static jit_reloc_t \
|
static jit_reloc_t \
|
||||||
emit_##name(jit_state_t *_jit, uint32_t inst) \
|
emit_##name(jit_state_t *_jit, uint32_t inst) \
|
||||||
{ \
|
{ \
|
||||||
jit_reloc_t ret = jit_reloc (_jit, JIT_RELOC_##RELOC, 0, \
|
while (1) { \
|
||||||
_jit->pc.uc, _jit->pc.uc, rsh); \
|
jit_reloc_t ret = jit_reloc (_jit, JIT_RELOC_##RELOC, 0, \
|
||||||
add_pending_literal(_jit, ret, kind##_width - 1); \
|
_jit->pc.uc, _jit->pc.uc, rsh); \
|
||||||
emit_u32(_jit, inst); \
|
if (add_pending_literal(_jit, ret, kind##_width - 1)) { \
|
||||||
return ret; \
|
emit_u32(_jit, inst); \
|
||||||
|
return ret; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_PATCHABLE_INSTRUCTION(jmp, simm26, JMP_WITH_VENEER, 2);
|
DEFINE_PATCHABLE_INSTRUCTION(jmp, simm26, JMP_WITH_VENEER, 2);
|
||||||
|
|
|
@ -324,15 +324,18 @@ patch_jmp_offset(uint32_t *loc, int32_t v)
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
emit_thumb_jump(jit_state_t *_jit, uint32_t inst)
|
emit_thumb_jump(jit_state_t *_jit, uint32_t inst)
|
||||||
{
|
{
|
||||||
uint8_t *pc_base = _jit->pc.uc + 4;
|
while (1) {
|
||||||
uint8_t rsh = 1;
|
uint8_t *pc_base = _jit->pc.uc + 4;
|
||||||
int32_t off = (_jit->pc.uc - pc_base) >> rsh;
|
uint8_t rsh = 1;
|
||||||
jit_reloc_t ret =
|
int32_t off = (_jit->pc.uc - pc_base) >> rsh;
|
||||||
jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh);
|
jit_reloc_t ret =
|
||||||
uint8_t thumb_jump_width = 24;
|
jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh);
|
||||||
add_pending_literal(_jit, ret, thumb_jump_width - 1);
|
uint8_t thumb_jump_width = 24;
|
||||||
emit_wide_thumb(_jit, patch_thumb_jump(inst, off));
|
if (add_pending_literal(_jit, ret, thumb_jump_width - 1)) {
|
||||||
return ret;
|
emit_wide_thumb(_jit, patch_thumb_jump(inst, off));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -397,15 +400,18 @@ patch_jcc_offset(uint32_t *loc, int32_t v)
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst)
|
emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst)
|
||||||
{
|
{
|
||||||
uint8_t *pc_base = _jit->pc.uc + 4;
|
while (1) {
|
||||||
uint8_t rsh = 1;
|
uint8_t *pc_base = _jit->pc.uc + 4;
|
||||||
int32_t off = (_jit->pc.uc - pc_base) >> rsh;
|
uint8_t rsh = 1;
|
||||||
jit_reloc_t ret =
|
int32_t off = (_jit->pc.uc - pc_base) >> rsh;
|
||||||
jit_reloc (_jit, JIT_RELOC_JCC_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh);
|
jit_reloc_t ret =
|
||||||
uint8_t thumb_cc_jump_width = 20;
|
jit_reloc (_jit, JIT_RELOC_JCC_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh);
|
||||||
add_pending_literal(_jit, ret, thumb_cc_jump_width - 1);
|
uint8_t thumb_cc_jump_width = 20;
|
||||||
emit_wide_thumb(_jit, patch_thumb_cc_jump(inst, off));
|
if (add_pending_literal(_jit, ret, thumb_cc_jump_width - 1)) {
|
||||||
return ret;
|
emit_wide_thumb(_jit, patch_thumb_cc_jump(inst, off));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1402,15 +1408,18 @@ patch_load_from_pool_offset(uint32_t *loc, int32_t v)
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
emit_load_from_pool(jit_state_t *_jit, uint32_t inst)
|
emit_load_from_pool(jit_state_t *_jit, uint32_t inst)
|
||||||
{
|
{
|
||||||
uint8_t *pc_base = (uint8_t *)((_jit->pc.w + 4) & ~3);
|
while (1) {
|
||||||
uint8_t rsh = 0;
|
uint8_t *pc_base = (uint8_t *)((_jit->pc.w + 4) & ~3);
|
||||||
int32_t off = (_jit->pc.uc - pc_base) >> rsh;
|
uint8_t rsh = 0;
|
||||||
jit_reloc_t ret =
|
int32_t off = (_jit->pc.uc - pc_base) >> rsh;
|
||||||
jit_reloc (_jit, JIT_RELOC_LOAD_FROM_POOL, 0, _jit->pc.uc, pc_base, rsh);
|
jit_reloc_t ret =
|
||||||
uint8_t load_from_pool_width = 12;
|
jit_reloc (_jit, JIT_RELOC_LOAD_FROM_POOL, 0, _jit->pc.uc, pc_base, rsh);
|
||||||
add_pending_literal(_jit, ret, load_from_pool_width);
|
uint8_t load_from_pool_width = 12;
|
||||||
emit_wide_thumb(_jit, patch_load_from_pool(inst, off));
|
if (add_pending_literal(_jit, ret, load_from_pool_width)) {
|
||||||
return ret;
|
emit_wide_thumb(_jit, patch_load_from_pool(inst, off));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
|
@ -2950,7 +2959,7 @@ struct veneer
|
||||||
static void
|
static void
|
||||||
patch_veneer(uint32_t *loc, jit_pointer_t addr)
|
patch_veneer(uint32_t *loc, jit_pointer_t addr)
|
||||||
{
|
{
|
||||||
struct veneer *v = (struct veneer*) v;
|
struct veneer *v = (struct veneer*) loc;
|
||||||
v->addr = (uintptr_t) addr;
|
v->addr = (uintptr_t) addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ struct jit_literal_pool
|
||||||
{
|
{
|
||||||
uint32_t deadline;
|
uint32_t deadline;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t byte_size;
|
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
struct jit_literal_pool_entry entries[];
|
struct jit_literal_pool_entry entries[];
|
||||||
};
|
};
|
||||||
|
@ -98,11 +97,11 @@ static struct jit_literal_pool* alloc_literal_pool(jit_state_t *_jit,
|
||||||
static void reset_literal_pool(jit_state_t *_jit,
|
static void reset_literal_pool(jit_state_t *_jit,
|
||||||
struct jit_literal_pool *pool);
|
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 jit_bool_t add_literal_pool_entry(jit_state_t *_jit,
|
||||||
struct jit_literal_pool_entry entry,
|
struct jit_literal_pool_entry entry,
|
||||||
ptrdiff_t max_offset);
|
uint32_t max_offset);
|
||||||
static void add_pending_literal(jit_state_t *_jit, jit_reloc_t src,
|
static jit_bool_t add_pending_literal(jit_state_t *_jit, jit_reloc_t src,
|
||||||
ptrdiff_t max_offset_bits);
|
uint8_t max_offset_bits);
|
||||||
static void remove_pending_literal(jit_state_t *_jit, jit_reloc_t src);
|
static void remove_pending_literal(jit_state_t *_jit, jit_reloc_t src);
|
||||||
static void patch_pending_literal(jit_state_t *_jit, jit_reloc_t src,
|
static void patch_pending_literal(jit_state_t *_jit, jit_reloc_t src,
|
||||||
uint64_t value);
|
uint64_t value);
|
||||||
|
@ -187,6 +186,7 @@ jit_begin(jit_state_t *_jit, uint8_t* buf, size_t length)
|
||||||
_jit->overflow = 0;
|
_jit->overflow = 0;
|
||||||
_jit->frame_size = 0;
|
_jit->frame_size = 0;
|
||||||
#if JIT_NEEDS_LITERAL_POOL
|
#if JIT_NEEDS_LITERAL_POOL
|
||||||
|
ASSERT(_jit->pool->size == 0);
|
||||||
_jit->pool->deadline = length;
|
_jit->pool->deadline = length;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1229,13 +1229,20 @@ 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 uint32_t
|
||||||
|
literal_pool_byte_size(struct jit_literal_pool *pool)
|
||||||
|
{
|
||||||
|
// Assume that we might need a uint32_t to branch over a table, and up
|
||||||
|
// to 7 bytes for alignment of the table. Then we assume that no
|
||||||
|
// entry will be more than two words.
|
||||||
|
return sizeof(uint32_t) + 7 + pool->size * sizeof(uintptr_t) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reset_literal_pool(jit_state_t *_jit,
|
reset_literal_pool(jit_state_t *_jit, struct jit_literal_pool *pool)
|
||||||
struct jit_literal_pool *pool)
|
|
||||||
{
|
{
|
||||||
pool->deadline = _jit->limit - _jit->start;
|
pool->deadline = _jit->limit - _jit->start;
|
||||||
pool->size = 0;
|
pool->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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1268,34 +1275,40 @@ grow_literal_pool(jit_state_t *_jit)
|
||||||
_jit->pool = new_pool;
|
_jit->pool = new_pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static jit_bool_t
|
||||||
add_literal_pool_entry(jit_state_t *_jit, struct jit_literal_pool_entry entry,
|
add_literal_pool_entry(jit_state_t *_jit, struct jit_literal_pool_entry entry,
|
||||||
ptrdiff_t max_offset)
|
uint32_t max_offset)
|
||||||
{
|
{
|
||||||
|
if (max_offset <= literal_pool_byte_size(_jit->pool)) {
|
||||||
|
emit_literal_pool(_jit, GUARD_NEEDED);
|
||||||
|
ASSERT(_jit->pool->size == 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (_jit->pool->size == _jit->pool->capacity)
|
if (_jit->pool->size == _jit->pool->capacity)
|
||||||
grow_literal_pool (_jit);
|
grow_literal_pool (_jit);
|
||||||
|
|
||||||
|
uint32_t loc_offset = _jit->pc.uc - _jit->start;
|
||||||
|
uint32_t inst_offset = loc_offset - entry.reloc.inst_start_offset;
|
||||||
|
uint32_t pc_base_offset = inst_offset + entry.reloc.pc_base_offset;
|
||||||
uint32_t deadline =
|
uint32_t deadline =
|
||||||
_jit->pc.uc - _jit->start + max_offset - _jit->pool->byte_size;
|
pc_base_offset + (max_offset - literal_pool_byte_size(_jit->pool));
|
||||||
// Assume that we might need a uint32_t for alignment, and another
|
|
||||||
// to branch over the table.
|
|
||||||
deadline -= 2 * sizeof(uint32_t);
|
|
||||||
if (deadline < _jit->pool->deadline)
|
if (deadline < _jit->pool->deadline)
|
||||||
_jit->pool->deadline = deadline;
|
_jit->pool->deadline = deadline;
|
||||||
|
|
||||||
// Assume that each entry takes a max of 16 bytes.
|
|
||||||
_jit->pool->byte_size += 16;
|
|
||||||
|
|
||||||
_jit->pool->entries[_jit->pool->size++] = entry;
|
_jit->pool->entries[_jit->pool->size++] = entry;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static jit_bool_t
|
||||||
add_pending_literal(jit_state_t *_jit, jit_reloc_t src,
|
add_pending_literal(jit_state_t *_jit, jit_reloc_t src,
|
||||||
ptrdiff_t max_offset_bits)
|
uint8_t max_offset_bits)
|
||||||
{
|
{
|
||||||
struct jit_literal_pool_entry entry = { src, 0 };
|
struct jit_literal_pool_entry entry = { src, 0 };
|
||||||
add_literal_pool_entry(_jit, entry,
|
uint32_t max_inst_size = sizeof(uint32_t);
|
||||||
(1 << (max_offset_bits + src.rsh)) - 1);
|
uint32_t max_offset = (1 << (max_offset_bits + src.rsh)) - max_inst_size;
|
||||||
|
return add_literal_pool_entry(_jit, entry, max_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1340,7 +1353,10 @@ emit_literal_pool(jit_state_t *_jit, enum guard_pool guard)
|
||||||
|
|
||||||
// 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++) {
|
||||||
jit_align(_jit, 8);
|
// Align to 8-byte boundary without emitting pool.
|
||||||
|
if (_jit->pc.w & 1) emit_u8(_jit, 0);
|
||||||
|
if (_jit->pc.w & 2) emit_u16(_jit, 0);
|
||||||
|
if (_jit->pc.w & 4) emit_u32(_jit, 0);
|
||||||
struct jit_literal_pool_entry *entry = &_jit->pool->entries[i];
|
struct jit_literal_pool_entry *entry = &_jit->pool->entries[i];
|
||||||
uint8_t *loc = _jit->start + entry->reloc.offset;
|
uint8_t *loc = _jit->start + entry->reloc.offset;
|
||||||
uint8_t *pc_base =
|
uint8_t *pc_base =
|
||||||
|
@ -1348,6 +1364,9 @@ emit_literal_pool(jit_state_t *_jit, enum guard_pool guard)
|
||||||
ptrdiff_t diff = _jit->pc.uc - pc_base;
|
ptrdiff_t diff = _jit->pc.uc - pc_base;
|
||||||
diff >>= entry->reloc.rsh;
|
diff >>= entry->reloc.rsh;
|
||||||
|
|
||||||
|
if (_jit->overflow)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (entry->reloc.kind) {
|
switch (entry->reloc.kind) {
|
||||||
case JIT_RELOC_JMP_WITH_VENEER:
|
case JIT_RELOC_JMP_WITH_VENEER:
|
||||||
patch_jmp_offset((uint32_t*) loc, diff);
|
patch_jmp_offset((uint32_t*) loc, diff);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue