[pypy-svn] r32034 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/test translator/c translator/c/test

arigo at codespeak.net arigo at codespeak.net
Wed Sep 6 21:34:35 CEST 2006


Author: arigo
Date: Wed Sep  6 21:34:33 2006
New Revision: 32034

Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/test/test_llinterp.py
   pypy/dist/pypy/translator/c/exceptiontransform.py
   pypy/dist/pypy/translator/c/test/test_exceptiontransform.py
Log:
(pedronis, arigo)

Attach the ExcData produced by the exception transformer to each
transformed graph.  This allows llinterpretation of a mixture of
transformed and non-transformed graphs, with conversion between the
stored-in-ExcData and raised-as-LLException styles.



Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Wed Sep  6 21:34:33 2006
@@ -1,6 +1,7 @@
 from pypy.objspace.flow.model import FunctionGraph, Constant, Variable, c_last_exception
 from pypy.rpython.rarithmetic import intmask, r_uint, ovfcheck, r_longlong, r_ulonglong
 from pypy.rpython.lltypesystem import lltype, llmemory, lloperation, llheap
+from pypy.rpython.lltypesystem import rclass
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.objectmodel import ComputedIntSymbolic
 
@@ -14,7 +15,7 @@
 class LLException(Exception):
     def __str__(self):
         etype = self.args[0]
-        evalue = self.args[0]
+        #evalue = self.args[1]
         if len(self.args) > 2:
             f = cStringIO.StringIO()
             original_type, original_value, original_tb = self.args[2]
@@ -277,6 +278,15 @@
                 evalue = self.getval(evaluevar)
                 # watch out, these are _ptr's
                 raise LLException(etype, evalue)
+            if hasattr(self.graph, 'exceptiontransformed'):
+                # re-raise the exception set by this graph, if any
+                exc_data = self.graph.exceptiontransformed
+                etype = rclass.fishllattr(exc_data, 'exc_type')
+                if etype:
+                    evalue = rclass.fishllattr(exc_data, 'exc_value')
+                    if tracer:
+                        tracer.dump('raise')
+                    raise LLException(etype, evalue)
             if tracer:
                 tracer.dump('return')
             resultvar, = block.getvariables()
@@ -504,7 +514,19 @@
 
     def op_direct_call(self, f, *args):
         FTYPE = self.llinterpreter.typer.type_system.derefType(lltype.typeOf(f))
-        return self.perform_call(f, FTYPE.ARGS, args)
+        try:
+            return self.perform_call(f, FTYPE.ARGS, args)
+        except LLException, e:
+            if hasattr(self.graph, 'exceptiontransformed'):
+                # store the LLException into the exc_data used by this graph
+                exc_data = self.graph.exceptiontransformed
+                etype = e.args[0]
+                evalue = e.args[1]
+                rclass.feedllattr(exc_data, 'exc_type', etype)
+                rclass.feedllattr(exc_data, 'exc_value', evalue)
+                from pypy.translator.c.exceptiontransform import error_value
+                return error_value(FTYPE.RESULT).value
+            raise
 
     op_safe_call = op_direct_call
 

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Wed Sep  6 21:34:33 2006
@@ -858,3 +858,17 @@
         raise AttributeError("%s has no field %s" % (lltype.typeOf(widest),
                                                      name))
     return default
+
+def feedllattr(inst, name, llvalue):
+    p = widest = lltype.normalizeptr(inst)
+    while True:
+        try:
+            return setattr(p, 'inst_' + name, llvalue)
+        except AttributeError:
+            pass
+        try:
+            p = p.super
+        except AttributeError:
+            break
+    raise AttributeError("%s has no field %s" % (lltype.typeOf(widest),
+                                                 name))

Modified: pypy/dist/pypy/rpython/test/test_llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_llinterp.py	(original)
+++ pypy/dist/pypy/rpython/test/test_llinterp.py	Wed Sep  6 21:34:33 2006
@@ -5,7 +5,7 @@
 from pypy.rpython.rmodel import inputconst
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.rint import signed_repr
-from pypy.rpython.lltypesystem import rstr
+from pypy.rpython.lltypesystem import rstr, lltype
 from pypy.annotation import model as annmodel
 from pypy.annotation.model import lltype_to_annotation
 from pypy.rpython.rarithmetic import r_uint, ovfcheck
@@ -495,3 +495,53 @@
     graph = graphof(t, bb)
     interp = LLInterpreter(t.rtyper)
     res = interp.eval_graph(graph, [1])
+
+def test_half_exceptiontransformed_graphs():
+    from pypy.translator.c import exceptiontransform
+    def f1(x):
+        if x < 0:
+            raise ValueError
+        return 754
+    def g1(x):
+        try:
+            return f1(x)
+        except ValueError:
+            return 5
+    def f2(x):
+        if x < 0:
+            raise ValueError
+        return 21
+    def g2(x):
+        try:
+            return f2(x)
+        except ValueError:
+            return 6
+    f3 = lltype.functionptr(lltype.FuncType([lltype.Signed], lltype.Signed),
+                            'f3', _callable = f1)
+    def g3(x):
+        try:
+            return f3(x)
+        except ValueError:
+            return 7
+    def f(flag, x):
+        if flag == 1:
+            return g1(x)
+        elif flag == 2:
+            return g2(x)
+        else:
+            return g3(x)
+    t = TranslationContext()
+    t.buildannotator().build_types(f, [int, int])
+    t.buildrtyper().specialize()
+    etrafo = exceptiontransform.ExceptionTransformer(t)
+    etrafo.create_exception_handling(graphof(t, f1))
+    etrafo.create_exception_handling(graphof(t, g2))
+    etrafo.create_exception_handling(graphof(t, g3))
+    graph = graphof(t, f)
+    interp = LLInterpreter(t.rtyper)
+    res = interp.eval_graph(graph, [1, -64])
+    assert res == 5
+    res = interp.eval_graph(graph, [2, -897])
+    assert res == 6
+    res = interp.eval_graph(graph, [3, -9831])
+    assert res == 7

Modified: pypy/dist/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/dist/pypy/translator/c/exceptiontransform.py	(original)
+++ pypy/dist/pypy/translator/c/exceptiontransform.py	Wed Sep  6 21:34:33 2006
@@ -137,13 +137,12 @@
 
         ExcDataDef = translator.annotator.bookkeeper.getuniqueclassdef(ExcData)
         self.ExcData_repr = rclass.getinstancerepr(translator.rtyper, ExcDataDef)
-        exc_data_ptr = self.ExcData_repr.convert_const(exc_data)
-        self.cexcdata = Constant(exc_data_ptr, self.ExcData_repr.lowleveltype)
+        self.exc_data_ptr = self.ExcData_repr.convert_const(exc_data)
+        self.cexcdata = Constant(self.exc_data_ptr,
+                                 self.ExcData_repr.lowleveltype)
         
         self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
 
-        self.seen_graphs = {}
-    
     def transform_completely(self):
         for graph in self.translator.graphs:
             self.create_exception_handling(graph)
@@ -156,8 +155,12 @@
         from the current graph with a special value (False/-1/-1.0/null).
         Because of the added exitswitch we need an additional block.
         """
-        assert graph not in self.seen_graphs
-        self.seen_graphs[graph] = True
+        if hasattr(graph, 'exceptiontransformed'):
+            assert self.exc_data_ptr._same_obj(graph.exceptiontransformed)
+            return
+        else:
+            graph.exceptiontransformed = self.exc_data_ptr
+
         join_blocks(graph)
         # collect the blocks before changing them
         n_need_exc_matching_blocks = 0

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	Wed Sep  6 21:34:33 2006
@@ -185,4 +185,5 @@
     g = graphof(t, f)
     etrafo = exceptiontransform.ExceptionTransformer(t)
     etrafo.create_exception_handling(g)
-    py.test.raises(AssertionError, etrafo.create_exception_handling, g)
+    etrafo2 = exceptiontransform.ExceptionTransformer(t)
+    py.test.raises(AssertionError, etrafo2.create_exception_handling, g)



More information about the Pypy-commit mailing list