[pypy-commit] pypy arm-backend-2: port encoding of locations used for guards from the x86 backend

bivab noreply at buildbot.pypy.org
Mon Jan 9 11:56:51 CET 2012


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r51167:ffbd6f34a8c3
Date: 2012-01-04 15:58 +0100
http://bitbucket.org/pypy/pypy/changeset/ffbd6f34a8c3/

Log:	port encoding of locations used for guards from the x86 backend

diff --git a/pypy/jit/backend/arm/assembler.py b/pypy/jit/backend/arm/assembler.py
--- a/pypy/jit/backend/arm/assembler.py
+++ b/pypy/jit/backend/arm/assembler.py
@@ -11,6 +11,7 @@
 from pypy.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager,
                     ARMv7RegisterManager, check_imm_arg,
                     operations as regalloc_operations,
+                    get_fp_offset,
                     operations_with_guard as regalloc_operations_with_guard)
 from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
 from pypy.jit.backend.model import CompiledLoopToken
@@ -30,30 +31,6 @@
 
 
 class AssemblerARM(ResOpAssembler):
-    """
-    Encoding for locations in memory
-    types:
-    \xED = FLOAT
-    \xEE = REF
-    \xEF = INT
-    location:
-    \xFC = stack location
-    \xFD = imm location
-    emtpy = reg location
-    \xFE = Empty loc
-
-    \xFF = END_OF_LOCS
-    """
-    FLOAT_TYPE = '\xED'
-    REF_TYPE = '\xEE'
-    INT_TYPE = '\xEF'
-
-    STACK_LOC = '\xFC'
-    IMM_LOC = '\xFD'
-    # REG_LOC is empty
-    EMPTY_LOC = '\xFE'
-
-    END_OF_LOCS = '\xFF'
 
     STACK_FIXED_AREA = -1
 
@@ -183,132 +160,138 @@
             """mem_loc is a structure in memory describing where the values for
             the failargs are stored.  frame loc is the address of the frame
             pointer for the frame to be decoded frame """
-            return self.decode_registers_and_descr(mem_loc,
-                                            frame_pointer, stack_pointer)
+            vfp_registers = rffi.cast(rffi.LONGLONGP, stack_pointer)
+            registers = rffi.ptradd(vfp_registers, len(r.all_vfp_regs))
+            registers = rffi.cast(rffi.LONGP, registers)
+            return self.decode_registers_and_descr(mem_loc, frame_pointer,
+                                                    registers, vfp_registers)
 
         self.failure_recovery_func = failure_recovery_func
 
-    recovery_func_sign = lltype.Ptr(lltype.FuncType([lltype.Signed,
-                                lltype.Signed, lltype.Signed], lltype.Signed))
+    recovery_func_sign = lltype.Ptr(lltype.FuncType([lltype.Signed] * 3,
+                                                        lltype.Signed))
 
     @rgc.no_collect
-    def decode_registers_and_descr(self, mem_loc, frame_loc, regs_loc):
+    def decode_registers_and_descr(self, mem_loc, frame_pointer,
+                                                registers, vfp_registers):
         """Decode locations encoded in memory at mem_loc and write the values
         to the failboxes.  Values for spilled vars and registers are stored on
         stack at frame_loc """
-        # XXX check if units are correct here, when comparing words and bytes
-        # and stuff assert 0, 'check if units are correct here, when comparing
-        # words and bytes and stuff'
+        assert frame_pointer & 1 == 0
+        bytecode = rffi.cast(rffi.UCHARP, mem_loc)
+        num = 0
+        value = 0
+        fvalue = 0
+        code_inputarg = False
+        while True:
+            code = bytecode[0]
+            bytecode = rffi.ptradd(bytecode, 1)
+            if code >= self.CODE_FROMSTACK:
+                if code > 0x7F:
+                    shift = 7
+                    code &= 0x7F
+                    while True:
+                        nextcode = rffi.cast(lltype.Signed, bytecode[0])
+                        bytecode = rffi.ptradd(bytecode, 1)
+                        code |= (nextcode & 0x7F) << shift
+                        shift += 7
+                        if nextcode <= 0x7F:
+                            break
+                # load the value from the stack
+                kind = code & 3
+                code = int((code - self.CODE_FROMSTACK) >> 2)
+                if code_inputarg:
+                    code = ~code
+                    code_inputarg = False
+                if kind == self.DESCR_FLOAT:
+                    # we use code + 1 to get the hi word of the double worded float
+                    stackloc = frame_pointer - get_fp_offset(int(code) + 1)
+                    assert stackloc & 3 == 0
+                    fvalue = rffi.cast(rffi.LONGLONGP, stackloc)[0]
+                else:
+                    stackloc = frame_pointer - get_fp_offset(int(code))
+                    assert stackloc & 1 == 0
+                    value = rffi.cast(rffi.LONGP, stackloc)[0]
+            else:
+                # 'code' identifies a register: load its value
+                kind = code & 3
+                if kind == self.DESCR_SPECIAL:
+                    if code == self.CODE_HOLE:
+                        num += 1
+                        continue
+                    if code == self.CODE_INPUTARG:
+                        code_inputarg = True
+                        continue
+                    assert code == self.CODE_STOP
+                    break
+                code >>= 2
+                if kind == self.DESCR_FLOAT:
+                    fvalue = vfp_registers[code]
+                else:
+                    value = registers[code]
+            # store the loaded value into fail_boxes_<type>
+            if kind == self.DESCR_FLOAT:
+                tgt = self.fail_boxes_float.get_addr_for_num(num)
+                rffi.cast(rffi.LONGLONGP, tgt)[0] = fvalue
+            else:
+                if kind == self.DESCR_INT:
+                    tgt = self.fail_boxes_int.get_addr_for_num(num)
+                elif kind == self.DESCR_REF:
+                    assert (value & 3) == 0, "misaligned pointer"
+                    tgt = self.fail_boxes_ptr.get_addr_for_num(num)
+                else:
+                    assert 0, "bogus kind"
+                rffi.cast(rffi.LONGP, tgt)[0] = value
+            num += 1
+        self.fail_boxes_count = num
+        fail_index = rffi.cast(rffi.INTP, bytecode)[0]
+        fail_index = rffi.cast(lltype.Signed, fail_index)
+        return fail_index
 
-        enc = rffi.cast(rffi.CCHARP, mem_loc)
-        frame_depth = frame_loc - (regs_loc + len(r.all_regs)
-                            * WORD + len(r.all_vfp_regs) * DOUBLE_WORD)
-        assert (frame_loc - frame_depth) % 4 == 0
-        stack = rffi.cast(rffi.CCHARP, frame_loc - frame_depth)
-        assert regs_loc % 4 == 0
-        vfp_regs = rffi.cast(rffi.CCHARP, regs_loc)
-        assert (regs_loc + len(r.all_vfp_regs) * DOUBLE_WORD) % 4 == 0
-        assert frame_depth >= 0
-
-        regs = rffi.cast(rffi.CCHARP,
-                    regs_loc + len(r.all_vfp_regs) * DOUBLE_WORD)
-        i = -1
-        fail_index = -1
-        while(True):
-            i += 1
-            fail_index += 1
-            res = enc[i]
-            if res == self.END_OF_LOCS:
+    def decode_inputargs(self, code):
+        descr_to_box_type = [REF, INT, FLOAT]
+        bytecode = rffi.cast(rffi.UCHARP, code)
+        arglocs = []
+        code_inputarg = False
+        while 1:
+            # decode the next instruction from the bytecode
+            code = rffi.cast(lltype.Signed, bytecode[0])
+            bytecode = rffi.ptradd(bytecode, 1)
+            if code >= self.CODE_FROMSTACK:
+                # 'code' identifies a stack location
+                if code > 0x7F:
+                    shift = 7
+                    code &= 0x7F
+                    while True:
+                        nextcode = rffi.cast(lltype.Signed, bytecode[0])
+                        bytecode = rffi.ptradd(bytecode, 1)
+                        code |= (nextcode & 0x7F) << shift
+                        shift += 7
+                        if nextcode <= 0x7F:
+                            break
+                kind = code & 3
+                code = (code - self.CODE_FROMSTACK) >> 2
+                if code_inputarg:
+                    code = ~code
+                    code_inputarg = False
+                loc = ARMFrameManager.frame_pos(code, descr_to_box_type[kind])
+            elif code == self.CODE_STOP:
                 break
-            if res == self.EMPTY_LOC:
+            elif code == self.CODE_HOLE:
                 continue
-
-            group = res
-            i += 1
-            res = enc[i]
-            if res == self.IMM_LOC:
-                # imm value
-                if group == self.INT_TYPE or group == self.REF_TYPE:
-                    value = decode32(enc, i + 1)
-                    i += 4
+            elif code == self.CODE_INPUTARG:
+                code_inputarg = True
+                continue
+            else:
+                # 'code' identifies a register
+                kind = code & 3
+                code >>= 2
+                if kind == self.DESCR_FLOAT:
+                    loc = r.all_vfp_regs[code]
                 else:
-                    assert group == self.FLOAT_TYPE
-                    adr = decode32(enc, i + 1)
-                    tp = rffi.CArrayPtr(longlong.FLOATSTORAGE)
-                    value = rffi.cast(tp, adr)[0]
-                    self.fail_boxes_float.setitem(fail_index, value)
-                    i += 4
-                    continue
-            elif res == self.STACK_LOC:
-                stack_loc = decode32(enc, i + 1)
-                i += 4
-                if group == self.FLOAT_TYPE:
-                    value = decode64(stack,
-                            frame_depth - (stack_loc + 1) * WORD)
-                    fvalue = rffi.cast(longlong.FLOATSTORAGE, value)
-                    self.fail_boxes_float.setitem(fail_index, fvalue)
-                    continue
-                else:
-                    value = decode32(stack, frame_depth - stack_loc * WORD)
-            else:  # REG_LOC
-                reg = ord(enc[i])
-                if group == self.FLOAT_TYPE:
-                    value = decode64(vfp_regs, reg * DOUBLE_WORD)
-                    self.fail_boxes_float.setitem(fail_index, value)
-                    continue
-                else:
-                    value = decode32(regs, reg * WORD)
-
-            if group == self.INT_TYPE:
-                self.fail_boxes_int.setitem(fail_index, value)
-            elif group == self.REF_TYPE:
-                assert (value & 3) == 0, "misaligned pointer"
-                tgt = self.fail_boxes_ptr.get_addr_for_num(fail_index)
-                rffi.cast(rffi.LONGP, tgt)[0] = value
-            else:
-                assert 0, 'unknown type'
-
-        assert enc[i] == self.END_OF_LOCS
-        descr = decode32(enc, i + 1)
-        self.fail_boxes_count = fail_index
-        self.fail_force_index = frame_loc
-        return descr
-
-    def decode_inputargs(self, enc):
-        locs = []
-        j = 0
-        while enc[j] != self.END_OF_LOCS:
-            res = enc[j]
-            if res == self.EMPTY_LOC:
-                j += 1
-                continue
-
-            assert res in [self.FLOAT_TYPE, self.INT_TYPE, self.REF_TYPE], \
-                        'location type is not supported'
-            res_type = res
-            j += 1
-            res = enc[j]
-            if res == self.IMM_LOC:
-                # XXX decode imm if necessary
-                assert 0, 'Imm Locations are not supported'
-            elif res == self.STACK_LOC:
-                if res_type == self.FLOAT_TYPE:
-                    t = FLOAT
-                elif res_type == self.INT_TYPE:
-                    t = INT
-                else:
-                    t = REF
-                stack_loc = decode32(enc, j + 1)
-                loc = ARMFrameManager.frame_pos(stack_loc, t)
-                j += 4
-            else:  # REG_LOC
-                if res_type == self.FLOAT_TYPE:
-                    loc = r.all_vfp_regs[ord(res)]
-                else:
-                    loc = r.all_regs[ord(res)]
-            j += 1
-            locs.append(loc)
-        return locs
+                    loc = r.all_regs[code]
+            arglocs.append(loc)
+        return arglocs[:]
 
     def _build_malloc_slowpath(self):
         mc = ARMv7Builder()
@@ -364,85 +347,78 @@
         return mc.materialize(self.cpu.asmmemmgr, [],
                                    self.cpu.gc_ll_descr.gcrootmap)
 
-    def gen_descr_encoding(self, descr, args, arglocs):
-        # The size of the allocated memory is based on the following sizes
-        # first argloc is the frame depth and not considered for the memory
-        # allocation
-        # 4 bytes for the value
-        # 1 byte for the type
-        # 1 byte for the location
-        # 1 separator byte
-        # 4 bytes for the faildescr
-        # const floats are stored in memory and the box contains the address
-        memsize = (len(arglocs) - 1) * 6 + 5
+    DESCR_REF       = 0x00
+    DESCR_INT       = 0x01
+    DESCR_FLOAT     = 0x02
+    DESCR_SPECIAL   = 0x03
+    CODE_FROMSTACK  = 64
+    CODE_STOP       = 0 | DESCR_SPECIAL
+    CODE_HOLE       = 4 | DESCR_SPECIAL
+    CODE_INPUTARG   = 8 | DESCR_SPECIAL
+
+    def gen_descr_encoding(self, descr, failargs, locs):
+        buf = []
+        for i in range(len(failargs)):
+            arg = failargs[i]
+            if arg is not None:
+                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 loc.is_stack():
+                    pos = loc.position
+                    if pos < 0:
+                        buf.append(chr(self.CODE_INPUTARG))
+                        pos = ~pos
+                    n = self.CODE_FROMSTACK // 4 + pos
+                else:
+                    assert loc.is_reg() or loc.is_vfp_reg()
+                    n = loc.value
+                n = kind + 4 * n
+                while n > 0x7F:
+                    buf.append(chr((n & 0x7F) | 0x80))
+                    n >>= 7
+            else:
+                n = self.CODE_HOLE
+            buf.append(chr(n))
+        buf.append(chr(self.CODE_STOP))
+
+        fdescr = self.cpu.get_fail_descr_number(descr)
+        buf.append(chr(fdescr & 0xFF))
+        buf.append(chr(fdescr >> 8 & 0xFF))
+        buf.append(chr(fdescr >> 16 & 0xFF))
+        buf.append(chr(fdescr >> 24 & 0xFF))
+
+        # assert that the fail_boxes lists are big enough
+        assert len(failargs) <= self.fail_boxes_int.SIZE
+
+        memsize = len(buf)
         memaddr = self.datablockwrapper.malloc_aligned(memsize, alignment=1)
         mem = rffi.cast(rffi.CArrayPtr(lltype.Char), memaddr)
-        i = 0
-        j = 0
-        while i < len(args):
-            if arglocs[i + 1]:
-                arg = args[i]
-                loc = arglocs[i + 1]
-                if arg.type == INT:
-                    mem[j] = self.INT_TYPE
-                    j += 1
-                elif arg.type == REF:
-                    mem[j] = self.REF_TYPE
-                    j += 1
-                elif arg.type == FLOAT:
-                    mem[j] = self.FLOAT_TYPE
-                    j += 1
-                else:
-                    assert 0, 'unknown type'
-
-                if loc.is_reg() or loc.is_vfp_reg():
-                    mem[j] = chr(loc.value)
-                    j += 1
-                elif loc.is_imm() or loc.is_imm_float():
-                    assert (arg.type == INT or arg.type == REF
-                                or arg.type == FLOAT)
-                    mem[j] = self.IMM_LOC
-                    encode32(mem, j + 1, loc.getint())
-                    j += 5
-                else:
-                    assert loc.is_stack()
-                    mem[j] = self.STACK_LOC
-                    if arg.type == FLOAT:
-                        # Float locs store the location number with an offset
-                        # of 1 -.- so we need to take this into account here
-                        # when generating the encoding
-                        encode32(mem, j + 1, loc.position - 1)
-                    else:
-                        encode32(mem, j + 1, loc.position)
-                    j += 5
-            else:
-                mem[j] = self.EMPTY_LOC
-                j += 1
-            i += 1
-
-        mem[j] = chr(0xFF)
-
-        n = self.cpu.get_fail_descr_number(descr)
-        encode32(mem, j + 1, n)
+        for i in range(memsize):
+            mem[i] = buf[i]
         return memaddr
 
     def _gen_path_to_exit_path(self, descr, args, arglocs,
                                             save_exc, fcond=c.AL):
         assert isinstance(save_exc, bool)
-        memaddr = self.gen_descr_encoding(descr, args, arglocs)
+        memaddr = self.gen_descr_encoding(descr, args, arglocs[1:])
         self.gen_exit_code(self.mc, memaddr, save_exc, fcond)
         return memaddr
 
     def gen_exit_code(self, mc, memaddr, save_exc, fcond=c.AL):
         assert isinstance(save_exc, bool)
         self.mc.gen_load_int(r.ip.value, memaddr)
-        #mc.LDR_ri(r.ip.value, r.pc.value, imm=WORD)
         if save_exc:
             path = self._leave_jitted_hook_save_exc
         else:
             path = self._leave_jitted_hook
         mc.B(path)
-        #mc.write32(memaddr)
 
     def align(self):
         while(self.mc.currpos() % FUNC_ALIGN != 0):
@@ -576,9 +552,8 @@
         self._dump(operations, 'bridge')
         assert isinstance(faildescr, AbstractFailDescr)
         code = faildescr._arm_failure_recovery_code
-        enc = rffi.cast(rffi.CCHARP, code)
         frame_depth = faildescr._arm_current_frame_depth
-        arglocs = self.decode_inputargs(enc)
+        arglocs = self.decode_inputargs(code)
         if not we_are_translated():
             assert len(inputargs) == len(arglocs)
 
diff --git a/pypy/jit/backend/arm/locations.py b/pypy/jit/backend/arm/locations.py
--- a/pypy/jit/backend/arm/locations.py
+++ b/pypy/jit/backend/arm/locations.py
@@ -80,9 +80,6 @@
     def is_imm(self):
         return True
 
-    def as_key(self):
-        return self.value + 40
-
 
 class ConstFloatLoc(AssemblerLocation):
     """This class represents an imm float value which is stored in memory at
@@ -103,9 +100,6 @@
     def is_imm_float(self):
         return True
 
-    def as_key(self):
-        return -1 * self.value
-
 
 class StackLocation(AssemblerLocation):
     _immutable_ = True
@@ -132,7 +126,7 @@
         return True
 
     def as_key(self):
-        return -self.position
+        return self.position + 10000
 
 
 def imm(i):
diff --git a/pypy/jit/backend/arm/regalloc.py b/pypy/jit/backend/arm/regalloc.py
--- a/pypy/jit/backend/arm/regalloc.py
+++ b/pypy/jit/backend/arm/regalloc.py
@@ -327,6 +327,7 @@
         count = 0
         n_register_args = len(r.argument_regs)
         cur_frame_pos = - (self.assembler.STACK_FIXED_AREA / WORD) + 1
+        cur_frame_pos = 1 - (self.assembler.STACK_FIXED_AREA // WORD)
         for box in inputargs:
             assert isinstance(box, Box)
             # handle inputargs in argument registers


More information about the pypy-commit mailing list