[pypy-svn] r28184 - in pypy/dist/pypy/translator: c stackless stackless/test

mwh at codespeak.net mwh at codespeak.net
Sat Jun 3 18:25:30 CEST 2006


Author: mwh
Date: Sat Jun  3 18:25:27 2006
New Revision: 28184

Modified:
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/stackless/test/test_resume_point.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
(mwh, pedronis)
Another resume_point test, resuming with an instance value.
For variety, run it through genc and add the miniscule support genc needed for
this.
It works, but it really shouldn't :)
Next on the menu: making it fail.


Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Sat Jun  3 18:25:27 2006
@@ -663,6 +663,9 @@
         typename = cdecl(self.db.gettype(TYPE), '')        
         return "%(result)s = (%(typename)s)(%(val)s);" % locals()
 
+    def OP_RESUME_POINT(self, op):
+        return '/* resume point %s */'%(op.args[0],)
+
     def OP_DEBUG_PRINT(self, op):
         # XXX
         from pypy.rpython.lltypesystem.rstr import STR

Modified: pypy/dist/pypy/translator/stackless/test/test_resume_point.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_resume_point.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_resume_point.py	Sat Jun  3 18:25:27 2006
@@ -1,5 +1,5 @@
 from pypy.translator.stackless.transform import StacklessTransformer
-from pypy.translator.stackless.test.test_transform import llinterp_stackless_function, rtype_stackless_function, one
+from pypy.translator.stackless.test.test_transform import llinterp_stackless_function, rtype_stackless_function, one, run_stackless_function
 from pypy import conftest
 import py
 from pypy.rpython import rstack
@@ -123,3 +123,20 @@
         return v1*100 + rstack.resume_state_invoke(int, s1)
     res = llinterp_stackless_function(example, assert_unwind=False)
     assert res == 406
+
+def test_really_return_instance():
+    class C:
+        pass
+    def g(x):
+        c = C()
+        c.x = x + 1
+        rstack.resume_point("rp1", c)
+        return c
+    def example():
+        v1 = g(one()).x
+        c = C()
+        c.x = 4*one()
+        s1 = rstack.resume_state_create(None, "rp1", c)
+        return v1*100 + rstack.resume_state_invoke(C, s1).x
+    res = run_stackless_function(example)
+    assert res == 204

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Sat Jun  3 18:25:27 2006
@@ -112,7 +112,7 @@
             return True
         elif op.opname == 'resume_point':
             return True
-        elif op.opname == 'resume_point_invoke':
+        elif op.opname == 'resume_state_invoke':
             return True
         return self.stackless_gc and LL_OPERATIONS[op.opname].canunwindgc
 
@@ -394,23 +394,8 @@
                 newblock.exitswitch = None
 
             if resume_point.var_result.concretetype != rettype:
-                llops = LowLevelOpList()
-                newvar = gen_cast(llops,
-                                  resume_point.var_result.concretetype,
-                                  retval)
-                convertblock = unsimplify.insert_empty_block(
-                    None, newblock.exits[0], llops)
-                # begin ouch!
-                for index, linkvar in enumerate(convertblock.exits[0].args):
-                    # does this var come from retval ?
-                    try:
-                        index1 = convertblock.inputargs.index(linkvar)
-                    except ValueError:   # e.g. linkvar is a Constant
-                        continue
-                    if newblock.exits[0].args[index1] is retval:
-                        # yes
-                        convertblock.exits[0].args[index] = newvar
-                # end ouch!
+                self.insert_return_conversion(
+                    newblock.exits[0], resume_point.var_result.concretetype, retval)
             
             resuming_links.append(
                 model.Link([], newblock, resume_point_index))
@@ -422,6 +407,25 @@
         new_start_block.isstartblock = True
         graph.startblock = new_start_block
 
+    def insert_return_conversion(self, link, targettype, retvar):
+        llops = LowLevelOpList()
+        newvar = gen_cast(llops, targettype, retvar)
+        convertblock = unsimplify.insert_empty_block(None, link, llops)
+        # begin ouch!
+        foundit = False
+        for index, linkvar in enumerate(convertblock.exits[0].args):
+            # does this var come from retval ?
+            try:
+                index1 = convertblock.inputargs.index(linkvar)
+            except ValueError:   # e.g. linkvar is a Constant
+                continue
+            if link.args[index1] is retvar:
+                foundit = True
+                # yes
+                convertblock.exits[0].args[index] = newvar
+        # end ouch!
+        assert foundit
+        
     def handle_resume_point(self, block, i):
         # in some circumstances we might be able to reuse
         # an already inserted resume point
@@ -508,20 +512,30 @@
         llops.append(model.SpaceOperation('same_as', [v_state], op.result))
         block.operations[i:i+1] = llops
 
-    def handle_resume_state_invoke(self, block, i):
-        op = block.operations[i]
-        if op.result.concretetype != lltype.Signed:
-            raise NotImplementedError
+    def handle_resume_state_invoke(self, block):
+        op = block.operations[-1]
+        assert op.opname == 'resume_state_invoke'
+        rettype = storage_type(op.result.concretetype)
+        if op.result.concretetype != rettype:
+            retvar = varoftype(rettype)
+        else:
+            retvar = op.result
         v_returns = op.args[1]
         if v_returns.concretetype == lltype.Signed:
             raise NotImplementedError
         elif v_returns.concretetype == lltype.Void:
             args = [self.resume_after_void_ptr] + op.args
-            newop = model.SpaceOperation('direct_call', args, op.result)
-            block.operations[i] = newop
+            newop = model.SpaceOperation('direct_call', args, retvar)
+            block.operations[-1] = newop
         else:
             raise NotImplementedError
-        return newop
+        if retvar is not op.result:
+            noexclink = block.exits[0]
+            for i, a in enumerate(noexclink.args):
+                if a is op.result:
+                    noexclink.args[i] = retvar
+            self.insert_return_conversion(
+                noexclink, op.result.concretetype, retvar)
 
     def transform_block(self, block):
         i = 0
@@ -543,10 +557,6 @@
                 op = replace_with_call(self.yield_current_frame_to_caller_ptr)
                 stackless_op = True
 
-            if op.opname == 'resume_state_invoke':
-                op = self.handle_resume_state_invoke(block, i)
-                stackless_op = True
-
             if op.opname == 'resume_state_create':
                 self.handle_resume_state_create(block, i)
                 continue # go back and look at that malloc
@@ -556,7 +566,7 @@
                 if op.opname == 'resume_point':
                     block, i = self.handle_resume_point(block, i)
                     continue
-                    
+                
                 # trap calls to stackless-related suggested primitives
                 if op.opname == 'direct_call':
                     func = getattr(op.args[0].value._obj, '_callable', None)
@@ -616,6 +626,11 @@
                 # function be called right at the end of the resuming
                 # block, and that it is called even if the return
                 # value is not again used.
+
+                if op.opname == 'resume_state_invoke':
+                    self.handle_resume_state_invoke(block)
+                    op = block.operations[-1]
+
                 args = vars_to_save(block)
 
                 save_block, frame_state_type, fieldnames = \



More information about the Pypy-commit mailing list