[pypy-svn] r28240 - in pypy/dist/pypy: rpython rpython/lltypesystem translator/stackless translator/stackless/test
mwh at codespeak.net
mwh at codespeak.net
Sun Jun 4 12:37:50 CEST 2006
Author: mwh
Date: Sun Jun 4 12:37:48 2006
New Revision: 28240
Modified:
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
pypy/dist/pypy/rpython/rstack.py
pypy/dist/pypy/translator/stackless/code.py
pypy/dist/pypy/translator/stackless/test/test_resume_point.py
pypy/dist/pypy/translator/stackless/transform.py
Log:
(mwh, pedronis)
* support for Constant arguments to resume_state_create and
resume_state_invoke.
* some sanity checks here and there
* add a raising= argument to resume_state_invoke, and test it.
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sun Jun 4 12:37:48 2006
@@ -344,7 +344,7 @@
'yield_current_frame_to_caller': LLOp(canraise=(StackException,)),
# can always unwind, not just if stackless gc
- 'resume_point': LLOp(),
+ 'resume_point': LLOp(canraise=(Exception,)),
'resume_state_create': LLOp(canraise=(MemoryError,), canunwindgc=True),
'resume_state_invoke': LLOp(canraise=(Exception, StackException)),
Modified: pypy/dist/pypy/rpython/rstack.py
==============================================================================
--- pypy/dist/pypy/rpython/rstack.py (original)
+++ pypy/dist/pypy/rpython/rstack.py Sun Jun 4 12:37:48 2006
@@ -48,6 +48,7 @@
def specialize_call(self, hop, **kwds_i):
from pypy.rpython.lltypesystem import lltype
+ from pypy.objspace.flow import model
assert hop.args_s[0].is_constant()
c_label = hop.inputconst(lltype.Void, hop.args_s[0].const)
@@ -56,10 +57,15 @@
assert len(kwds_i) == 1
returns_index = kwds_i['i_returns']
v_return = args_v.pop(returns_index-1)
+ assert isinstance(v_return, model.Variable), \
+ "resume_point returns= argument must be a Variable"
else:
assert not kwds_i
v_return = hop.inputconst(lltype.Void, None)
+ for v in args_v:
+ assert isinstance(v, model.Variable), "resume_point arguments must be Variables"
+
hop.exception_is_here()
return hop.genop('resume_point', [c_label, v_return] + args_v,
hop.r_result)
@@ -70,6 +76,16 @@
def resume_state_create(prevstate, label, *args):
raise RuntimeError("cannot resume states in non-translated versions")
+def concretify_argument(hop, index):
+ from pypy.objspace.flow import model
+
+ v_arg = hop.args_v[index]
+ if isinstance(v_arg, model.Variable):
+ return v_arg
+
+ r_arg = hop.rtyper.bindingrepr(v_arg)
+ return hop.inputarg(r_arg, arg=index)
+
class ResumeStateCreateFnEntry(ExtRegistryEntry):
_about_ = resume_state_create
@@ -86,8 +102,10 @@
c_label = hop.inputconst(lltype.Void, hop.args_s[1].const)
v_state = hop.inputarg(hop.r_result, arg=0)
-
- args_v = hop.args_v[2:]
+
+ args_v = []
+ for i in range(2, len(hop.args_v)):
+ args_v.append(concretify_argument(hop, i))
hop.exception_is_here()
return hop.genop('resume_state_create', [v_state, c_label] + args_v,
@@ -119,14 +137,21 @@
if 'i_returning' in kwds_i:
assert len(kwds_i) == 1
- returns_index = kwds_i['i_returning']
- v_return = hop.args_v[returns_index]
+ returning_index = kwds_i['i_returning']
+ v_returning = concretify_argument(hop, returning_index)
+ v_raising = hop.inputconst(lltype.Void, None)
+ elif 'i_raising' in kwds_i:
+ assert len(kwds_i) == 1
+ raising_index = kwds_i['i_raising']
+ v_returning = hop.inputconst(lltype.Void, None)
+ v_raising = concretify_argument(hop, raising_index)
else:
assert not kwds_i
- v_return = hop.inputconst(lltype.Void, None)
+ v_returning = hop.inputconst(lltype.Void, None)
+ v_raising = hop.inputconst(lltype.Void, None)
hop.exception_is_here()
- return hop.genop('resume_state_invoke', [v_state, v_return],
+ return hop.genop('resume_state_invoke', [v_state, v_returning, v_raising],
hop.r_result)
Modified: pypy/dist/pypy/translator/stackless/code.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/code.py (original)
+++ pypy/dist/pypy/translator/stackless/code.py Sun Jun 4 12:37:48 2006
@@ -215,6 +215,39 @@
[RESUME_AFTER_STATE,
EMPTY_STATE])
+
+def resume_after_raising(state, exception):
+ if global_state.restart_substate == -1:
+ # normal entry point for a call to state.switch()
+ # first unwind the stack
+ u = UnwindException()
+ s = lltype.malloc(RESUME_AFTER_STATE)
+ s.header.f_restart = INDEX_RESUME_AFTER_RAISING
+ s.c = state
+ add_frame_state(u, s.header)
+ global_state.exception = exception
+ raise u
+ elif global_state.restart_substate == 0:
+ # STATE 0: we didn't do anything so far, but the stack is unwound
+ global_state.restart_substate = -1
+ # grab the frame corresponding to ourself
+ # the 'targetstate' local is garbage here, it must be read back from
+ # 's.c' where we saved it by the normal entry point above
+ mystate = global_state.top
+ s = lltype.cast_pointer(lltype.Ptr(RESUME_AFTER_STATE), mystate)
+ targetstate = s.c
+ resume_bottom = targetstate
+ while resume_bottom.f_back:
+ resume_bottom = resume_bottom.f_back
+ resume_bottom.f_back = mystate.f_back
+ global_state.top = targetstate
+ raise UnwindException()
+
+resume_after_raising.stackless_explicit = True
+INDEX_RESUME_AFTER_RAISING = frame.RestartInfo.add_prebuilt(resume_after_raising,
+ [RESUME_AFTER_STATE,
+ EMPTY_STATE])
+
template = """\
def resume_after_%(typename)s(state, retvalue):
if global_state.restart_substate == -1:
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 Sun Jun 4 12:37:48 2006
@@ -201,4 +201,25 @@
return v1*100 + v2
res = llinterp_stackless_function(example)
assert res == 141
+
+def test_invoke_raising():
+ def g(x):
+ rstack.resume_point("rp0", x)
+ return x + 1
+ def f(x):
+ x = x - 1
+ try:
+ r = g(x)
+ rstack.resume_point("rp1", returns=r)
+ except KeyError:
+ r = 42
+ return r - 1
+ def example():
+ v1 = f(one()+one())
+ s1 = rstack.resume_state_create(None, "rp1")
+ s0 = rstack.resume_state_create(s1, "rp0", 0)
+ v2 = rstack.resume_state_invoke(int, s0, raising=KeyError())
+ return v1*100 + v2
+ res = llinterp_stackless_function(example)
+ assert res == 141
Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py (original)
+++ pypy/dist/pypy/translator/stackless/transform.py Sun Jun 4 12:37:48 2006
@@ -260,6 +260,13 @@
[s_hdrptr, annmodel.SomePtr(SAVED_REFERENCE)],
annmodel.s_None),
}
+ exception_def = bk.getuniqueclassdef(Exception)
+ self.resume_after_raising_ptr = mixlevelannotator.constfunc(
+ code.resume_after_raising,
+ [s_hdrptr, annmodel.SomeInstance(exception_def)],
+ annmodel.s_None)
+ self.exception_type = getinstancerepr(
+ self.translator.rtyper, exception_def).lowleveltype
mixlevelannotator.finish()
@@ -550,14 +557,25 @@
# self.resume_points and we don't want a constant "zero" in
# there.
v_state = op.args[0]
- v_returns = op.args[1]
- erased_returns_type = storage_type(v_returns.concretetype)
- resume_after_ptr = self.resume_afters[erased_returns_type]
+ v_returning = op.args[1]
+ v_raising = op.args[2]
llops = LowLevelOpList()
- if erased_returns_type != v_returns.concretetype:
- v_returns = gen_cast(llops, erased_returns_type, v_returns)
- llops.genop('direct_call', [resume_after_ptr, v_state, v_returns],
+
+ if v_raising.concretetype == lltype.Void:
+ erased_type = storage_type(v_returning.concretetype)
+ resume_after_ptr = self.resume_afters[erased_type]
+ v_param = v_returning
+ else:
+ assert v_returning.concretetype == lltype.Void
+ erased_type = self.exception_type
+ resume_after_ptr = self.resume_after_raising_ptr
+ v_param = v_raising
+
+ if erased_type != v_param.concretetype:
+ v_param = gen_cast(llops, erased_type, v_param)
+ llops.genop('direct_call', [resume_after_ptr, v_state, v_param],
resulttype=lltype.Void)
+
del block.operations[-1]
block.operations.extend(llops)
More information about the Pypy-commit
mailing list