[pypy-svn] r18192 - in pypy/dist/pypy/translator: backendopt backendopt/test tool

arigo at codespeak.net arigo at codespeak.net
Wed Oct 5 14:03:25 CEST 2005


Author: arigo
Date: Wed Oct  5 14:03:20 2005
New Revision: 18192

Modified:
   pypy/dist/pypy/translator/backendopt/inline.py
   pypy/dist/pypy/translator/backendopt/test/test_inline.py
   pypy/dist/pypy/translator/tool/make_dot.py
Log:
(pedronis, arigo)  Eric pointed out that we can have 'keepalive' as the
operation whose exceptions are caught, which makes no sense.  As a result,
found more bugs in inline, old and new.



Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/inline.py	Wed Oct  5 14:03:20 2005
@@ -68,6 +68,7 @@
         ops[-4].opname != "setfield" or ops[-3].opname != "cast_pointer" or
         ops[-2].opname != "getfield" or ops[-1].opname != "cast_pointer" or
         len(block.exits) != 1 or block.exits[0].args[0] != ops[-2].result or
+        block.exitswitch is not None or
         block.exits[0].args[1] != ops[-1].result or
         not isinstance(ops[-4].args[1], Constant) or
         ops[-4].args[1].value != "typeptr"):
@@ -201,7 +202,6 @@
             #try to match the exceptions for simple cases
             for link in entrymap[graph_to_inline.exceptblock]:
                 copiedblock = copied_blocks[link.prevblock]
-                copiedblock.operations += generate_keepalive(passon_vars[link.prevblock])
                 copiedlink = copiedblock.exits[0]
                 eclass = _find_exception_type(copiedblock)
                 #print copiedblock.operations
@@ -211,6 +211,8 @@
                 evalue = copiedlink.args[1]
                 for exceptionlink in afterblock.exits[1:]:
                     if exc_match.value(eclass, exceptionlink.llexitcase):
+                        copiedblock.operations += generate_keepalive(
+                            passon_vars[link.prevblock])
                         copiedlink.target = exceptionlink.target
                         linkargs = find_args_in_exceptional_case(exceptionlink,
                                                                  link.prevblock,
@@ -249,13 +251,18 @@
             blocks[-1].exits = blocks[-1].exits[:1]
             blocks[-1].operations = []
             blocks[-1].exitswitch = None
+            blocks[-1].exits[0].exitcase = None
+            del blocks[-1].exits[0].llexitcase
             linkargs = copiedexceptblock.inputargs
             copiedexceptblock.closeblock(Link(linkargs, blocks[0]))
             copiedexceptblock.operations += generate_keepalive(linkargs)
-            afterblock.exits = [afterblock.exits[0]]
-            afterblock.exitswitch = None
+    if exception_guarded:
+        assert afterblock.exits[0].exitcase is None
+        afterblock.exits = [afterblock.exits[0]]
+        afterblock.exitswitch = None
     #cleaning up -- makes sense to be here, because I insert quite
     #some empty blocks and blocks that can be joined
+    checkgraph(graph)
     eliminate_empty_blocks(graph)
     join_blocks(graph)
     remove_identical_vars(graph)

Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_inline.py	Wed Oct  5 14:03:20 2005
@@ -1,12 +1,14 @@
 import py
 import os
 from pypy.objspace.flow.model import traverse, Block, Link, Variable, Constant
+from pypy.objspace.flow.model import last_exception, checkgraph
 from pypy.translator.backendopt.inline import inline_function, CannotInline
 from pypy.translator.backendopt.inline import auto_inlining
 from pypy.translator.backendopt.inline import collect_called_functions
 from pypy.translator.backendopt.inline import measure_median_execution_cost
 from pypy.translator.translator import Translator
 from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.rarithmetic import ovfcheck
 from pypy.translator.test.snippet import is_perfect_number
 
 def no_missing_concretetype(node):
@@ -27,19 +29,21 @@
         if isinstance(node.last_exc_value, (Variable, Constant)):
             assert hasattr(node.last_exc_value, 'concretetype')
 
+def sanity_check(t):
+    # look for missing '.concretetype'
+    for graph in t.flowgraphs.values():
+        checkgraph(graph)
+        traverse(no_missing_concretetype, graph)
+
 def check_inline(func, in_func, sig):
     t = Translator(in_func)
     a = t.annotate(sig)
     a.simplify()
     t.specialize()
-    # look for missing '.concretetype' before inlining (so we don't blame it)
-    for graph in t.flowgraphs.values():
-        traverse(no_missing_concretetype, graph)
     # inline!
+    sanity_check(t)    # also check before inlining (so we don't blame it)
     inline_function(t, func, t.flowgraphs[in_func])
-    # look for missing '.concretetype'
-    for graph in t.flowgraphs.values():
-        traverse(no_missing_concretetype, graph)
+    sanity_check(t)
     interp = LLInterpreter(t.flowgraphs, t.rtyper)
     return interp
 
@@ -90,7 +94,9 @@
     a = t.annotate([int])
     a.simplify()
     t.specialize()
+    sanity_check(t)    # also check before inlining (so we don't blame it)
     inline_function(t, f, t.flowgraphs[g])
+    sanity_check(t)
     interp = LLInterpreter(t.flowgraphs, t.rtyper)
     result = interp.eval_function(h, [0])
     assert result == 0
@@ -168,6 +174,18 @@
     result = interp.eval_function(g, [42])
     assert result == 1
 
+def test_inline_nonraising_into_catching():
+    def f(x):
+        return x+1
+    def g(x):
+        try:
+            return f(x)
+        except KeyError:
+            return 42
+    interp = check_inline(f, g, [int])
+    result = interp.eval_function(g, [7654])
+    assert result == 7655
+
 def DONOTtest_call_call():
     # for reference.  Just remove this test if we decide not to support
     # catching exceptions while inlining a graph that contains further
@@ -187,7 +205,9 @@
     a = t.annotate([int])
     a.simplify()
     t.specialize()
+    sanity_check(t)    # also check before inlining (so we don't blame it)
     inline_function(t, f, t.flowgraphs[g])
+    sanity_check(t)
     interp = LLInterpreter(t.flowgraphs, t.rtyper)
     result = interp.eval_function(g, [100])
     assert result == 106
@@ -209,7 +229,9 @@
             break
     else:
         assert 0, "cannot find ll_rangenext_*() function"
+    sanity_check(t)    # also check before inlining (so we don't blame it)
     inline_function(t, graph, t.flowgraphs[f])
+    sanity_check(t)
     interp = LLInterpreter(t.flowgraphs, t.rtyper)
     result = interp.eval_function(f, [10])
     assert result == 45
@@ -282,6 +304,22 @@
     result = interp.eval_function(f, [])
     assert result is True
 
+def test_inline_catching_different_exception():
+    d = {1: 2}
+    def f2(n):
+        try:
+            return ovfcheck(n+1)
+        except OverflowError:
+            raise
+    def f(n):
+        try:
+            return f2(n)
+        except ValueError:
+            return -1
+    interp = check_inline(f2, f, [int])
+    result = interp.eval_function(f, [54])
+    assert result == 55
+
 def test_auto_inline_os_path_isdir():
     directory = "./."
     def f():

Modified: pypy/dist/pypy/translator/tool/make_dot.py
==============================================================================
--- pypy/dist/pypy/translator/tool/make_dot.py	(original)
+++ pypy/dist/pypy/translator/tool/make_dot.py	Wed Oct  5 14:03:20 2005
@@ -134,9 +134,11 @@
             shape = "box"
         else:
             color = "red"
-            lines.append("exitswitch: %s" % block.exitswitch)
             shape = "octagon"
 
+        if block.exitswitch is not None:
+            lines.append("exitswitch: %s" % block.exitswitch)
+
         iargs = " ".join(map(repr, block.inputargs))
         if block.exc_handler:
             eh = 'EH'
@@ -164,16 +166,14 @@
         self.emit_node(name, label=data, shape=shape, color=color, style="filled", fillcolor=fillcolor)
 
         # do links/exits
-        if numblocks == 1:
-            name2 = self.blockname(block.exits[0].target)
-            label = " ".join(map(repr, block.exits[0].args))
-            self.emit_edge(name, name2, label, style="solid")
-        elif numblocks >1:
-            for link in block.exits:
-                name2 = self.blockname(link.target)
-                label = " ".join(map(repr, link.args))
+        for link in block.exits:
+            name2 = self.blockname(link.target)
+            label = " ".join(map(repr, link.args))
+            if link.exitcase is not None:
                 label = "%s: %s" %(link.exitcase, label)
-                self.emit_edge(name, name2, label, style="dotted", color=color)
+                self.emit_edge(name, name2, label, style="dotted", color="red")
+            else:
+                self.emit_edge(name, name2, label, style="solid")
 
 
 def make_dot(graphname, graph, storedir=None, target='ps'):



More information about the Pypy-commit mailing list