[pypy-svn] r40772 - in pypy/dist/pypy: rpython translator/oosupport translator/oosupport/test
antocuni at codespeak.net
antocuni at codespeak.net
Mon Mar 19 14:57:27 CET 2007
Author: antocuni
Date: Mon Mar 19 14:57:24 2007
New Revision: 40772
Added:
pypy/dist/pypy/translator/oosupport/test/
pypy/dist/pypy/translator/oosupport/test/__init__.py (contents, props changed)
pypy/dist/pypy/translator/oosupport/test/test_treebuilder.py (contents, props changed)
pypy/dist/pypy/translator/oosupport/treebuilder.py (contents, props changed)
Modified:
pypy/dist/pypy/rpython/llinterp.py
Log:
Add a general way to transform SSI graphs in stack-based machine
friendly form.
Operations now accept three kinds of arguments:
- variables
- constants
- sub-operation (recursively)
The algorithm could be improved, because at the moment it simply
ignores operations involving mutable objects instead of checking if
they are effectively mutated.
Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py (original)
+++ pypy/dist/pypy/rpython/llinterp.py Mon Mar 19 14:57:24 2007
@@ -226,6 +226,16 @@
assert False, "type error: %r val from %r var/const" % (lltype.typeOf(val), varorconst.concretetype)
return val
+ def getval_or_subop(self, varorsubop):
+ from pypy.translator.oosupport.treebuilder import SubOperation
+ if isinstance(varorsubop, SubOperation):
+ self.eval_operation(varorsubop.op)
+ resultval = self.getval(varorsubop.op.result)
+ del self.bindings[varorsubop.op.result] # XXX hack
+ return resultval
+ else:
+ return self.getval(varorsubop)
+
# _______________________________________________________
# other helpers
def getoperationhandler(self, opname):
@@ -365,7 +375,7 @@
if getattr(ophandler, 'specialform', False):
retval = ophandler(*operation.args)
else:
- vals = [self.getval(x) for x in operation.args]
+ vals = [self.getval_or_subop(x) for x in operation.args]
if getattr(ophandler, 'need_result_type', False):
vals.insert(0, operation.result.concretetype)
try:
Added: pypy/dist/pypy/translator/oosupport/test/__init__.py
==============================================================================
Added: pypy/dist/pypy/translator/oosupport/test/test_treebuilder.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/oosupport/test/test_treebuilder.py Mon Mar 19 14:57:24 2007
@@ -0,0 +1,89 @@
+from pypy.rpython.llinterp import LLInterpreter
+from pypy.translator.translator import TranslationContext, graphof
+from pypy.translator.oosupport.treebuilder import build_trees, SubOperation
+from pypy.conftest import option
+from pypy.rpython.test.test_rlist import BaseTestRlist
+from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin
+from pypy.rpython.test.test_llinterp import get_interpreter
+
+def translate(func, argtypes):
+ t = TranslationContext()
+ t.buildannotator().build_types(func, argtypes)
+ t.buildrtyper(type_system='ootype').specialize()
+ return t
+
+def check_trees(func, argtypes):
+ t = translate(func, argtypes)
+ if option.view:
+ t.view()
+ graph = graphof(t, func)
+ build_trees(graph)
+ if option.view:
+ t.view()
+ interp = LLInterpreter(t.rtyper)
+ def eval_func(*args):
+ return interp.eval_graph(graph, args)
+ return graph, eval_func
+
+def test_simple():
+ def fn(x):
+ x = x+1
+ x = x+1
+ return x
+ graph, eval_func = check_trees(fn, [int])
+ block = graph.startblock
+ assert len(block.operations) == 1
+ assert isinstance(block.operations[0].args[0], SubOperation)
+ assert eval_func(0) == 2
+
+def test_function_call():
+ def g(x):
+ return x+1
+ def fn(x):
+ a = g(x)
+ b = g(x+1)
+ return a + b
+ graph, eval_func = check_trees(fn, [int])
+ block = graph.startblock
+ assert len(block.operations) == 1
+ assert isinstance(block.operations[0].args[0], SubOperation)
+ assert isinstance(block.operations[0].args[1], SubOperation)
+ assert eval_func(1) == 5
+
+def test_count_exit_links():
+ def g(x):
+ pass
+ def fn(x):
+ res = x+1
+ g(res)
+ return res
+ graph, eval_func = check_trees(fn, [int])
+ block = graph.startblock
+ assert len(block.operations) == 2
+ v0 = block.operations[0].result
+ assert block.exits[0].args == [v0]
+ assert eval_func(0) == 1
+
+def test_mutable_values():
+ def fn():
+ lst = []
+ length = len(lst)
+ lst.append(42)
+ return length + 1
+ graph, eval_func = check_trees(fn, [])
+ block = graph.startblock
+ assert not isinstance(block.operations[-1].args[0], SubOperation)
+ assert eval_func() == 1
+
+class BuildTreeRtypingTest(BaseRtypingTest, OORtypeMixin):
+ def interpret(self, fn, args):
+ interp, graph = get_interpreter(fn, args, view=False, viewbefore=False, type_system=self.type_system)
+ if option.view:
+ interp.typer.annotator.translator.view()
+ build_trees(graph)
+ if option.view:
+ interp.typer.annotator.translator.view()
+ return interp.eval_graph(graph, args)
+
+class TestBuildTreeList(BuildTreeRtypingTest, BaseTestRlist):
+ pass
Added: pypy/dist/pypy/translator/oosupport/treebuilder.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/oosupport/treebuilder.py Mon Mar 19 14:57:24 2007
@@ -0,0 +1,59 @@
+from pypy.rpython.ootypesystem import ootype
+from pypy.objspace.flow import model as flowmodel
+
+class SubOperation(object):
+ def __init__(self, op):
+ self.op = op
+ self.concretetype = op.result.concretetype
+
+ def __repr__(self):
+ return "[%s(%s)]" % (self.op.opname,
+ ", ".join(map(repr, self.op.args)))
+
+def is_mutable(TYPE):
+ return isinstance(TYPE, (ootype.Instance,
+ ootype.Record,
+ ootype.List,
+ ootype.Dict,
+ ootype.StringBuilder.__class__,
+ ootype.CustomDict,
+ ootype.DictItemsIterator))
+
+def can_be_inlined(op):
+ for v in op.args:
+ if isinstance(v, flowmodel.Variable) and is_mutable(v.concretetype):
+ return False
+ return True
+
+def build_op_map(block):
+ var_count = {}
+ var_to_op = {}
+ def inc(v):
+ if isinstance(v, flowmodel.Variable):
+ var_count[v] = var_count.get(v, 0) + 1
+
+ for i, op in enumerate(block.operations):
+ var_to_op[op.result] = i, op
+ for v in op.args:
+ inc(v)
+ for link in block.exits:
+ for v in link.args:
+ inc(v)
+ return var_count, var_to_op
+
+def build_trees_for_block(block):
+ var_count, var_to_op = build_op_map(block)
+ for op in block.operations:
+ for i, v in enumerate(op.args):
+ if var_count.get(v, None) == 1 and v not in block.inputargs: # "inline" the operation
+ sub_i, sub_op = var_to_op[v]
+ if can_be_inlined(sub_op):
+ op.args[i] = SubOperation(sub_op)
+ block.operations[sub_i] = None
+ block.operations = [op for op in block.operations if op is not None]
+
+def build_trees(graph):
+ if not getattr(graph, 'tree_built', False):
+ for block in graph.iterblocks():
+ build_trees_for_block(block)
+ graph.tree_built = True
More information about the Pypy-commit
mailing list