Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r76741:36a76678c87c
Date: 2015-04-07 19:58 +0200
http://bitbucket.org/pypy/pypy/changeset/36a76678c87c/

Log:    Refine RaiseAnalyzer to be able to distinguish between "real"
        exceptions and what is "merely" MemoryErrors.

diff --git a/rpython/translator/backendopt/canraise.py 
b/rpython/translator/backendopt/canraise.py
--- a/rpython/translator/backendopt/canraise.py
+++ b/rpython/translator/backendopt/canraise.py
@@ -9,9 +9,15 @@
 
 
 class RaiseAnalyzer(graphanalyze.BoolGraphAnalyzer):
+    ignore_exact_class = None
+
+    def do_ignore_memory_error(self):
+        self.ignore_exact_class = MemoryError
+
     def analyze_simple_operation(self, op, graphinfo):
         try:
-            return bool(LL_OPERATIONS[op.opname].canraise)
+            canraise = LL_OPERATIONS[op.opname].canraise
+            return bool(canraise) and canraise != (self.ignore_exact_class,)
         except KeyError:
             log.WARNING("Unknown operation: %s" % op.opname)
             return True
@@ -20,7 +26,22 @@
         fnobj = op.args[0].value._obj
         return getattr(fnobj, 'canraise', True)
 
-    def analyze_exceptblock(self, block, seen=None):
+    analyze_exceptblock = None    # don't call this
+
+    def analyze_exceptblock_in_graph(self, graph, block, seen=None):
+        if self.ignore_exact_class is not None:
+            from rpython.translator.backendopt.ssa import DataFlowFamilyBuilder
+            dff = DataFlowFamilyBuilder(graph)
+            variable_families = dff.get_variable_families()
+            v_exc_instance = variable_families.find_rep(block.inputargs[1])
+            for link1 in graph.iterlinks():
+                v = link1.last_exc_value
+                if v is not None:
+                    if variable_families.find_rep(v) is v_exc_instance:
+                        # this is a case of re-raise the exception caught;
+                        # it doesn't count.  We'll see the place that really
+                        # raises the exception in the first place.
+                        return False
         return True
 
     # backward compatible interface
diff --git a/rpython/translator/backendopt/graphanalyze.py 
b/rpython/translator/backendopt/graphanalyze.py
--- a/rpython/translator/backendopt/graphanalyze.py
+++ b/rpython/translator/backendopt/graphanalyze.py
@@ -49,6 +49,9 @@
     def analyze_exceptblock(self, block, seen=None):
         return self.bottom_result()
 
+    def analyze_exceptblock_in_graph(self, graph, block, seen=None):
+        return self.analyze_exceptblock(block, seen)
+
     def analyze_startblock(self, block, seen=None):
         return self.bottom_result()
 
@@ -121,7 +124,7 @@
             elif block is graph.exceptblock:
                 result = self.add_to_result(
                     result,
-                    self.analyze_exceptblock(block, seen)
+                    self.analyze_exceptblock_in_graph(graph, block, seen)
                 )
             if not self.is_top_result(result):
                 for op in block.operations:
diff --git a/rpython/translator/backendopt/test/test_canraise.py 
b/rpython/translator/backendopt/test/test_canraise.py
--- a/rpython/translator/backendopt/test/test_canraise.py
+++ b/rpython/translator/backendopt/test/test_canraise.py
@@ -225,3 +225,32 @@
         fgraph = graphof(t, f)
         result = ra.can_raise(fgraph.startblock.operations[0])
         assert not result
+
+    def test_memoryerror(self):
+        def f(x):
+            return [x, 42]
+        t, ra = self.translate(f, [int])
+        result = ra.analyze_direct_call(graphof(t, f))
+        assert result
+        #
+        ra = RaiseAnalyzer(t)
+        ra.do_ignore_memory_error()
+        result = ra.analyze_direct_call(graphof(t, f))
+        assert not result
+        #
+        def g(x):
+            try:
+                return f(x)
+            except:
+                raise
+        t, ra = self.translate(g, [int])
+        ra.do_ignore_memory_error()
+        result = ra.analyze_direct_call(graphof(t, g))
+        assert not result
+        #
+        def h(x):
+            return {5:6}[x]
+        t, ra = self.translate(h, [int])
+        ra.do_ignore_memory_error()     # but it's potentially a KeyError
+        result = ra.analyze_direct_call(graphof(t, h))
+        assert result
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to