[pypy-svn] r28155 - in pypy/dist/pypy: rpython translator/stackless translator/stackless/test

mwh at codespeak.net mwh at codespeak.net
Sat Jun 3 13:47:15 CEST 2006


Author: mwh
Date: Sat Jun  3 13:47:02 2006
New Revision: 28155

Modified:
   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:
(pedronis, mwh)
Reenable the first resume_point test.
Most/all of the code from the branch is now on the trunk, but a little
saner.
Some refactorings were necessary for sanity + a couple bugfixes.


Modified: pypy/dist/pypy/rpython/rstack.py
==============================================================================
--- pypy/dist/pypy/rpython/rstack.py	(original)
+++ pypy/dist/pypy/rpython/rstack.py	Sat Jun  3 13:47:02 2006
@@ -86,12 +86,12 @@
         c_label = hop.inputconst(lltype.Void, hop.args_s[1].const)
 
         r =  SimplePointerRepr(lltype.Ptr(STATE_HEADER))
-        state_v = hop.inputarg(r, arg=0)
+        v_state = hop.inputarg(r, arg=0)
         
         args_v = hop.args_v[2:]
 
         hop.exception_is_here()
-        return hop.genop('resume_state_create', [c_label] + args_v,
+        return hop.genop('resume_state_create', [v_state, c_label] + args_v,
                          hop.r_result)
 
 class ResumeStateEntry(ExtRegistryEntry):
@@ -116,7 +116,7 @@
 
     def specialize_call(self, hop, **kwds_i):
         from pypy.rpython.lltypesystem import lltype
-        v_state = hop.args_v[0]
+        v_state = hop.args_v[1]
         
         if 'i_returns' in kwds_i:
             assert len(kwds_i) == 1

Modified: pypy/dist/pypy/translator/stackless/code.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/code.py	(original)
+++ pypy/dist/pypy/translator/stackless/code.py	Sat Jun  3 13:47:02 2006
@@ -181,6 +181,38 @@
 INDEX_CAPTURE = frame.RestartInfo.add_prebuilt(ll_stack_capture,
                                                [EMPTY_STATE])
 
+RESUME_AFTER_STATE = frame.make_state_header_type('resume_after_state',
+                                                  ('c', lltype.Ptr(STATE_HEADER)),)
+
+def resume_after_void(state, retvalue):
+    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_VOID
+        s.c = state
+        add_frame_state(u, s.header)
+        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
+        targetstate.f_back = mystate.f_back
+        global_state.top = targetstate
+        raise UnwindException()
+    else:
+        return 0
+
+resume_after_void.stackless_explicit = True
+INDEX_RESUME_AFTER_VOID = frame.RestartInfo.add_prebuilt(resume_after_void,
+                                                         [RESUME_AFTER_STATE,
+                                                          EMPTY_STATE])
 # ____________________________________________________________
 
 class StacklessData:

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 13:47:02 2006
@@ -25,9 +25,9 @@
         state = rstack.resume_state_create(None, "rp0", one(), one()+one()+one())
         v2 = rstack.resume_state_invoke(int, state)
         return v1*10 + v2
-    transform_stackless_function(example)
-##     res = llinterp_stackless_function(example, assert_unwind=False)
-##     assert res == 24
+##     transform_stackless_function(example)
+    res = llinterp_stackless_function(example, assert_unwind=False)
+    assert res == 24
 
 def test_call():
     def g(x,y):

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 13:47:02 2006
@@ -12,6 +12,7 @@
 from pypy.rpython.rbuiltin import gen_cast
 from pypy.rpython.rtyper import LowLevelOpList
 from pypy.rpython.module import ll_stackless, ll_stack
+from pypy.rpython.objectmodel import ComputedIntSymbolic
 from pypy.translator.backendopt import graphanalyze
 
 from pypy.translator.stackless.frame import SAVED_REFERENCE, STORAGE_TYPES
@@ -54,6 +55,15 @@
 #         abort()
 #     return retval + x + 1
 
+class SymbolicRestartNumber(ComputedIntSymbolic):
+    def __init__(self, value=None):
+        ComputedIntSymbolic.__init__(self, self._getvalue)
+        self.value = value
+
+    def _getvalue(self):
+        assert self.value is not None
+        return self.value
+
 class ResumePoint:
     def __init__(self, var_result, args, links_to_resumption,
                  frame_state_type, fieldnames):
@@ -223,6 +233,11 @@
         self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc(
             code.yield_current_frame_to_caller, [], s_StatePtr)
 
+        self.resume_after_void_ptr = mixlevelannotator.constfunc(
+            code.resume_after_void, [annmodel.SomePtr(lltype.Ptr(STATE_HEADER)),
+                                     annmodel.s_None],
+                                    annmodel.SomeInteger())
+
         mixlevelannotator.finish()
 
         s_global_state = bk.immutablevalue(code.global_state)
@@ -244,7 +259,8 @@
 
         self.is_finished = False
 
-        self.explicit_resume_points = {}
+        #self.explicit_resume_points = {}
+        self.symbolic_restart_numbers = {}
 
         # register the prebuilt restartinfos
         for restartinfo in frame.RestartInfo.prebuilt:
@@ -404,6 +420,96 @@
         new_start_block.isstartblock = True
         graph.startblock = new_start_block
 
+    def handle_resume_point(self, block, i):
+        # in some circumstances we might be able to reuse
+        # an already inserted resume point
+        op = block.operations[i]
+        if i == len(block.operations) - 1:
+            link = block.exits[0]
+        else:
+            link = support.split_block_with_keepalive(block, i+1)
+        parms = op.args[1:]
+        if not isinstance(parms[0], model.Variable):
+            assert parms[0].value is None
+            parms[0] = None
+        args = vars_to_save(block)
+        for a in args:
+            if a not in parms:
+                raise Exception, "not covered needed value at resume_point"
+            if parms[0] is not None: # returns= case
+                res = parms[0]
+                args = [arg for arg in args if arg is not res]
+            else:
+                args = args
+                res = op.result
+
+        (frame_type,
+         fieldnames) = self.frametyper.frame_type_for_vars(parms[1:])
+
+        self.resume_points.append(
+            ResumePoint(res, parms[1:], tuple(block.exits),
+                        frame_type, fieldnames))
+
+        label = op.args[0].value
+
+        restart_number = len(self.masterarray1) + len(self.resume_points)-1
+
+##                     assert label not in self.explicit_resume_points
+##                     self.explicit_resume_points[label] = {
+##                         'restype': res.concretetype,
+##                     }
+
+        if label in self.symbolic_restart_numbers:
+            symb = self.symbolic_restart_numbers[label]
+            assert symb.value is None
+            symb.value = restart_number
+        else:
+            symb = SymbolicRestartNumber(restart_number)
+            self.symbolic_restart_numbers[label] = symb
+
+        return link.target, i
+
+    def handle_resume_state_create(self, block, i):
+        op = block.operations[i]
+        llops = LowLevelOpList()
+        # XXX we do not look at op.args[0], the prevstate, at all
+        label = op.args[1].value
+        parms = op.args[2:]
+        FRAME, fieldnames = self.frametyper.frame_type_for_vars(parms)
+        c_FRAME = model.Constant(FRAME, lltype.Void)
+        v_state = llops.genop('malloc', [c_FRAME],
+                              resulttype = lltype.Ptr(FRAME))
+        llops.extend(self.generate_saveops(v_state, parms, fieldnames))
+        v_state = llops.genop('cast_pointer', [v_state],
+                              resulttype = lltype.Ptr(frame.STATE_HEADER))
+
+        if label in self.symbolic_restart_numbers:
+            symb = self.symbolic_restart_numbers[label]
+        else:
+            symb = SymbolicRestartNumber()
+            self.symbolic_restart_numbers[label] = symb
+
+        llops.genop('setfield', [v_state,
+                                 model.Constant('f_restart', lltype.Void),
+                                 model.Constant(symb, lltype.Signed)])
+        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
+        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
+        else:
+            raise NotImplementedError
+        return newop
+
     def transform_block(self, block):
         i = 0
 
@@ -424,51 +530,18 @@
                 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
+                        
             if (op.opname in ('direct_call', 'indirect_call')
                 or self.analyzer.operation_is_true(op)):
                 if op.opname == 'resume_point':
-                    # in some circumstances we might be able to reuse
-                    # an already inserted resume point
-                    if i == len(block.operations) - 1:
-                        link = block.exits[0]
-                    else:
-                        link = support.split_block_with_keepalive(block, i+1)
-                    parms = op.args[1:]
-                    if not isinstance(parms[0], model.Variable):
-                        assert parms[0].value is None
-                        parms[0] = None
-                    args = vars_to_save(block)
-                    for a in args:
-                        if a not in parms:
-                            raise Exception, "not covered needed value at resume_point"
-                        if parms[0] is not None: # returns= case
-                            res = parms[0]
-                            args = [arg for arg in args if arg is not res]
-                        else:
-                            args = args
-                            res = op.result
-
-                    (frame_type,
-                     fieldnames) = self.frametyper.frame_type_for_vars(args)
-
-                    self.resume_points.append(
-                        ResumePoint(res, args, tuple(block.exits),
-                                    frame_type, fieldnames))
-
-                    field2parm = {}
-                    for arg, fieldname in zip(args, fieldnames):
-                        p = parms.index(arg)
-                        field2parm[fieldname] = p-1 # ignore parm[0]
-                        
-                    label = op.args[0].value
-                    self.explicit_resume_points[label] = {
-                        'restart': len(self.masterarray1) + len(self.resume_points)-1,
-                        'frame_type': frame_type,
-                        'restype': res.concretetype,
-                        'field2parm': field2parm,
-                    }
-                    block = link.target
-                    i = 0
+                    block, i = self.handle_resume_point(block, i)
                     continue
                     
                 # trap calls to stackless-related suggested primitives
@@ -477,7 +550,7 @@
                     if func in self.suggested_primitives:
                         op = replace_with_call(self.suggested_primitives[func])
                         stackless_op = True
-                        
+
                 if not stackless_op and not self.analyzer.analyze(op):
                     i += 1
                     continue



More information about the Pypy-commit mailing list