[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