[pypy-svn] r69452 - in pypy/branch/shorter-guard-path/pypy/jit/backend/x86: . test

arigo at codespeak.net arigo at codespeak.net
Thu Nov 19 16:29:12 CET 2009


Author: arigo
Date: Thu Nov 19 16:29:12 2009
New Revision: 69452

Modified:
   pypy/branch/shorter-guard-path/pypy/jit/backend/x86/assembler.py
   pypy/branch/shorter-guard-path/pypy/jit/backend/x86/test/test_assembler.py
Log:
Trying another approach...  In-progress.


Modified: pypy/branch/shorter-guard-path/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/shorter-guard-path/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/shorter-guard-path/pypy/jit/backend/x86/assembler.py	Thu Nov 19 16:29:12 2009
@@ -1,7 +1,7 @@
 import sys, os
 import ctypes
 from pypy.jit.backend.llsupport import symbolic
-from pypy.jit.metainterp.history import Const, Box, BoxPtr, REF, FLOAT
+from pypy.jit.metainterp.history import Const, Box, BoxPtr, INT, REF, FLOAT
 from pypy.jit.metainterp.history import AbstractFailDescr
 from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr, llmemory
 from pypy.rpython.lltypesystem.rclass import OBJECT
@@ -86,7 +86,7 @@
         self.fail_boxes_int = NonmovableGrowableArraySigned()
         self.fail_boxes_ptr = NonmovableGrowableArrayGCREF()
         self.fail_boxes_float = NonmovableGrowableArrayFloat()
-        self.setup_failure_recovery()
+        self.failure_recovery_code = [0, 0]
 
     def leave_jitted_hook(self):
         # XXX BIG FAT WARNING XXX
@@ -123,7 +123,8 @@
             # 'mc2' is for guard recovery code
             self.mc = MachineCodeBlockWrapper()
             self.mc2 = MachineCodeBlockWrapper()
-            self._build_failure_recovery_builder_trampoline()
+            self._build_failure_recovery(False)
+            self._build_failure_recovery(True)
 
     def assemble_loop(self, inputargs, operations, looptoken):
         """adds the following attributes to looptoken:
@@ -757,10 +758,9 @@
         self._no_const_locs(failargs)
         exc = (guard_opnum == rop.GUARD_EXCEPTION or
                guard_opnum == rop.GUARD_NO_EXCEPTION)
-        faildescr._x86_faillocs = fail_locs
-        return self.generate_quick_failure(faildescr, failargs, exc)
+        return self.generate_quick_failure(faildescr, failargs, fail_locs, exc)
 
-    def generate_quick_failure(self, faildescr, failargs, exc):
+    def generate_quick_failure(self, faildescr, failargs, fail_locs, exc):
         """Generate the initial code for handling a failure.  We try to
         keep it as compact as possible.  The idea is that this code is
         executed at most once (and very often, zero times); when
@@ -774,93 +774,78 @@
         mc = self.mc2._mc
         addr = mc.tell()
         mc.PUSH(imm32(fail_index))
-        mc.CALL(rel32(self.failure_recovery_code))
-        # write a bitfield of 0's (int or float argument) or 1's (ref argument)
-        self.write_bitfield_for_failargs(mc, failargs, exc)
-        if not we_are_translated():
-            faildescr._x86_exc_locs_are_ref = (
-                exc, [v.type == REF for v in failargs])
+        mc.CALL(rel32(self.failure_recovery_code[exc]))
+        # write tight data that describes the failure recovery
+        self.write_failure_recovery_description(mc, failargs, fail_locs)
         return addr
 
-    def write_bitfield_for_failargs(self, mc, failargs, exc):
-        #print 'writing:', mc.tell()
-        #mc.writechr(0xDD)
-        bitfield = int(exc)    # the first bit: "save exceptions"
-        bit = 0x02
+    DESCR_INT       = 0x00
+    DESCR_REF       = 0x01
+    DESCR_FLOAT     = 0x02
+    DESCR_FROMSTACK = 8
+    DESCR_STOP      = DESCR_INT + 4*esp.op
+
+    def write_failure_recovery_description(self, mc, failargs, locs):
         for i in range(len(failargs)):
-            if bit == 0x100:
-                mc.writechr(bitfield)
-                bitfield = 0
-                bit = 0x01
-            if failargs[i].type == REF:
-                bitfield |= bit
-            bit <<= 1
-        mc.writechr(bitfield)
-        #mc.writechr(0xCC)
-
-    def getbit_from_bitfield(self, bitfield_ptr, i):
-        byte = ord(bitfield_ptr[i >> 3])
-        return bool(byte & (1 << (i & 7)))
-
-    def setup_failure_recovery(self):
-
-        def failure_recovery_builder(fail_index, bitfield_ptr):
-            #assert bitfield_ptr[0] == chr(0xDD)
-            faildescr = self.cpu.get_fail_descr_from_number(fail_index)
-            locs = faildescr._x86_faillocs
-            #assert bitfield_ptr[1 + (1+len(locs)+7)//8] == chr(0xCC)
-            exc = self.getbit_from_bitfield(bitfield_ptr, 0)    # the first bit
-            locs_are_ref = [self.getbit_from_bitfield(bitfield_ptr, 1 + i)
-                            for i in range(len(locs))]
-            if not we_are_translated():
-                #print 'completing:', rffi.cast(lltype.Signed, bitfield_ptr)
-                assert (exc, locs_are_ref) == faildescr._x86_exc_locs_are_ref
-            addr = self.mc2.tell()
-            self.generate_failure(self.mc2, fail_index, locs, exc,
-                                  locs_are_ref)
-            self.patch_jump(faildescr, addr)
-            return addr
-
-        self.failure_recovery_builder = failure_recovery_builder
-        self.failure_recovery_code = 0
-
-    _FAILURE_RECOVERY_BUILDER = lltype.Ptr(lltype.FuncType(
-        [lltype.Signed, rffi.CCHARP], lltype.Signed))
-
-    def _build_failure_recovery_builder_trampoline(self):
-        failure_recovery_builder = llhelper(self._FAILURE_RECOVERY_BUILDER,
-                                            self.failure_recovery_builder)
-        failure_recovery_builder = rffi.cast(lltype.Signed,
-                                             failure_recovery_builder)
+            arg = failargs[i]
+            if arg.type == REF:
+                kind = self.DESCR_REF
+            elif arg.type == INT:
+                kind = self.DESCR_INT
+            elif arg.type == FLOAT:
+                kind = self.DESCR_FLOAT
+            else:
+                raise AssertionError("bogus kind")
+            loc = locs[i]
+            if isinstance(loc, REG):
+                n = loc.op
+            else:
+                n = self.DESCR_FROMSTACK + loc.position
+            n = kind + 4*n
+            while n > 0x7F:
+                mc.writechr((n & 0x7F) | 0x80)
+                n >>= 7
+            mc.writechr(n)
+        mc.writechr(self.DESCR_STOP)
+
+    def _build_failure_recovery(self, exc):
         mc = self.mc2
+        esp_offset = 0
         code = mc.tell()
-        mc.PUSH(ebp)
-        mc.MOV(ebp, esp)
-        # push all registers on the stack
-        mc.PUSHA()
+        # push the xmm registers on the stack
         if self.cpu.supports_floats:
             mc.SUB(esp, imm(8*8))
+            esp_offset += 8*8
             for i in range(8):
                 mc.MOVSD(mem64(esp, 8*i), xmm_registers[i])
+        # push eax, edx and ecx on the stack
+        mc.PUSH(eax)
+        mc.PUSH(edx)
+        mc.PUSH(ecx)
+        esp_offset += 3*4
         # really call the failure recovery builder code
-        mc.PUSH(mem(ebp, 4))        # the return address: ptr to bitfield
-        mc.PUSH(mem(ebp, 8))        # fail_index
+        mc.PUSH(mem(esp, esp_offset))    # the return address: ptr to bitfield
+        esp_offset += 4
+        mc.PUSH(mem(esp, esp_offset+4))  # fail_index
+        esp_offset += 4
         mc.CALL(rel32(failure_recovery_builder))
         mc.ADD(esp, imm(8))
-        # save the return value into ebp+4.  This is the address of the code
-        # written by generate_failure.  Doing so overwrites this function's
-        # own return address, which was just a ptr to the bitfield, so far.
-        mc.MOV(mem(ebp, 4), eax)
+        esp_offset -= 8
+        # the return value in eax is the address of the code written by
+        # generate_failure.  We write it over this function's own return
+        # address, which was just a ptr to the bitfield, so far.
+        mc.MOV(mem(esp, esp_offset), eax)
         # pop all registers
+        mc.POP(ecx)
+        mc.POP(edx)
+        mc.POP(eax)
         if self.cpu.supports_floats:
             for i in range(8):
                 mc.MOVSD(xmm_registers[i], mem64(esp, 8*i))
             mc.ADD(esp, imm(8*8))
-        mc.POPA()
         # epilogue
-        mc.POP(ebp)
         mc.RET(imm16(4))
-        self.failure_recovery_code = code
+        self.failure_recovery_code[exc] = code
 
     def generate_failure(self, mc, fail_index, locs, exc, locs_are_ref):
         for i in range(len(locs)):

Modified: pypy/branch/shorter-guard-path/pypy/jit/backend/x86/test/test_assembler.py
==============================================================================
--- pypy/branch/shorter-guard-path/pypy/jit/backend/x86/test/test_assembler.py	(original)
+++ pypy/branch/shorter-guard-path/pypy/jit/backend/x86/test/test_assembler.py	Thu Nov 19 16:29:12 2009
@@ -1,5 +1,7 @@
+from pypy.jit.backend.x86.ri386 import *
 from pypy.jit.backend.x86.assembler import Assembler386
-from pypy.jit.metainterp.history import BoxInt, BoxPtr
+from pypy.jit.backend.x86.regalloc import X86StackManager
+from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat
 
 
 class FakeCPU:
@@ -12,23 +14,32 @@
         self.content.append(n)
 
 
-def test_bitfield():
+def test_write_failure_recovery_description():
     assembler = Assembler386(FakeCPU())
     mc = FakeMC()
-    assembler.write_bitfield_for_failargs(mc, [BoxInt(), BoxPtr()], False)
-    assert mc.content == [4]
-    bitfield = map(chr, mc.content)
-    assert assembler.getbit_from_bitfield(bitfield, 0) == False
-    assert assembler.getbit_from_bitfield(bitfield, 1) == False
-    assert assembler.getbit_from_bitfield(bitfield, 2) == True
-
-def test_larger_bitfield():
-    assembler = Assembler386(FakeCPU())
-    mc = FakeMC()
-    lst = [BoxInt(), BoxPtr(), BoxPtr()] * 6
-    assembler.write_bitfield_for_failargs(mc, lst, True)
-    bitfield = map(chr, mc.content)
-    assert assembler.getbit_from_bitfield(bitfield, 0) == True
-    for i in range(len(lst)):
-        expected = (lst[i].__class__ == BoxPtr)
-        assert assembler.getbit_from_bitfield(bitfield, 1+i) == expected
+    failargs = [BoxInt(), BoxPtr(), BoxFloat()] * 3
+    locs = [X86StackManager.stack_pos(0, 1),
+            X86StackManager.stack_pos(1, 1),
+            X86StackManager.stack_pos(10, 2),
+            X86StackManager.stack_pos(100, 1),
+            X86StackManager.stack_pos(101, 1),
+            X86StackManager.stack_pos(110, 2),
+            ebx,
+            esi,
+            xmm2]
+    assembler.write_failure_recovery_description(mc, failargs, locs)
+    nums = [0 + 4*(8+0),
+            1 + 4*(8+1),
+            2 + 4*(8+10),
+            0 + 4*(8+100),
+            1 + 4*(8+101),
+            2 + 4*(8+110),
+            0 + 4*ebx.op,
+            1 + 4*esi.op,
+            2 + 4*xmm2.op]
+    double_byte_nums = []
+    for num in nums[3:6]:
+        double_byte_nums.append((num & 0x7F) | 0x80)
+        double_byte_nums.append(num >> 7)
+    assert mc.content == (nums[:3] + double_byte_nums + nums[6:] +
+                          [assembler.DESCR_STOP])



More information about the Pypy-commit mailing list