[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