[pypy-commit] pypy arm-backend-2: refactor guards make the handling more similar to how it is done in the x86

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


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r45219:0268a6ca49d1
Date: 2011-07-01 14:25 +0200
http://bitbucket.org/pypy/pypy/changeset/0268a6ca49d1/

Log:	refactor guards make the handling more similar to how it is done in
	the x86 backend generating a check and a conditional jump to an exit
	stub that is later generated at the end of the compiled loop.

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
@@ -300,11 +300,7 @@
         return mc.materialize(self.cpu.asmmemmgr, [],
                                    self.cpu.gc_ll_descr.gcrootmap)
 
-    def gen_descr_encoding(self, op, args, arglocs):
-        descr = op.getdescr()
-        if op.getopnum() != rop.FINISH:
-            assert isinstance(descr, AbstractFailDescr)
-            descr._arm_frame_depth = arglocs[0].getint()
+    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
@@ -359,8 +355,8 @@
         encode32(mem, j+1, n)
         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)
+    def _gen_path_to_exit_path(self, descr, args, arglocs, fcond=c.AL, save_exc=False):
+        memaddr = self.gen_descr_encoding(descr, args, arglocs)
         self.gen_exit_code(self.mc, memaddr, fcond, save_exc)
         return memaddr
 
@@ -586,6 +582,7 @@
         direct_bootstrap_code = self.mc.currpos()
         self.gen_direct_bootstrap_code(loop_head, looptoken, inputargs)
 
+        self.write_pending_failure_recoveries()
         loop_start = self.materialize_loop(looptoken)
         looptoken._arm_bootstrap_code = loop_start
         looptoken._arm_direct_bootstrap_code = loop_start + direct_bootstrap_code
@@ -617,6 +614,7 @@
         #original_loop_token._arm_frame_depth = regalloc.frame_manager.frame_depth
         self._patch_sp_offset(sp_patch_location, regalloc.frame_manager.frame_depth)
 
+        self.write_pending_failure_recoveries()
         bridge_start = self.materialize_loop(original_loop_token)
         self.process_pending_guards(bridge_start)
 
@@ -634,17 +632,38 @@
         return self.mc.materialize(self.cpu.asmmemmgr, allblocks,
                                    self.cpu.gc_ll_descr.gcrootmap)
 
+    def write_pending_failure_recoveries(self):
+        for tok in self.pending_guards:
+            descr = tok.descr
+            #generate the exit stub and the encoded representation
+            pos = self.mc.currpos()
+            tok.pos_recovery_stub = pos 
+
+            memaddr = self._gen_path_to_exit_path(descr, tok.failargs,
+                                            tok.faillocs, save_exc=tok.save_exc)
+            # store info on the descr
+            descr._arm_frame_depth = tok.faillocs[0].getint()
+            descr._failure_recovery_code = memaddr
+            descr._arm_guard_pos = pos
+
     def process_pending_guards(self, block_start):
         clt = self.current_clt
         for tok in self.pending_guards:
             descr = tok.descr
+            assert isinstance(descr, AbstractFailDescr)
+
             #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:
+
+            if not tok.is_invalidate:
+                #patch the guard jumpt to the stub
+                # overwrite the generate NOP with a B_offs to the pos of the stub
+                mc = ARMv7Builder()
+                mc.B_offs(descr._arm_guard_pos - tok.offset, c.get_opposite_of(tok.fcond))
+                mc.copy_to_raw_memory(block_start + tok.offset)
+            else:
                 clt.invalidate_positions.append(
-                    (block_start + tok.offset, tok.encoded_args))
+                    (block_start + tok.offset, descr._arm_guard_pos - tok.offset))
 
     def get_asmmemmgr_blocks(self, looptoken):
         clt = looptoken.compiled_loop_token
diff --git a/pypy/jit/backend/arm/codebuilder.py b/pypy/jit/backend/arm/codebuilder.py
--- a/pypy/jit/backend/arm/codebuilder.py
+++ b/pypy/jit/backend/arm/codebuilder.py
@@ -156,6 +156,8 @@
         self.write32(cond << 28 | 0xEF1FA10)
 
     def B(self, target, c=cond.AL):
+        #assert self._fits_in_24bits(target)
+        #return (c << 20 | 0xA << 24 | target & 0xFFFFFF)
         if c == cond.AL:
             self.LDR_ri(reg.pc.value, reg.pc.value, -arch.PC_OFFSET/2)
             self.write32(target)
@@ -165,12 +167,9 @@
 
     def B_offs(self, target_ofs, c=cond.AL):
         pos = self.currpos()
-        if target_ofs > pos:
-            raise NotImplementedError
-        else:
-            target_ofs = target_ofs - (pos + arch.PC_OFFSET)
-            assert target_ofs & 0x3 == 0
-            self.write32(c << 28 | 0xA << 24 | (target_ofs >> 2) & 0xFFFFFF)
+        target_ofs = target_ofs - (pos + arch.PC_OFFSET)
+        assert target_ofs & 0x3 == 0
+        self.write32(c << 28 | 0xA << 24 | (target_ofs >> 2) & 0xFFFFFF)
 
     def BL(self, target, c=cond.AL):
         if c == cond.AL:
@@ -242,6 +241,9 @@
         self.index = start
         self.end = start + size
 
+    def currpos(self):
+        return self.index
+
     def writechar(self, char):
         assert self.index <= self.end
         self.cb.overwrite(self.index, char)
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
@@ -34,11 +34,15 @@
 NO_FORCE_INDEX = -1
 
 class GuardToken(object):
-    def __init__(self, descr, offset=0, encoded_args=0, is_invalidate=False):
+    def __init__(self, descr, failargs, faillocs, offset, fcond=c.AL,
+                                        save_exc=False, is_invalidate=False):
         self.descr = descr
         self.offset = offset
-        self.encoded_args = encoded_args
         self.is_invalidate = is_invalidate
+        self.failargs = failargs
+        self.faillocs = faillocs
+        self.save_exc = save_exc
+        self.fcond=fcond
 
 class IntOpAsslember(object):
 
@@ -165,7 +169,7 @@
     _mixin_ = True
 
     guard_size = 5*WORD
-    def _emit_guard(self, op, arglocs, fcond, save_exc=False):
+    def _emit_guard(self, op, arglocs, fcond, save_exc=False, is_guard_not_ivalidated=False):
         descr = op.getdescr()
         assert isinstance(descr, AbstractFailDescr)
 
@@ -173,13 +177,15 @@
         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)
         pos = self.mc.currpos()
-
-        memaddr = self._gen_path_to_exit_path(op, op.getfailargs(),
-                                            arglocs, save_exc=save_exc)
-        self.pending_guards.append(GuardToken(op.getdescr(), 
-                                    offset=pos, encoded_args=memaddr))
+        self.mc.NOP()
+        self.pending_guards.append(GuardToken(descr,
+                                    failargs=op.getfailargs(),
+                                    faillocs=arglocs,
+                                    offset=pos,
+                                    fcond=fcond,
+                                    is_invalidate=is_guard_not_ivalidated,
+                                    save_exc=save_exc))
         return c.AL
 
     def _emit_guard_overflow(self, guard, failargs, fcond):
@@ -241,17 +247,14 @@
 
         self.mc.CMP_ri(arglocs[0].value, 0)
         if offset is not None:
-            self.mc.ADD_ri(r.pc.value, r.pc.value, 2*WORD, cond=c.EQ)
+            self._emit_guard(op, arglocs[3:], c.NE)
         else:
             raise NotImplementedError
         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))
-        return fcond
+        return self._emit_guard(op, locs, fcond, is_guard_not_ivalidated=True)
 
     def _cmp_guard_class(self, op, locs, regalloc, fcond):
         offset = locs[2]
@@ -289,7 +292,7 @@
         return fcond
 
     def emit_op_finish(self, op, arglocs, regalloc, fcond):
-        self._gen_path_to_exit_path(op, op.getarglist(), arglocs, c.AL)
+        self._gen_path_to_exit_path(op.getdescr(), op.getarglist(), arglocs, c.AL)
         return fcond
 
     def emit_op_call(self, op, args, regalloc, fcond, force_index=-1):
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
@@ -139,9 +139,9 @@
         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:
+        for jmp, tgt  in looptoken.compiled_loop_token.invalidate_positions:
             mc = ARMv7Builder()
-            self.assembler.gen_exit_code(mc, memaddr)
-            mc.copy_to_raw_memory(tgt)
+            mc.B_offs(tgt)
+            mc.copy_to_raw_memory(jmp)
         # positions invalidated
         looptoken.compiled_loop_token.invalidate_positions = []


More information about the pypy-commit mailing list