[pypy-svn] r25931 - in pypy/dist/pypy/translator/backendopt: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Apr 18 10:36:39 CEST 2006
Author: arigo
Date: Tue Apr 18 10:36:37 2006
New Revision: 25931
Modified:
pypy/dist/pypy/translator/backendopt/malloc.py
pypy/dist/pypy/translator/backendopt/test/test_malloc.py
Log:
A test that shows a situation where malloc removal needs an
extra 'keepalive' to be valid. Fix.
Modified: pypy/dist/pypy/translator/backendopt/malloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/malloc.py (original)
+++ pypy/dist/pypy/translator/backendopt/malloc.py Tue Apr 18 10:36:37 2006
@@ -153,11 +153,12 @@
for block, vars in variables_by_block.items():
- def flowin(var, newvarsmap):
+ def flowin(var, newvarsmap, insert_keepalive=False):
# in this 'block', follow where the 'var' goes to and replace
# it by a flattened-out family of variables. This family is given
# by newvarsmap, whose keys are the 'flatnames'.
vars = {var: True}
+ last_removed_access = None
def list_newvars():
return [newvarsmap[key] for key in flatnames]
@@ -175,11 +176,13 @@
[newvarsmap[S, fldname]],
op.result)
newops.append(newop)
+ last_removed_access = len(newops)
elif op.opname == "setfield":
S = op.args[0].concretetype.TO
fldname = op.args[1].value
assert (S, fldname) in newvarsmap
newvarsmap[S, fldname] = op.args[2]
+ last_removed_access = len(newops)
elif op.opname in ("same_as", "cast_pointer"):
assert op.result not in vars
vars[op.result] = True
@@ -188,7 +191,7 @@
# flattened list of variables for both, as a "setfield"
# via one pointer must be reflected in the other.
elif op.opname == 'keepalive':
- pass
+ last_removed_access = len(newops)
else:
raise AssertionError, op.opname
elif op.result in vars:
@@ -198,7 +201,7 @@
# drop the "malloc" operation
else:
newops.append(op)
- block.operations[:] = newops
+
assert block.exitswitch not in vars
for link in block.exits:
@@ -206,10 +209,24 @@
for arg in link.args:
if arg in vars:
newargs += list_newvars()
+ insert_keepalive = False # kept alive by the link
else:
newargs.append(arg)
link.args[:] = newargs
+ if insert_keepalive and last_removed_access is not None:
+ keepalives = []
+ for v in list_newvars():
+ T = v.concretetype
+ if isinstance(T, lltype.Ptr) and T._needsgc():
+ v0 = Variable()
+ v0.concretetype = lltype.Void
+ newop = SpaceOperation('keepalive', [v], v0)
+ keepalives.append(newop)
+ newops[last_removed_access:last_removed_access] = keepalives
+
+ block.operations[:] = newops
+
# look for variables arriving from outside the block
for var in vars:
if var in block.inputargs:
@@ -224,7 +241,7 @@
newinputargs += block.inputargs[i+1:]
block.inputargs[:] = newinputargs
assert var not in block.inputargs
- flowin(var, newvarsmap)
+ flowin(var, newvarsmap, insert_keepalive=True)
# look for variables created inside the block by a malloc
vars_created_here = []
Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_malloc.py (original)
+++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py Tue Apr 18 10:36:37 2006
@@ -3,6 +3,7 @@
from pypy.translator.backendopt.inline import inline_function
from pypy.translator.backendopt.all import backend_optimizations
from pypy.translator.translator import TranslationContext, graphof
+from pypy.translator import simplify
from pypy.objspace.flow.model import checkgraph, flatten, Block
from pypy.rpython.llinterp import LLInterpreter
from pypy.conftest import option
@@ -28,6 +29,8 @@
if option.view:
t.view()
remove_simple_mallocs(graph)
+ # to detect missing keepalives:
+ simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks()))
if option.view:
t.view()
if must_be_removed:
@@ -146,3 +149,33 @@
op = graph.startblock.exits[0].target.exits[1].target.operations[0]
assert op.opname == "malloc"
+def test_add_keepalives():
+ from pypy.rpython.lltypesystem import lltype
+ class A:
+ pass
+ SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
+ BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
+ def fn7(i):
+ big = lltype.malloc(BIG)
+ a = A()
+ a.big = big
+ a.small = big.s
+ while i > 0:
+ a.small.x += i
+ i -= 1
+ return a.small.x
+ check(fn7, [int], [10], 55, must_be_removed=False)
+
+def test_getsubstruct():
+ py.test.skip("in-progress")
+ from pypy.rpython.lltypesystem import lltype
+ SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
+ BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
+
+ def fn(n1, n2):
+ b = lltype.malloc(BIG)
+ b.z = n1
+ b.s.x = n2
+ return b.z - b.s.x
+
+ check(fn, [int, int], [100, 58], 42)
More information about the Pypy-commit
mailing list