[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