[pypy-commit] pypy jitframe-on-heap: support for new guards handling

bivab noreply at buildbot.pypy.org
Tue Jan 29 15:16:33 CET 2013


Author: David Schneider <david.schneider at picle.org>
Branch: jitframe-on-heap
Changeset: r60682:f40c4e68b860
Date: 2013-01-29 14:56 +0100
http://bitbucket.org/pypy/pypy/changeset/f40c4e68b860/

Log:	support for new guards handling

diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -8,7 +8,7 @@
                                     N_REGISTERS_SAVED_BY_MALLOC, \
                                     JITFRAME_FIXED_SIZE, FRAME_FIXED_SIZE
 from rpython.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
-from rpython.jit.backend.arm.locations import get_fp_offset
+from rpython.jit.backend.arm.locations import get_fp_offset, imm
 from rpython.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager,
                     CoreRegisterManager, check_imm_arg,
                     operations as regalloc_operations,
@@ -372,48 +372,63 @@
         # see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null
         self.mc.CMP_ri(r.r0.value, 0)
         self.mc.B(self.propagate_exception_path, c=c.EQ)
+    
+    def _push_all_regs_to_jitframe(self, mc, ignored_regs, withfloats,
+                                callee_only=False):
+        if callee_only:
+            regs = CoreRegisterManager.save_around_call_regs
+        else:
+            regs = CoreRegisterManager.all_regs
+        # use STMDB ops here
+        for i, gpr in enumerate(regs):
+            if gpr in ignored_regs:
+                continue
+            mc.STR_ri(gpr.value, r.fp.value, i * WORD)
+        if withfloats:
+            assert 0, 'implement me'
 
     def _build_failure_recovery(self, exc, withfloats=False):
         mc = ARMv7Builder()
-        failure_recovery = llhelper(self._FAILURE_RECOVERY_FUNC,
-                                            self.failure_recovery_func)
+        self._push_all_regs_to_jitframe(mc, [], withfloats)
         self._insert_checks(mc)
-        if withfloats:
-            f = r.all_vfp_regs
-        else:
-            f = []
-        with saved_registers(mc, r.all_regs, f):
-            if exc:
-                # We might have an exception pending.  Load it into r4
-                # (this is a register saved across calls)
-                mc.gen_load_int(r.r5.value, self.cpu.pos_exc_value())
-                mc.LDR_ri(r.r4.value, r.r5.value)
-                # clear the exc flags
-                mc.gen_load_int(r.r6.value, 0)
-                mc.STR_ri(r.r6.value, r.r5.value)
-                mc.gen_load_int(r.r5.value, self.cpu.pos_exception())
-                mc.STR_ri(r.r6.value, r.r5.value)
-            # move mem block address, to r0 to pass as
-            mc.MOV_rr(r.r0.value, r.lr.value)
-            # pass the current frame pointer as second param
-            mc.MOV_rr(r.r1.value, r.fp.value)
-            # pass the current stack pointer as third param
-            mc.MOV_rr(r.r2.value, r.sp.value)
-            self._insert_checks(mc)
-            mc.BL(rffi.cast(lltype.Signed, failure_recovery))
-            if exc:
-                # save ebx into 'jf_guard_exc'
-                from rpython.jit.backend.llsupport.descr import unpack_fielddescr
-                descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
-                offset, size, _ = unpack_fielddescr(descrs.jf_guard_exc)
-                mc.STR_rr(r.r4.value, r.r0.value, offset, cond=c.AL)
-            mc.MOV_rr(r.ip.value, r.r0.value)
-        mc.MOV_rr(r.r0.value, r.ip.value)
-        self.gen_func_epilog(mc=mc)
-        rawstart = mc.materialize(self.cpu.asmmemmgr, [],
-                                   self.cpu.gc_ll_descr.gcrootmap)
+
+        if exc:
+            # We might have an exception pending.  Load it into r4
+            # (this is a register saved across calls)
+            mc.gen_load_int(r.r5.value, self.cpu.pos_exc_value())
+            mc.LDR_ri(r.r4.value, r.r5.value)
+            # clear the exc flags
+            mc.gen_load_int(r.r6.value, 0)
+            mc.STR_ri(r.r6.value, r.r5.value) # pos_exc_value is still in r5
+            mc.gen_load_int(r.r5.value, self.cpu.pos_exception())
+            mc.STR_ri(r.r6.value, r.r5.value)
+            # save r4 into 'jf_guard_exc'
+            offset = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+            assert check_imm_arg(abs(offset))
+            mc.STR_ri(r.r4.value, r.fp.value, imm=offset)
+        # now we return from the complete frame, which starts from
+        # _call_header_with_stack_check().  The LEA in _call_footer below
+        # throws away most of the frame, including all the PUSHes that we
+        # did just above.
+        ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
+        assert check_imm_arg(abs(ofs))
+        ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+        assert check_imm_arg(abs(ofs2))
+        base_ofs = self.cpu.get_baseofs_of_frame_field()
+        # store the gcmap
+        mc.POP([r.ip.value])
+        mc.STR_ri(r.ip.value, r.fp.value, imm=ofs2)
+        # store the descr
+        mc.POP([r.ip.value])
+        mc.STR_ri(r.ip.value, r.fp.value, imm=ofs)
+
+        # set return value
+        assert check_imm_arg(base_ofs)
+        mc.SUB_ri(r.r0.value, r.fp.value, base_ofs)
+
+        self.gen_func_epilog(mc)
+        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
         self.failure_recovery_code[exc + 2 * withfloats] = rawstart
-        self.mc = None
 
     DESCR_REF       = 0x00
     DESCR_INT       = 0x01
@@ -459,30 +474,37 @@
 
 
     def generate_quick_failure(self, guardtok, fcond=c.AL):
-        assert isinstance(guardtok.save_exc, bool)
-        fail_index = self.cpu.get_fail_descr_number(guardtok.descr)
+        assert isinstance(guardtok.exc, bool)
         startpos = self.mc.currpos()
         withfloats = False
         for box in guardtok.failargs:
             if box is not None and box.type == FLOAT:
                 withfloats = True
                 break
-        exc = guardtok.save_exc
+        exc = guardtok.exc
         target = self.failure_recovery_code[exc + 2 * withfloats]
-        assert target != 0
+        fail_descr = cast_instance_to_gcref(guardtok.faildescr)
+        fail_descr = rffi.cast(lltype.Signed, fail_descr)
+        positions = [0] * len(guardtok.fail_locs)
+        for i, loc in enumerate(guardtok.fail_locs):
+            if loc is None:
+                positions[i] = -1
+            elif loc.is_stack():
+                positions[i] = loc.value
+            else:
+                if loc.is_reg():
+                    assert loc is not r.fp # for now
+                    v = loc.value
+                else:
+                    assert 0, 'fix for floats'
+                    assert loc.is_vfp_reg()
+                    #v = len(VFPRegisterManager.all_regs) + loc.value
+                positions[i] = v * WORD
+        # write down the positions of locs
+        guardtok.faildescr.rd_locs = positions
+        self.regalloc_push(imm(fail_descr))
+        self.push_gcmap(self.mc, gcmap=guardtok.gcmap, push=True)
         self.mc.BL(target)
-        # write tight data that describes the failure recovery
-        if guardtok.is_guard_not_forced:
-            self.mc.writechar(chr(self.CODE_FORCED))
-        self.write_failure_recovery_description(guardtok.descr,
-                                guardtok.failargs, guardtok.faillocs[1:])
-        self.mc.write32(fail_index)
-        # for testing the decoding, write a final byte 0xCC
-        if not we_are_translated():
-            self.mc.writechar('\xCC')
-            faillocs = [loc for loc in guardtok.faillocs if loc is not None]
-            guardtok.descr._arm_debug_faillocs = faillocs
-        self.align()
         return startpos
 
     def align(self):
@@ -747,13 +769,11 @@
         for tok in self.pending_guards:
             #generate the exit stub and the encoded representation
             tok.pos_recovery_stub = self.generate_quick_failure(tok)
-            # store info on the descr
-            tok.descr._arm_current_frame_depth = tok.faillocs[0].getint()
 
     def process_pending_guards(self, block_start):
         clt = self.current_clt
         for tok in self.pending_guards:
-            descr = tok.descr
+            descr = tok.faildescr
             assert isinstance(descr, AbstractFailDescr)
             failure_recovery_pos = block_start + tok.pos_recovery_stub
             descr._arm_failure_recovery_block = failure_recovery_pos
@@ -1213,16 +1233,18 @@
         # keep the ref alive
         self.current_clt.allgcrefs.append(gcmapref)
         rgc._make_sure_does_not_move(gcmapref)
-        pass
-        #if push:
-        #    mc.PUSH(imm(rffi.cast(lltype.Signed, gcmapref)))
-        #elif mov:
-        #    mc.MOV(RawEspLoc(0, REF),
-        #           imm(rffi.cast(lltype.Signed, gcmapref)))
-        #else:
-        #    assert store
-        #    ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
-        #    mc.MOV(raw_stack(ofs), imm(rffi.cast(lltype.Signed, gcmapref)))
+        if push:
+            mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, gcmapref))
+            mc.PUSH([r.ip.value])
+        elif mov:
+            assert 0
+            mc.MOV(RawEspLoc(0, REF),
+                   imm(rffi.cast(lltype.Signed, gcmapref)))
+        else:
+            assert store
+            ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+            mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, gcmapref))
+            mc.STR_ri(r.ip.value, r.fp.value, imm=ofs)
 
     def pop_gcmap(self, mc):
         ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -2,7 +2,7 @@
 from rpython.jit.backend.arm import conditions as c
 from rpython.jit.backend.arm import registers as r
 from rpython.jit.backend.arm import shift
-from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD
+from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE
 
 from rpython.jit.backend.arm.helper.assembler import (gen_emit_op_by_helper_call,
                                                 gen_emit_op_unary_cmp,
@@ -21,7 +21,7 @@
 from rpython.jit.backend.arm.jump import remap_frame_layout
 from rpython.jit.backend.arm.regalloc import TempInt, TempPtr
 from rpython.jit.backend.arm.locations import imm
-from rpython.jit.backend.llsupport import symbolic
+from rpython.jit.backend.llsupport import symbolic, jitframe
 from rpython.jit.backend.llsupport.descr import InteriorFieldDescr
 from rpython.jit.metainterp.history import (Box, AbstractFailDescr,
                                             INT, FLOAT, REF)
@@ -35,18 +35,43 @@
 
 
 class GuardToken(object):
-    def __init__(self, descr, failargs, faillocs, offset, save_exc, fcond=c.AL,
+    def __init__(self, faildescr, failargs, fail_locs, offset, exc, fcond=c.AL,
                  is_guard_not_invalidated=False, is_guard_not_forced=False):
-        assert isinstance(save_exc, bool)
-        self.descr = descr
+        assert isinstance(exc, bool)
+        self.faildescr = faildescr
+        self.failargs = failargs
+        self.fail_locs = fail_locs[1:]
         self.offset = offset
+        self.gcmap = self.compute_gcmap(failargs, fail_locs, fail_locs[0].value)
+        self.exc = exc
         self.is_guard_not_invalidated = is_guard_not_invalidated
         self.is_guard_not_forced = is_guard_not_forced
-        self.failargs = failargs
-        self.faillocs = faillocs
-        self.save_exc = save_exc
         self.fcond = fcond
 
+    def compute_gcmap(self, failargs, fail_locs, frame_depth):
+        # note that regalloc has a very similar compute, but
+        # one that does iteration over all bindings, so slightly different,
+        # eh
+        size = frame_depth + JITFRAME_FIXED_SIZE
+        gcmap = lltype.malloc(jitframe.GCMAP, size // WORD // 8 + 1,
+                              zero=True)
+        input_i = 0
+        for i in range(len(failargs)):
+            arg = failargs[i]
+            if arg is None:
+                continue
+            loc = fail_locs[input_i]
+            input_i += 1
+            if arg.type == REF:
+                loc = fail_locs[i]
+                if loc.is_reg():
+                    val = loc.value
+                else:
+                    assert 0, 'ffuu, implement'
+                    val = loc.value // WORD
+                gcmap[val // WORD // 8] |= r_uint(1) << (val % (WORD * 8))
+        return gcmap
+
 
 class ResOpAssembler(object):
 
@@ -211,9 +236,9 @@
             self.mc.BKPT()
         self.pending_guards.append(GuardToken(descr,
                                     failargs=op.getfailargs(),
-                                    faillocs=arglocs,
+                                    fail_locs=arglocs,
                                     offset=pos,
-                                    save_exc=save_exc,
+                                    exc=save_exc,
                                     is_guard_not_invalidated=is_guard_not_invalidated,
                                     is_guard_not_forced=is_guard_not_forced,
                                     fcond=fcond))
diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -709,6 +709,7 @@
         # optimization only: fill in the 'hint_frame_locations' dictionary
         # of rm and xrm based on the JUMP at the end of the loop, by looking
         # at where we would like the boxes to be after the jump.
+        return # XXX disabled for now
         op = operations[-1]
         if op.getopnum() != rop.JUMP:
             return


More information about the pypy-commit mailing list