diff options
author | Andy Wingo <wingo@pobox.com> | 2019-05-22 17:30:25 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2019-05-22 17:30:25 +0200 |
commit | 3b707bb43d5c25d28a5198d5bc9d9594e74afc48 (patch) | |
tree | e1e0f5c0c63b6717e6774977a7a9cc7e0d4bc387 /libguile | |
parent | 9b4870cad3d24fc74b7001b37849fafb2379bd83 (diff) | |
parent | 0b3393415ec91683aa49b256b3158020ba5731c1 (diff) | |
download | guile-3b707bb43d5c25d28a5198d5bc9d9594e74afc48.tar.gz |
Merge remote-tracking branch 'lightening/master'
Diffstat (limited to 'libguile')
-rw-r--r-- | libguile/lightening/lightening/aarch64.c | 13 | ||||
-rw-r--r-- | libguile/lightening/lightening/arm-cpu.c | 65 | ||||
-rw-r--r-- | libguile/lightening/lightening/lightening.c | 65 |
3 files changed, 87 insertions, 56 deletions
diff --git a/libguile/lightening/lightening/aarch64.c b/libguile/lightening/lightening/aarch64.c index 66fb27b61..d5994d9dc 100644 --- a/libguile/lightening/lightening/aarch64.c +++ b/libguile/lightening/lightening/aarch64.c @@ -108,11 +108,14 @@ DEFINE_ENCODER(size, 2, 22, unsigned, uint32_t) static jit_reloc_t \ emit_##name(jit_state_t *_jit, uint32_t inst) \ { \ - jit_reloc_t ret = jit_reloc (_jit, JIT_RELOC_##RELOC, 0, \ - _jit->pc.uc, _jit->pc.uc, rsh); \ - add_pending_literal(_jit, ret, kind##_width - 1); \ - emit_u32(_jit, inst); \ - return ret; \ + while (1) { \ + jit_reloc_t ret = jit_reloc (_jit, JIT_RELOC_##RELOC, 0, \ + _jit->pc.uc, _jit->pc.uc, rsh); \ + if (add_pending_literal(_jit, ret, kind##_width - 1)) { \ + emit_u32(_jit, inst); \ + return ret; \ + } \ + } \ } DEFINE_PATCHABLE_INSTRUCTION(jmp, simm26, JMP_WITH_VENEER, 2); diff --git a/libguile/lightening/lightening/arm-cpu.c b/libguile/lightening/lightening/arm-cpu.c index 491b34ebe..6d91f2f87 100644 --- a/libguile/lightening/lightening/arm-cpu.c +++ b/libguile/lightening/lightening/arm-cpu.c @@ -324,15 +324,18 @@ patch_jmp_offset(uint32_t *loc, int32_t v) static jit_reloc_t emit_thumb_jump(jit_state_t *_jit, uint32_t inst) { - uint8_t *pc_base = _jit->pc.uc + 4; - uint8_t rsh = 1; - int32_t off = (_jit->pc.uc - pc_base) >> rsh; - jit_reloc_t ret = - jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh); - uint8_t thumb_jump_width = 24; - add_pending_literal(_jit, ret, thumb_jump_width - 1); - emit_wide_thumb(_jit, patch_thumb_jump(inst, off)); - return ret; + while (1) { + uint8_t *pc_base = _jit->pc.uc + 4; + uint8_t rsh = 1; + int32_t off = (_jit->pc.uc - pc_base) >> rsh; + jit_reloc_t ret = + jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh); + uint8_t thumb_jump_width = 24; + if (add_pending_literal(_jit, ret, thumb_jump_width - 1)) { + emit_wide_thumb(_jit, patch_thumb_jump(inst, off)); + return ret; + } + } } static int @@ -397,15 +400,18 @@ patch_jcc_offset(uint32_t *loc, int32_t v) static jit_reloc_t emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst) { - uint8_t *pc_base = _jit->pc.uc + 4; - uint8_t rsh = 1; - int32_t off = (_jit->pc.uc - pc_base) >> rsh; - jit_reloc_t ret = - jit_reloc (_jit, JIT_RELOC_JCC_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh); - uint8_t thumb_cc_jump_width = 20; - add_pending_literal(_jit, ret, thumb_cc_jump_width - 1); - emit_wide_thumb(_jit, patch_thumb_cc_jump(inst, off)); - return ret; + while (1) { + uint8_t *pc_base = _jit->pc.uc + 4; + uint8_t rsh = 1; + int32_t off = (_jit->pc.uc - pc_base) >> rsh; + jit_reloc_t ret = + jit_reloc (_jit, JIT_RELOC_JCC_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh); + uint8_t thumb_cc_jump_width = 20; + if (add_pending_literal(_jit, ret, thumb_cc_jump_width - 1)) { + emit_wide_thumb(_jit, patch_thumb_cc_jump(inst, off)); + return ret; + } + } } static void @@ -1402,15 +1408,18 @@ patch_load_from_pool_offset(uint32_t *loc, int32_t v) static jit_reloc_t emit_load_from_pool(jit_state_t *_jit, uint32_t inst) { - uint8_t *pc_base = (uint8_t *)((_jit->pc.w + 4) & ~3); - uint8_t rsh = 0; - int32_t off = (_jit->pc.uc - pc_base) >> rsh; - jit_reloc_t ret = - jit_reloc (_jit, JIT_RELOC_LOAD_FROM_POOL, 0, _jit->pc.uc, pc_base, rsh); - uint8_t load_from_pool_width = 12; - add_pending_literal(_jit, ret, load_from_pool_width); - emit_wide_thumb(_jit, patch_load_from_pool(inst, off)); - return ret; + while (1) { + uint8_t *pc_base = (uint8_t *)((_jit->pc.w + 4) & ~3); + uint8_t rsh = 0; + int32_t off = (_jit->pc.uc - pc_base) >> rsh; + jit_reloc_t ret = + jit_reloc (_jit, JIT_RELOC_LOAD_FROM_POOL, 0, _jit->pc.uc, pc_base, rsh); + uint8_t load_from_pool_width = 12; + if (add_pending_literal(_jit, ret, load_from_pool_width)) { + emit_wide_thumb(_jit, patch_load_from_pool(inst, off)); + return ret; + } + } } static jit_reloc_t @@ -2950,7 +2959,7 @@ struct veneer static void 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; } diff --git a/libguile/lightening/lightening/lightening.c b/libguile/lightening/lightening/lightening.c index bf9d9edbd..4f03851d7 100644 --- a/libguile/lightening/lightening/lightening.c +++ b/libguile/lightening/lightening/lightening.c @@ -60,7 +60,6 @@ struct jit_literal_pool { uint32_t deadline; uint32_t size; - uint32_t byte_size; uint32_t capacity; 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, struct jit_literal_pool *pool); static void grow_literal_pool(jit_state_t *_jit); -static void add_literal_pool_entry(jit_state_t *_jit, - struct jit_literal_pool_entry entry, - ptrdiff_t max_offset); -static void add_pending_literal(jit_state_t *_jit, jit_reloc_t src, - ptrdiff_t max_offset_bits); +static jit_bool_t add_literal_pool_entry(jit_state_t *_jit, + struct jit_literal_pool_entry entry, + uint32_t max_offset); +static jit_bool_t add_pending_literal(jit_state_t *_jit, jit_reloc_t src, + uint8_t max_offset_bits); 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, uint64_t value); @@ -187,6 +186,7 @@ jit_begin(jit_state_t *_jit, uint8_t* buf, size_t length) _jit->overflow = 0; _jit->frame_size = 0; #if JIT_NEEDS_LITERAL_POOL + ASSERT(_jit->pool->size == 0); _jit->pool->deadline = length; #endif } @@ -1229,13 +1229,20 @@ jit_load_args(jit_state_t *_jit, size_t argc, jit_operand_t args[]) } #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 -reset_literal_pool(jit_state_t *_jit, - struct jit_literal_pool *pool) +reset_literal_pool(jit_state_t *_jit, struct jit_literal_pool *pool) { pool->deadline = _jit->limit - _jit->start; pool->size = 0; - pool->byte_size = 0; 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; } -static void +static jit_bool_t 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) 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 = - _jit->pc.uc - _jit->start + max_offset - _jit->pool->byte_size; - // Assume that we might need a uint32_t for alignment, and another - // to branch over the table. - deadline -= 2 * sizeof(uint32_t); + pc_base_offset + (max_offset - literal_pool_byte_size(_jit->pool)); if (deadline < _jit->pool->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; + + return 1; } -static void +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) { struct jit_literal_pool_entry entry = { src, 0 }; - add_literal_pool_entry(_jit, entry, - (1 << (max_offset_bits + src.rsh)) - 1); + uint32_t max_inst_size = sizeof(uint32_t); + uint32_t max_offset = (1 << (max_offset_bits + src.rsh)) - max_inst_size; + return add_literal_pool_entry(_jit, entry, max_offset); } static void @@ -1340,7 +1353,10 @@ emit_literal_pool(jit_state_t *_jit, enum guard_pool guard) // FIXME: Could de-duplicate constants. 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]; uint8_t *loc = _jit->start + entry->reloc.offset; 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; diff >>= entry->reloc.rsh; + if (_jit->overflow) + return; + switch (entry->reloc.kind) { case JIT_RELOC_JMP_WITH_VENEER: patch_jmp_offset((uint32_t*) loc, diff); |