[pypy-svn] r24617 - in pypy/dist/pypy/translator/c: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Mon Mar 20 17:17:42 CET 2006
Author: cfbolz
Date: Mon Mar 20 17:17:31 2006
New Revision: 24617
Modified:
pypy/dist/pypy/translator/c/exceptiontransform.py
pypy/dist/pypy/translator/c/test/test_exceptiontransform.py
Log:
small refactoring to the exception transformation:
use a class to prevent the growth of a Huge Function From Hell (tm)
use the RaiseAnalyzer to find out which calls can raise at all
Modified: pypy/dist/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/dist/pypy/translator/c/exceptiontransform.py (original)
+++ pypy/dist/pypy/translator/c/exceptiontransform.py Mon Mar 20 17:17:31 2006
@@ -1,55 +1,56 @@
from pypy.translator.unsimplify import split_block
+from pypy.translator.backendopt import canraise
from pypy.objspace.flow.model import Block, Constant, Variable, Link, \
c_last_exception, SpaceOperation
from pypy.rpython import rclass
-n_calls = n_calls_patched = 0
+class ExceptionTransformer(object):
+ def __init__(self, translator):
+ self.translator = translator
+ self.raise_analyzer = canraise.RaiseAnalyzer(translator)
+
+ def create_exception_handling(self, graph):
+ """After an exception in a direct_call (or indirect_call), that is not caught
+ by an explicit
+ except statement, we need to reraise the exception. So after this
+ direct_call we need to test if an exception had occurred. If so, we return
+ from the current graph with an unused value (false/0/0.0/null).
+ Because of the added exitswitch we need an additional block.
+ """
+ exc_data = self.translator.rtyper.getexceptiondata()
+ for block in graph.iterblocks():
+ last_operation = len(block.operations)-1
+ if block.exitswitch == c_last_exception:
+ last_operation -= 1
+ for i in range(last_operation, -1, -1):
+ op = block.operations[i]
+ print "considering op", op, i
+ if not self.raise_analyzer.can_raise(op):
+ continue
+ called_can_raise = True #XXX maybe we even want a list of possible exceptions
+ if not called_can_raise:
+ continue
+
+ afterblock = split_block(self.translator, graph, block, i+1)
+
+ block.exitswitch = c_last_exception
+
+ #non-exception case
+ block.exits[0].exitcase = block.exits[0].llexitcase = None
+
+ #exception occurred case
+ etype = Variable('extra_etype')
+ etype.concretetype = exc_data.lltype_of_exception_type
+ evalue = Variable('extra_evalue')
+ evalue.concretetype = exc_data.lltype_of_exception_value
+
+ l = Link([etype, evalue], graph.exceptblock)
+ l.extravars(etype, evalue)
+ l.prevblock = block
+ l.exitcase = Exception
+ r_case = rclass.get_type_repr(self.translator.rtyper)
+ l.llexitcase = r_case.convert_const(l.exitcase)
-def create_exception_handling(translator, graph):
- """After an exception in a direct_call (or indirect_call), that is not caught
- by an explicit
- except statement, we need to reraise the exception. So after this
- direct_call we need to test if an exception had occurred. If so, we return
- from the current graph with an unused value (false/0/0.0/null).
- Because of the added exitswitch we need an additional block.
- """
- global n_calls, n_calls_patched
- n_calls_patched_begin = n_calls_patched
- e = translator.rtyper.getexceptiondata()
- for block in graph.iterblocks():
- last_operation = len(block.operations)-1
- if block.exitswitch == c_last_exception:
- last_operation -= 1
- for i in range(last_operation, -1, -1):
- op = block.operations[i]
- if op.opname not in ('direct_call', 'indirect_call'):
- continue
- n_calls += 1
- called_can_raise = True #XXX maybe we even want a list of possible exceptions
- if not called_can_raise:
- continue
- n_calls_patched += 1
-
- afterblock = split_block(translator, graph, block, i+1)
-
- block.exitswitch = c_last_exception
-
- #non-exception case
- block.exits[0].exitcase = block.exits[0].llexitcase = None
-
- #exception occurred case
- etype = Variable('extra_etype')
- etype.concretetype = e.lltype_of_exception_type
- evalue = Variable('extra_evalue')
- evalue.concretetype = e.lltype_of_exception_value
-
- l = Link([etype, evalue], graph.exceptblock)
- l.extravars(etype, evalue)
- l.prevblock = block
- l.exitcase = Exception
- r_case = rclass.get_type_repr(translator.rtyper)
- l.llexitcase = r_case.convert_const(l.exitcase)
-
- block.exits.append(l)
+ block.exits.append(l)
Modified: pypy/dist/pypy/translator/c/test/test_exceptiontransform.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_exceptiontransform.py (original)
+++ pypy/dist/pypy/translator/c/test/test_exceptiontransform.py Mon Mar 20 17:17:31 2006
@@ -11,16 +11,10 @@
if conftest.option.view:
t.view()
g = graphof(t, fn)
- exceptiontransform.create_exception_handling(t, g)
+ etrafo = exceptiontransform.ExceptionTransformer(t)
+ etrafo.create_exception_handling(g)
if conftest.option.view:
t.view()
- for b in g.iterblocks():
- l = len(b.operations)
- for i in range(l):
- op = b.operations[i]
- if op.opname == 'direct_call':
- assert i == l-1
- assert b.exitswitch is c_last_exception
return t, g
def test_simple():
@@ -32,6 +26,16 @@
one()
t, g = transform_func(foo, [])
+ assert len(list(g.iterblocks())) == 2 # graph does not change
-
-
+def test_raises():
+ def one(x):
+ if x:
+ raise ValueError()
+
+ def foo():
+ one(0)
+ one(1)
+ t, g = transform_func(foo, [])
+ assert len(list(g.iterblocks())) == 5
+
More information about the Pypy-commit
mailing list