[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