[pypy-svn] pypy arm-backend-2: (arigo, david) patch the frame size of a loop or bridge with a larger value if it jumps to another location that requires a larger frame than the current one would need

bivab commits-noreply at bitbucket.org
Tue Feb 22 18:45:36 CET 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r42219:65a51f86470e
Date: 2011-02-22 18:42 +0100
http://bitbucket.org/pypy/pypy/changeset/65a51f86470e/

Log:	(arigo, david) patch the frame size of a loop or bridge with a
	larger value if it jumps to another location that requires a larger
	frame than the current one would need

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
@@ -326,7 +326,7 @@
         looptoken._arm_arglocs = arglocs
         return arglocs
 
-    def gen_direct_bootstrap_code(self, arglocs, loop_head, regalloc):
+    def gen_direct_bootstrap_code(self, arglocs, loop_head, looptoken):
         self.gen_func_prolog()
         if len(arglocs) > 4:
             reg_args = 4
@@ -351,7 +351,7 @@
                 assert 0, 'invalid location'
         sp_patch_location = self._prepare_sp_patch_position()
         self.mc.B_offs(loop_head)
-        self._patch_sp_offset(sp_patch_location, regalloc)
+        self._patch_sp_offset(sp_patch_location, looptoken)
 
     def _dump(self, ops, type='loop'):
         debug_start('jit-backend-ops')
@@ -381,12 +381,13 @@
 
         self._walk_operations(operations, regalloc)
 
-        self._patch_sp_offset(sp_patch_location, regalloc)
+        looptoken._arm_frame_depth = regalloc.frame_manager.frame_depth 
+        self._patch_sp_offset(sp_patch_location, looptoken)
 
         self.align()
 
         direct_bootstrap_code = self.mc.currpos()
-        self.gen_direct_bootstrap_code(arglocs, loop_head, regalloc)
+        self.gen_direct_bootstrap_code(arglocs, loop_head, looptoken)
 
         loop_start = self.materialize_loop(looptoken)
         looptoken._arm_bootstrap_code = loop_start
@@ -416,7 +417,8 @@
 
         self._walk_operations(operations, regalloc)
 
-        self._patch_sp_offset(sp_patch_location, regalloc)
+        original_loop_token._arm_frame_depth = regalloc.frame_manager.frame_depth 
+        self._patch_sp_offset(sp_patch_location, original_loop_token)
 
         bridge_start = self.materialize_loop(original_loop_token)
         self.update_descrs_for_bridges(bridge_start)
@@ -460,13 +462,13 @@
             self.mc.MOV_rr(r.r0.value, r.r0.value)
         return l
 
-    def _patch_sp_offset(self, pos, regalloc):
+    def _patch_sp_offset(self, pos, looptoken):
         cb = OverwritingBuilder(self.mc, pos, OverwritingBuilder.size_of_gen_load_int)
         # Note: the frame_depth is one less than the value stored in the frame
         # manager
-        if regalloc.frame_manager.frame_depth == 1:
+        if looptoken._arm_frame_depth == 1:
             return
-        n = (regalloc.frame_manager.frame_depth-1)*WORD
+        n = (looptoken._arm_frame_depth-1)*WORD
         self._adjust_sp(n, cb, base_reg=r.fp)
 
     def _adjust_sp(self, n, cb=None, fcond=c.AL, base_reg=r.sp):

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
@@ -228,6 +228,8 @@
         else:
             target = descr._arm_bootstrap_code + descr._arm_loop_code
             self.mc.B(target, fcond)
+            new_fd = max(regalloc.frame_manager.frame_depth, descr._arm_frame_depth)
+            regalloc.frame_manager.frame_depth = new_fd
         return fcond
 
     def emit_op_finish(self, op, arglocs, regalloc, fcond):

diff --git a/pypy/jit/backend/test/test_frame_size.py b/pypy/jit/backend/test/test_frame_size.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/test/test_frame_size.py
@@ -0,0 +1,98 @@
+import py, sys, random, os, struct, operator
+from pypy.jit.metainterp.history import (AbstractFailDescr,
+                                         AbstractDescr,
+                                         BasicFailDescr,
+                                         BoxInt, Box, BoxPtr,
+                                         LoopToken,
+                                         ConstInt, ConstPtr,
+                                         BoxObj, Const,
+                                         ConstObj, BoxFloat, ConstFloat)
+from pypy.jit.metainterp.resoperation import ResOperation, rop
+from pypy.jit.metainterp.typesystem import deref
+from pypy.jit.tool.oparser import parse
+from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass
+from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.annlowlevel import llhelper
+from pypy.rpython.llinterp import LLException
+from pypy.jit.codewriter import heaptracker, longlong
+from pypy.rlib.rarithmetic import intmask
+from pypy.jit.backend.detect_cpu import getcpuclass
+
+CPU = getcpuclass()
+
+class TestFrameSize(object):
+    cpu = CPU(None, None)
+    cpu.setup_once()
+
+    looptoken = None
+    
+    def f1(x):
+        return x+1
+
+    F1PTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
+    f1ptr = llhelper(F1PTR, f1)
+    f1_calldescr = cpu.calldescrof(F1PTR.TO, F1PTR.TO.ARGS, F1PTR.TO.RESULT)
+    namespace = locals().copy()
+    type_system = 'lltype'
+
+    def parse(self, s, boxkinds=None):
+        return parse(s, self.cpu, self.namespace,
+                     type_system=self.type_system,
+                     boxkinds=boxkinds)
+
+    def interpret(self, ops, args, run=True):
+        loop = self.parse(ops)
+        self.cpu.compile_loop(loop.inputargs, loop.operations, loop.token)
+        for i, arg in enumerate(args):
+            if isinstance(arg, int):
+                self.cpu.set_future_value_int(i, arg)
+            elif isinstance(arg, float):
+                self.cpu.set_future_value_float(i, arg)
+            else:
+                assert isinstance(lltype.typeOf(arg), lltype.Ptr)
+                llgcref = lltype.cast_opaque_ptr(llmemory.GCREF, arg)
+                self.cpu.set_future_value_ref(i, llgcref)
+        if run:
+            self.cpu.execute_token(loop.token)
+        return loop
+
+    def getint(self, index):
+        return self.cpu.get_latest_value_int(index)
+
+    def getfloat(self, index):
+        return self.cpu.get_latest_value_float(index)
+
+    def getints(self, end):
+        return [self.cpu.get_latest_value_int(index) for
+                index in range(0, end)]
+
+    def getfloats(self, end):
+        return [self.cpu.get_latest_value_float(index) for
+                index in range(0, end)]
+
+    def getptr(self, index, T):
+        gcref = self.cpu.get_latest_value_ref(index)
+        return lltype.cast_opaque_ptr(T, gcref)
+
+    
+
+    def test_call_loop_from_loop(self): 
+
+        large_frame_loop = """ 
+        [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14]
+        i15 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
+        finish(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15)
+        """ 
+        large = self.interpret(large_frame_loop, range(15), run=False)
+        self.namespace['looptoken'] = large.token
+        assert self.namespace['looptoken']._arm_bootstrap_code != 0
+        small_frame_loop = """
+        [i0]
+        i1 = int_add(i0, 1)
+        jump(i1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, descr=looptoken)
+        """
+
+        self.interpret(small_frame_loop, [110])
+        expected = [111, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 112]
+        assert self.getints(16) == expected
+


More information about the Pypy-commit mailing list