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