[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