[pypy-svn] r74108 - in pypy/branch/blackhole-improvement/pypy/jit/codewriter: . test

arigo at codespeak.net arigo at codespeak.net
Tue Apr 27 13:50:02 CEST 2010


Author: arigo
Date: Tue Apr 27 13:50:00 2010
New Revision: 74108

Modified:
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/regalloc.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py
Log:
Tests and fixes.  Also generate "try_catch" just before the
instruction that can actually raise, instead of just after.


Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py	Tue Apr 27 13:50:00 2010
@@ -116,7 +116,7 @@
                 self.emitline("%s_return" % kind, self.getcolor(args[0]))
         elif len(args) == 2:
             # exception block, raising an exception from a function
-            xxx
+            self.emitline("raise", self.getcolor(args[1]))
         else:
             raise Exception("?")
 
@@ -145,6 +145,35 @@
             assert link.exitcase is None
             self.make_link(link)
         #
+        elif block.exitswitch is c_last_exception:
+            # An exception block. See test_exc_exitswitch in test_flatten.py
+            # for an example of what kind of code this makes.
+            assert block.exits[0].exitcase is None # is this always True?
+            self.emitlinebefore('_call', 'try_catch', TLabel(block.exits[0]))
+            self.make_link(block.exits[0])
+            self.emitline(Label(block.exits[0]))
+            for link in block.exits[1:]:
+                if link.exitcase is Exception:
+                    # this link captures all exceptions
+                    if (link.target.operations == ()
+                        and link.args == [link.last_exception,
+                                          link.last_exc_value]):
+                        # the link is going directly to the except block
+                        self.emitline("reraise")
+                    else:
+                        self.make_exception_link(link)
+                    break
+                self.emitline('goto_if_exception_mismatch',
+                              Constant(link.llexitcase,
+                                       lltype.typeOf(link.llexitcase)),
+                              TLabel(link))
+                self.make_exception_link(link)
+                self.emitline(Label(link))
+            else:
+                # no link captures all exceptions, so we have to put a reraise
+                # for the other exceptions
+                self.emitline("reraise")
+        #
         elif len(block.exits) == 2 and (
                 isinstance(block.exitswitch, tuple) or
                 block.exitswitch.concretetype == lltype.Bool):
@@ -169,39 +198,6 @@
             self.emitline(Label(linkfalse))
             self.make_link(linkfalse)
         #
-        elif block.exitswitch is c_last_exception:
-            # An exception block. Would create something like:
-            # if exception jump first check
-            # defaultcase
-            # if not exc_1 jmp next check
-            # exc_1 case
-            # if not exc_2 jmp next check
-            # exc_2 case
-            # reraise
-            assert block.exits[0].exitcase is None # is this always True?
-            self.emitline('catch', TLabel(block.exits[0]))
-            self.make_link(block.exits[0])
-            self.emitline(Label(block.exits[0]))
-            for link in block.exits[1:]:
-                if link.exitcase is Exception:
-                    # this link captures all exceptions
-                    if (link.target.operations == ()
-                        and len(link.target.inputargs) == 2):
-                        # the link is going directly to the except block
-                        self.emitline("reraise")
-                    else:
-                        self.make_exception_link(link)
-                    break
-                self.emitline('goto_if_exception_mismatch',
-                              Constant(link.llexitcase,
-                                       lltype.typeOf(link.llexitcase)),
-                              TLabel(link))
-                self.make_exception_link(link)
-                self.emitline(Label(link))
-            else:
-                # no link captures all exceptions, so we have to put a reraise
-                # for the other exceptions
-                self.emitline("reraise")
         else:
             # A switch.
             #
@@ -278,6 +274,13 @@
     def emitline(self, *line):
         self.ssarepr.insns.append(line)
 
+    def emitlinebefore(self, name_extract, *line):
+        assert name_extract in self.ssarepr.insns[-1][0], (
+            "emitlinebefore: the %s operation should be inserted before %s,"
+            " but it does not look like a %r operation" % (
+                line, self.ssarepr.insns[-1], name_extract))
+        self.ssarepr.insns.insert(-1, line)
+
     def flatten_list(self, arglist):
         args = []
         for v in arglist:

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/regalloc.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/regalloc.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/regalloc.py	Tue Apr 27 13:50:00 2010
@@ -83,6 +83,10 @@
             # than the start, given that we resume execution from the
             # middle during blackholing.
             for link in block.exits:
+                if link.last_exception is not None:
+                    self._depgraph.add_node(link.last_exception)
+                if link.last_exc_value is not None:
+                    self._depgraph.add_node(link.last_exc_value)
                 for i, v in enumerate(link.args):
                     self._try_coalesce(v, link.target.inputargs[i])
 

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py	Tue Apr 27 13:50:00 2010
@@ -243,8 +243,8 @@
                 return 3
 
         self.encoding_test(f, [65], """
+        try_catch L1
         direct_call $<* fn g>, %i0
-        catch L1
         int_return $3
         L1:
         goto_if_exception_mismatch $<* struct object_vtable>, L2
@@ -273,8 +273,8 @@
                 return 4
 
         self.encoding_test(f, [65], """
+        try_catch L1
         residual_call_ir_v $<* fn g>, <Descr>, I[%i0], R[]
-        catch L1
         int_return $4
         L1:
         goto_if_exception_mismatch $<* struct object_vtable>, L2
@@ -285,3 +285,31 @@
         L2:
         int_return $3
         """, transform=True)
+
+    def test_exc_raise_1(self):
+        class FooError(Exception):
+            pass
+        fooerror = FooError()
+        def f(i):
+            raise fooerror
+
+        self.encoding_test(f, [65], """
+        raise $<* struct object>
+        """)
+
+    def test_exc_raise_2(self):
+        def g(i):
+            pass
+        def f(i):
+            try:
+                g(i)
+            except Exception:
+                raise KeyError
+
+        self.encoding_test(f, [65], """
+        try_catch L1
+        direct_call $<* fn g>, %i0
+        void_return
+        L1:
+        raise $<* struct object>
+        """)

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py	Tue Apr 27 13:50:00 2010
@@ -5,7 +5,8 @@
 from pypy.jit.codewriter.format import format_assembler
 from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
-from pypy.rpython.lltypesystem import lltype
+from pypy.objspace.flow.model import c_last_exception
+from pypy.rpython.lltypesystem import lltype, rclass
 
 
 class TestRegAlloc:
@@ -145,3 +146,33 @@
             rescall I[%i0, %i1], %i0
             int_return %i0
         """)
+
+    def test_regalloc_exitswitch_2(self):
+        v1 = Variable(); v1.concretetype = rclass.CLASSTYPE
+        v2 = Variable(); v2.concretetype = rclass.CLASSTYPE
+        v3 = Variable(); v3.concretetype = rclass.CLASSTYPE
+        v4 = Variable(); v4.concretetype = rclass.CLASSTYPE
+        block = Block([])
+        block.operations = [
+            SpaceOperation('res_call', [], v1),
+            ]
+        graph = FunctionGraph('f', block, v4)
+        exclink = Link([v2], graph.returnblock)
+        exclink.llexitcase = 123     # normally an exception class
+        exclink.last_exception = v2
+        exclink.last_exc_value = "unused"
+        block.exitswitch = c_last_exception
+        block.closeblock(Link([v1], graph.returnblock),
+                         exclink)
+        #
+        self.check_assembler(graph, """
+            try_catch L1
+            res_call %i0
+            int_return %i0
+            L1:
+            goto_if_exception_mismatch $123, L2
+            last_exception %i0
+            int_return %i0
+            L2:
+            reraise
+        """)



More information about the Pypy-commit mailing list