[pypy-svn] r58850 - in pypy/dist/pypy/translator/backendopt: . test

arigo at codespeak.net arigo at codespeak.net
Wed Oct 8 19:34:49 CEST 2008


Author: arigo
Date: Wed Oct  8 19:34:48 2008
New Revision: 58850

Modified:
   pypy/dist/pypy/translator/backendopt/mallocv.py
   pypy/dist/pypy/translator/backendopt/test/test_mallocv.py
Log:
(fijal, antocuni, arigo)
Return values from inlined called functions -- works.


Modified: pypy/dist/pypy/translator/backendopt/mallocv.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/mallocv.py	(original)
+++ pypy/dist/pypy/translator/backendopt/mallocv.py	Wed Oct  8 19:34:48 2008
@@ -301,8 +301,14 @@
                 # so we can stop specializing.
                 specblock = link.target
             else:
-                newframe = VirtualFrame(link.target, 0, targetnodes,
-                                        callerframe=currentframe.callerframe)
+                if len(link.target.exits) == 0:    # return or except block
+                    if currentframe.callerframe is None:
+                        raise CannotVirtualize("return or except block")
+                    newframe = self.return_to_caller(currentframe,
+                                                     link.target, targetnodes)
+                else:
+                    newframe = VirtualFrame(link.target, 0, targetnodes,
+                                          callerframe=currentframe.callerframe)
                 rtnodes = newframe.find_rt_nodes()
                 specblock = self.get_specialized_block(newframe)
 
@@ -313,15 +319,20 @@
             newlinks.append(newlink)
         return v_exitswitch, newlinks
 
+    def return_to_caller(self, currentframe, returnblock, targetnodes):
+        [v_ret] = returnblock.inputargs
+        retnode = targetnodes[v_ret]
+        callerframe = currentframe.callerframe
+        for i in range(len(callerframe.nodelist)):
+            if isinstance(callerframe.nodelist[i], FutureReturnValue):
+                callerframe.nodelist[i] = retnode
+        return callerframe
+
     def get_specialized_block(self, virtualframe):
         specblock = self.cache.lookup_spec_block(virtualframe)
         if specblock is None:
             orgblock = virtualframe.sourceblock
-            if len(orgblock.exits) == 0:
-                if virtualframe.callerframe is None:
-                    raise CannotVirtualize("return or except block")
-                else:
-                    return self.get_specialized_block(virtualframe.callerframe)
+            assert len(orgblock.exits) != 0
             spec = BlockSpecializer(self)
             specinputargs = spec.initialize_renamings(virtualframe.copy({}))
             specblock = Block(specinputargs)
@@ -496,6 +507,7 @@
     def handle_mutable_call(self, op, graph, newnodes):
         sourceblock = self.virtualframe.sourceblock
         nextopindex = self.virtualframe.nextopindex
+        self.nodes[op.result] = FutureReturnValue(op)
         myframe = VirtualFrame(sourceblock, nextopindex,
                                self.nodes,
                                self.virtualframe.callerframe)
@@ -507,11 +519,24 @@
         self.nodes = calleeframe.get_nodes_in_use()
         return []
 
+
+class FutureReturnValue(object):
+    def __init__(self, op):
+        self.op = op    # for debugging
+    def getfrozenkey(self, memo):
+        return None
+    def accumulate_rt_nodes(self, memo, result):
+        pass
+    def copy(self, memo):
+        return self
+
 # ____________________________________________________________
 # helpers
 
 def vars_alive_through_op(block, index):
     # NB. make sure this always returns the variables in the same order
+    if len(block.exits) == 0:
+        return block.inputargs   # return or except block
     result = []
     seen = {}
     def see(v):

Modified: pypy/dist/pypy/translator/backendopt/test/test_mallocv.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_mallocv.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_mallocv.py	Wed Oct  8 19:34:48 2008
@@ -108,6 +108,34 @@
         insns = summary(graph)
         assert insns.get('direct_call', 0) == 0     # no more call, inlined
 
+    def test_direct_call_mutable_retval(self):
+        A = lltype.GcStruct('A', ('x', lltype.Signed))
+        def g(a):
+            a.x += 1
+            return a.x * 100
+        def f(x):
+            a = lltype.malloc(A)
+            a.x = x
+            y = g(a)
+            return a.x + y
+        graph = self.check(f, [int], [41], 4242)
+        insns = summary(graph)
+        assert insns.get('direct_call', 0) == 0     # no more call, inlined
+
+    def test_direct_call_mutable_ret_virtual(self):
+        A = lltype.GcStruct('A', ('x', lltype.Signed))
+        def g(a):
+            a.x += 1
+            return a
+        def f(x):
+            a = lltype.malloc(A)
+            a.x = x
+            b = g(a)
+            return a.x + b.x
+        graph = self.check(f, [int], [41], 84)
+        insns = summary(graph)
+        assert insns.get('direct_call', 0) == 0     # no more call, inlined
+
     def test_fn2(self):
         py.test.skip("redo me")
         class T:



More information about the Pypy-commit mailing list