[pypy-commit] pypy default: If a JMP and CALL instruction goes straight to a further JMP, emit
arigo
noreply at buildbot.pypy.org
Tue Jan 20 15:18:23 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r75449:dde0fac9f1a4
Date: 2015-01-20 15:02 +0100
http://bitbucket.org/pypy/pypy/changeset/dde0fac9f1a4/
Log: If a JMP and CALL instruction goes straight to a further JMP, emit
the original JMP or CALL to go directly to the target.
diff --git a/rpython/jit/backend/x86/codebuf.py b/rpython/jit/backend/x86/codebuf.py
--- a/rpython/jit/backend/x86/codebuf.py
+++ b/rpython/jit/backend/x86/codebuf.py
@@ -46,9 +46,9 @@
def copy_to_raw_memory(self, addr):
self._copy_to_raw_memory(addr)
if self.relocations is not None:
- for reloc in self.relocations:
+ for reloc in self.relocations: # for 32-bit only
p = addr + reloc
- adr = rffi.cast(rffi.LONGP, p - WORD)
- adr[0] = intmask(adr[0] - p)
+ adr = rffi.cast(rffi.INTP, p - 4)
+ adr[0] = rffi.cast(rffi.INT, intmask(adr[0]) - p)
valgrind.discard_translations(addr, self.get_relative_pos())
self._dump(addr, "jit-backend-dump", backend_name)
diff --git a/rpython/jit/backend/x86/regloc.py b/rpython/jit/backend/x86/regloc.py
--- a/rpython/jit/backend/x86/regloc.py
+++ b/rpython/jit/backend/x86/regloc.py
@@ -516,6 +516,10 @@
if code == possible_code:
val = getattr(loc, "value_" + possible_code)()
if possible_code == 'i':
+ # This is for CALL or JMP only. If target is
+ # immediately starting with another JMP instruction,
+ # follow it now.
+ val = self._follow_jump_instructions(val)
if self.WORD == 4:
_rx86_getattr(self, name + "_l")(val)
self.add_pending_relocation()
@@ -533,6 +537,17 @@
return func_with_new_name(INSN, "INSN_" + name)
+ _do_follow_jump_instructions = True
+
+ def _follow_jump_instructions(self, addr):
+ if not self._do_follow_jump_instructions or addr == 0: # for tests
+ return addr
+ # 'addr' is an absolute address here
+ while rffi.cast(rffi.CCHARP, addr)[0] == '\xE9': # JMP <4 bytes>
+ addr += 5
+ addr += intmask(rffi.cast(rffi.INTP, addr - 4)[0])
+ return addr
+
def _addr_as_reg_offset(self, addr):
# Encodes a (64-bit) address as an offset from the scratch register.
# If we are within a "reuse_scratch_register" block, we remember the
diff --git a/rpython/jit/backend/x86/test/test_regloc.py b/rpython/jit/backend/x86/test/test_regloc.py
--- a/rpython/jit/backend/x86/test/test_regloc.py
+++ b/rpython/jit/backend/x86/test/test_regloc.py
@@ -4,6 +4,7 @@
from rpython.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as
from rpython.jit.backend.x86.assembler import heap
from rpython.jit.backend.x86.arch import IS_X86_64, IS_X86_32
+from rpython.jit.backend.x86 import codebuf
from rpython.rlib.rarithmetic import intmask
import py.test
@@ -62,11 +63,11 @@
def test_relocation():
from rpython.rtyper.lltypesystem import lltype, rffi
- from rpython.jit.backend.x86 import codebuf
for target in [0x01020304, -0x05060708, 0x0102030405060708]:
if target > sys.maxint:
continue
mc = codebuf.MachineCodeBlockWrapper()
+ mc._do_follow_jump_instructions = False
mc.CALL(ImmedLoc(target))
length = mc.get_relative_pos()
buf = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw')
@@ -96,6 +97,38 @@
assert ''.join([buf[i] for i in range(length)]) == expected
lltype.free(buf, flavor='raw')
+def test_follow_jump_instructions_32():
+ buf = lltype.malloc(rffi.CCHARP.TO, 80, flavor='raw')
+ raw = rffi.cast(lltype.Signed, buf)
+ mc = codebuf.MachineCodeBlockWrapper(); mc.WORD = 4; mc.relocations = []
+ mc.RET()
+ mc.copy_to_raw_memory(raw)
+ mc = codebuf.MachineCodeBlockWrapper(); mc.WORD = 4; mc.relocations = []
+ mc.JMP(imm(raw))
+ mc.copy_to_raw_memory(raw + 20)
+ assert buf[20] == '\xE9' # JMP
+ assert buf[21] == '\xE7' # -25
+ assert buf[22] == '\xFF'
+ assert buf[23] == '\xFF'
+ assert buf[24] == '\xFF'
+ mc = codebuf.MachineCodeBlockWrapper(); mc.WORD = 4; mc.relocations = []
+ mc.JMP(imm(raw + 20))
+ mc.copy_to_raw_memory(raw + 40)
+ assert buf[40] == '\xE9' # JMP
+ assert buf[41] == '\xD3' # -45
+ assert buf[42] == '\xFF'
+ assert buf[43] == '\xFF'
+ assert buf[44] == '\xFF'
+ mc = codebuf.MachineCodeBlockWrapper(); mc.WORD = 4; mc.relocations = []
+ mc.CALL(imm(raw + 40))
+ mc.copy_to_raw_memory(raw + 60)
+ assert buf[60] == '\xE8' # CALL
+ assert buf[61] == '\xBF' # -65
+ assert buf[62] == '\xFF'
+ assert buf[63] == '\xFF'
+ assert buf[64] == '\xFF'
+ lltype.free(buf, flavor='raw')
+
class Test64Bits:
More information about the pypy-commit
mailing list