[pypy-commit] pypy arm-backend-2: start implementing support for out of line guards

bivab noreply at buildbot.pypy.org
Fri Jul 1 14:18:33 CEST 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r45216:fbc58902cd0d
Date: 2011-06-30 18:24 +0200
http://bitbucket.org/pypy/pypy/changeset/fbc58902cd0d/

Log:	start implementing support for out of line guards

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
@@ -25,7 +25,7 @@
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rpython.lltypesystem import lltype, rffi, llmemory
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.jit.backend.arm.opassembler import ResOpAssembler
+from pypy.jit.backend.arm.opassembler import ResOpAssembler, GuardToken
 from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
                              have_debug_prints)
 
@@ -76,7 +76,7 @@
         self.malloc_str_func_addr = 0
         self.malloc_unicode_func_addr = 0
         self.memcpy_addr = 0
-        self.guard_descrs = None
+        self.pending_guards = None
         self._exit_code_addr = 0
         self.current_clt = None
         self.malloc_slowpath = 0
@@ -88,7 +88,7 @@
         assert self.memcpy_addr != 0, 'setup_once() not called?'
         self.current_clt = looptoken.compiled_loop_token
         self.mc = ARMv7Builder()
-        self.guard_descrs = []
+        self.pending_guards = []
         assert self.datablockwrapper is None
         allblocks = self.get_asmmemmgr_blocks(looptoken)
         self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
@@ -98,7 +98,7 @@
         self.current_clt = None
         self._regalloc = None
         self.mc = None
-        self.guard_descrs = None
+        self.pending_guards = None
 
     def setup_once(self):
         # Addresses of functions called by new_xxx operations
@@ -300,7 +300,7 @@
         return mc.materialize(self.cpu.asmmemmgr, [],
                                    self.cpu.gc_ll_descr.gcrootmap)
 
-    def _gen_path_to_exit_path(self, op, args, arglocs, fcond=c.AL, save_exc=False):
+    def gen_descr_encoding(self, op, args, arglocs):
         descr = op.getdescr()
         if op.getopnum() != rop.FINISH:
             assert isinstance(descr, AbstractFailDescr)
@@ -357,15 +357,21 @@
 
         n = self.cpu.get_fail_descr_number(descr)
         encode32(mem, j+1, n)
-        self.mc.LDR_ri(r.ip.value, r.pc.value, imm=WORD)
+        return memaddr
+
+    def _gen_path_to_exit_path(self, op, args, arglocs, fcond=c.AL, save_exc=False):
+        memaddr = self.gen_descr_encoding(op, args, arglocs)
+        self.gen_exit_code(self.mc, memaddr, fcond, save_exc)
+        return memaddr
+
+    def gen_exit_code(self, mc, memaddr, fcond=c.AL, save_exc=False):
+        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
-        self.mc.B(path)
-        self.mc.write32(memaddr)
-
-        return memaddr
+        mc.B(path)
+        mc.write32(memaddr)
 
     def align(self):
         while(self.mc.currpos() % FUNC_ALIGN != 0):
@@ -583,7 +589,7 @@
         loop_start = self.materialize_loop(looptoken)
         looptoken._arm_bootstrap_code = loop_start
         looptoken._arm_direct_bootstrap_code = loop_start + direct_bootstrap_code
-        self.update_descrs_for_bridges(loop_start)
+        self.process_pending_guards(loop_start)
         if log and not we_are_translated():
             print 'Loop', inputargs, operations
             self.mc._dump_trace(loop_start, 'loop_%s.asm' % self.cpu.total_compiled_loops)
@@ -612,7 +618,7 @@
         self._patch_sp_offset(sp_patch_location, regalloc.frame_manager.frame_depth)
 
         bridge_start = self.materialize_loop(original_loop_token)
-        self.update_descrs_for_bridges(bridge_start)
+        self.process_pending_guards(bridge_start)
 
         self.patch_trace(faildescr, original_loop_token, bridge_start, regalloc)
         if log and not we_are_translated():
@@ -628,10 +634,17 @@
         return self.mc.materialize(self.cpu.asmmemmgr, allblocks,
                                    self.cpu.gc_ll_descr.gcrootmap)
 
-    def update_descrs_for_bridges(self, block_start):
-        for descr in self.guard_descrs:
+    def process_pending_guards(self, block_start):
+        clt = self.current_clt
+        for tok in self.pending_guards:
+            descr = tok.descr
+            #XXX _arm_block_start should go in the looptoken
             descr._arm_block_start = block_start
-
+            descr._failure_recovery_code = tok.encoded_args
+            descr._arm_guard_pos = tok.offset
+            if tok.is_invalidate:
+                clt.invalidate_positions.append(
+                    (block_start + tok.offset, tok.encoded_args))
 
     def get_asmmemmgr_blocks(self, looptoken):
         clt = looptoken.compiled_loop_token
diff --git a/pypy/jit/backend/arm/opassembler.py b/pypy/jit/backend/arm/opassembler.py
--- a/pypy/jit/backend/arm/opassembler.py
+++ b/pypy/jit/backend/arm/opassembler.py
@@ -33,6 +33,13 @@
 
 NO_FORCE_INDEX = -1
 
+class GuardToken(object):
+    def __init__(self, descr, offset=0, encoded_args=0, is_invalidate=False):
+        self.descr = descr
+        self.offset = offset
+        self.encoded_args = encoded_args
+        self.is_invalidate = is_invalidate
+
 class IntOpAsslember(object):
 
     _mixin_ = True
@@ -161,16 +168,17 @@
     def _emit_guard(self, op, arglocs, fcond, save_exc=False):
         descr = op.getdescr()
         assert isinstance(descr, AbstractFailDescr)
-        self.guard_descrs.append(descr)
+
+
         if not we_are_translated() and hasattr(op, 'getfailargs'):
            print 'Failargs: ', op.getfailargs()
 
         self.mc.ADD_ri(r.pc.value, r.pc.value, self.guard_size-PC_OFFSET, cond=fcond)
-        descr._arm_guard_pos = self.mc.currpos()
+        pos = self.mc.currpos()
 
         memaddr = self._gen_path_to_exit_path(op, op.getfailargs(),
                                             arglocs, save_exc=save_exc)
-        descr._failure_recovery_code = memaddr
+        self.pending_guards.append(GuardToken(op.getdescr(), pos=pos, memaddr=memaddr))
         return c.AL
 
     def _emit_guard_overflow(self, guard, failargs, fcond):
@@ -238,6 +246,11 @@
         self._cmp_guard_class(op, arglocs, regalloc, fcond)
         return fcond
 
+    def emit_op_guard_not_invalidated(self, op, locs, regalloc, fcond):
+        pos = self.mc.currpos() # after potential jmp
+        memaddr = self.gen_descr_encoding(op, op.getfailargs(), locs)
+        self.pending_guards.append(GuardToken(op.getdescr(), pos, memaddr, True))
+
     def _cmp_guard_class(self, op, locs, regalloc, fcond):
         offset = locs[2]
         if offset is not None:
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
@@ -509,6 +509,8 @@
         return locs
 
     prepare_op_guard_overflow = prepare_op_guard_no_overflow
+    prepare_op_guard_not_invalidated = prepare_op_guard_no_overflow
+
 
     def prepare_op_guard_exception(self, op, fcond):
         boxes = list(op.getarglist())
diff --git a/pypy/jit/backend/arm/runner.py b/pypy/jit/backend/arm/runner.py
--- a/pypy/jit/backend/arm/runner.py
+++ b/pypy/jit/backend/arm/runner.py
@@ -128,3 +128,20 @@
 
     def redirect_call_assembler(self, oldlooptoken, newlooptoken):
         self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)
+
+    def invalidate_loop(self, looptoken):
+        """Activate all GUARD_NOT_INVALIDATED in the loop and its attached
+        bridges.  Before this call, all GUARD_NOT_INVALIDATED do nothing;
+        after this call, they all fail.  Note that afterwards, if one such
+        guard fails often enough, it has a bridge attached to it; it is
+        possible then to re-call invalidate_loop() on the same looptoken,
+        which must invalidate all newer GUARD_NOT_INVALIDATED, but not the
+        old one that already has a bridge attached to it."""
+        from pypy.jit.backend.arm.codebuilder import ARMv7Builder
+
+        for tgt, memaddr in looptoken.compiled_loop_token.invalidate_positions:
+            mc = ARMv7Builder()
+            self.assembler.gen_exit_code(mc, memaddr)
+            mc.copy_to_raw_memory(tgt)
+        # positions invalidated
+        looptoken.compiled_loop_token.invalidate_positions = []


More information about the pypy-commit mailing list