[pypy-svn] r32543 - in pypy/branch/timeshift-refactoring/pypy/jit/timeshifter: . test

arigo at codespeak.net arigo at codespeak.net
Wed Sep 20 20:18:40 CEST 2006


Author: arigo
Date: Wed Sep 20 20:18:39 2006
New Revision: 32543

Modified:
   pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py
   pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py
   pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py
Log:
(arre, arigo)

Yellow calls!  The first real progress of the week, but it was worth the
effort.

Turned the dispatch_queue's lists of jitstates into chains (linked lists)
to make it easier to give a type to "list of jitstates": it's the same as
"jitstate".  (It's also more efficient, and less readable.)


Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtimeshift.py	Wed Sep 20 20:18:39 2006
@@ -234,10 +234,26 @@
     later_builder = jitstate.curbuilder.jump_if_false(exitgvar)
     jitstate.split(later_builder, resumepoint, list(greens_gv))
 
+def collect_split(jitstate_chain, resumepoint, *greens_gv):
+    greens_gv = list(greens_gv)
+    pending = jitstate_chain
+    while True:
+        jitstate = pending
+        pending = pending.next
+        jitstate.greens.extend(greens_gv)   # item 0 is the return value
+        jitstate.resumepoint = resumepoint
+        if pending is None:
+            break
+    dispatch_queue = jitstate_chain.frame.dispatch_queue
+    jitstate.next = dispatch_queue.split_chain
+    dispatch_queue.split_chain = jitstate_chain.next
+    # XXX obscurity++ above
+
 def dispatch_next(oldjitstate):
-    split_queue = oldjitstate.frame.dispatch_queue.split_queue
-    if split_queue:
-        jitstate = split_queue.pop()
+    dispatch_queue = oldjitstate.frame.dispatch_queue
+    if dispatch_queue.split_chain is not None:
+        jitstate = dispatch_queue.split_chain
+        dispatch_queue.split_chain = jitstate.next
         enter_block(jitstate)
         return jitstate
     else:
@@ -252,6 +268,9 @@
     assert None not in redboxes
     jitstate.frame.local_boxes = redboxes
 
+def save_greens(jitstate, *greens_gv):
+    jitstate.greens = list(greens_gv)
+
 def getlocalbox(jitstate, i):
     return jitstate.frame.local_boxes[i]
 
@@ -274,7 +293,10 @@
     jitstate.exc_value_box = box
 
 def save_return(jitstate):
-    jitstate.frame.dispatch_queue.return_queue.append(jitstate)
+    # add 'jitstate' to the chain of return-jitstates
+    dispatch_queue = jitstate.frame.dispatch_queue
+    jitstate.next = dispatch_queue.return_chain
+    dispatch_queue.return_chain = jitstate
 
 ##def ll_gvar_from_redbox(jitstate, redbox):
 ##    return redbox.getgenvar(jitstate.curbuilder)
@@ -286,8 +308,8 @@
 
 class BaseDispatchQueue(object):
     def __init__(self):
-        self.split_queue = []      # XXX could be turned into a linked list
-        self.return_queue = []     # XXX could be turned into a linked list
+        self.split_chain = None
+        self.return_chain = None
 
 def build_dispatch_subclass(attrnames):
     if len(attrnames) == 0:
@@ -387,6 +409,7 @@
 
 class JITState(object):
     returnbox = None
+    next      = None   # for linked lists
 
     def __init__(self, builder, frame, exc_type_box, exc_value_box,
                  resumepoint=-1, newgreens=[]):
@@ -405,7 +428,10 @@
                                   self.exc_value_box.copy(memo),
                                   newresumepoint,
                                   newgreens)
-        self.frame.dispatch_queue.split_queue.append(later_jitstate)
+        # add the later_jitstate to the chain of pending-for-dispatch_next()
+        dispatch_queue = self.frame.dispatch_queue
+        later_jitstate.next = dispatch_queue.split_chain
+        dispatch_queue.split_chain = later_jitstate
 
     def enter_block(self, incoming, memo):
         self.frame.enter_block(incoming, memo)
@@ -431,17 +457,25 @@
 # XXX is that too many specializations? ^^^
 
 def merge_returning_jitstates(jitstate):
-    return_queue = jitstate.frame.dispatch_queue.return_queue
+    return_chain = jitstate.frame.dispatch_queue.return_chain
     return_cache = {}
-    still_pending = []
-    for jitstate in return_queue:
+    still_pending = None
+    while return_chain is not None:
+        jitstate = return_chain
+        return_chain = return_chain.next
         res = retrieve_jitstate_for_merge(return_cache, jitstate, ())
         if res is False:    # not finished
-            still_pending.append(jitstate)
-    for jitstate in still_pending[:-1]:
+            jitstate.next = still_pending
+            still_pending = jitstate
+    assert still_pending is not None
+    most_general_jitstate = still_pending
+    still_pending = still_pending.next
+    while still_pending is not None:
+        jitstate = still_pending
+        still_pending = still_pending.next
         res = retrieve_jitstate_for_merge(return_cache, jitstate, ())
         assert res is True   # finished
-    return still_pending[-1]
+    return most_general_jitstate
 
 def leave_graph_red(jitstate):
     jitstate = merge_returning_jitstates(jitstate)
@@ -456,3 +490,11 @@
     myframe = jitstate.frame
     jitstate.frame = myframe.backframe
     return jitstate
+
+def leave_graph_yellow(jitstate):
+    return_chain = jitstate.frame.dispatch_queue.return_chain
+    jitstate = return_chain
+    while jitstate is not None:
+        jitstate.frame = jitstate.frame.backframe
+        jitstate = jitstate.next
+    return return_chain    # a jitstate, which is the head of the chain

Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rtyper.py	Wed Sep 20 20:18:39 2006
@@ -577,6 +577,14 @@
                                                   self.s_JITState)
         hop.llops.setjitstate(v_newjs)
 
+    def translate_op_leave_graph_yellow(self, hop):
+        v_jitstate = hop.llops.getjitstate()
+        v_njs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_yellow,
+                                                [self.s_JITState],
+                                                [v_jitstate     ],
+                                                self.s_JITState)
+        hop.llops.setjitstate(v_njs)
+
     def translate_op_save_locals(self, hop):
         v_jitstate = hop.llops.getjitstate()
         boxes_r = [self.getredrepr(originalconcretetype(hs))
@@ -588,6 +596,15 @@
                                         [v_jitstate     ] + boxes_v,
                                         annmodel.s_None)
 
+    def translate_op_save_greens(self, hop):
+        v_jitstate = hop.llops.getjitstate()
+        greens_v = list(self.wrap_green_vars(hop.llops, hop.args_v))
+        greens_s = [self.s_ConstOrVar] * len(greens_v)
+        return hop.llops.genmixlevelhelpercall(rtimeshift.save_greens,
+                                               [self.s_JITState] + greens_s,
+                                               [v_jitstate     ] + greens_v,
+                                               annmodel.s_None)
+
     def translate_op_enter_block(self, hop):
         v_jitstate = hop.llops.getjitstate()
         hop.llops.genmixlevelhelpercall(rtimeshift.enter_block,
@@ -677,6 +694,24 @@
         hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v,
                                         annmodel.s_None)
 
+    def translate_op_collect_split(self, hop):
+        GREENS = [v.concretetype for v in hop.args_v[1:]]
+        greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS]
+        vlist = hop.inputargs(lltype.Signed, *greens_r)
+
+        v_jitstate = hop.llops.getjitstate()
+        c_resumepoint = vlist[0]
+        greens_v = list(self.wrap_green_vars(hop.llops, vlist[1:]))
+
+        s_Int = annmodel.SomeInteger(nonneg=True)
+        args_s = [self.s_JITState, s_Int]
+        args_s += [self.s_ConstOrVar] * len(greens_v)
+        args_v = [v_jitstate, c_resumepoint]
+        args_v += greens_v
+        hop.llops.genmixlevelhelpercall(rtimeshift.collect_split,
+                                        args_s, args_v,
+                                        annmodel.s_None)
+
     def translate_op_merge_point(self, hop):
         mpfamily = hop.args_v[0].value
         attrname = hop.args_v[1].value
@@ -800,6 +835,8 @@
         v_newjitstate = hop.genop('direct_call', args_v, RESULT)
         hop.llops.setjitstate(v_newjitstate)
 
+    translate_op_yellow_call = translate_op_red_call
+
 
 class HintLowLevelOpList(LowLevelOpList):
     """Warning: the HintLowLevelOpList's rtyper is the *original*

Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/test/test_timeshift.py	Wed Sep 20 20:18:39 2006
@@ -900,7 +900,6 @@
         self.check_insns({})
 
     def test_split_on_green_return(self):
-        py.test.skip("in-progress")
         def ll_two(x):
             if x > 0:
                 return 17
@@ -908,7 +907,7 @@
                 return 22
         def ll_function(x):
             n = ll_two(x)
-            return n+1
+            return hint(n+1, variable=True)
         res = self.timeshift(ll_function, [-70], [])
         assert res == 23
         self.check_insns({'int_gt': 1})

Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py	(original)
+++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py	Wed Sep 20 20:18:39 2006
@@ -8,6 +8,7 @@
 from pypy.translator.unsimplify import varoftype, copyvar
 from pypy.translator.unsimplify import split_block, split_block_at_start
 from pypy.translator.backendopt.ssa import SSA_to_SSI
+from pypy.translator.backendopt import support
 
 
 class MergePointFamily(object):
@@ -22,6 +23,7 @@
 
 
 class HintGraphTransformer(object):
+    c_dummy = inputconst(lltype.Void, None)
 
     def __init__(self, hannotator, graph):
         self.hannotator = hannotator
@@ -128,7 +130,7 @@
         split_block(self.hannotator, block, 0)
         [link] = block.exits
         assert len(link.args) == 0
-        link.args = [inputconst(lltype.Void, None)]
+        link.args = [self.c_dummy]
         link.target.inputargs = [self.new_void_var('dummy')]
         self.graph.returnblock = link.target
         self.graph.returnblock.operations = ()
@@ -183,9 +185,9 @@
                     constant_block   : False,
                     nonconstant_block: False}, self.hannotator)
 
-    def get_resume_point(self, block):
+    def get_resume_point_link(self, block):
         try:
-            reenter_link = self.resumepoints[block]
+            return self.resumepoints[block]
         except KeyError:
             resumeblock = Block([])
             redcount   = 0
@@ -209,7 +211,10 @@
             N = len(self.resumepoints)
             reenter_link.exitcase = N
             self.resumepoints[block] = reenter_link
-        return reenter_link.exitcase
+            return reenter_link
+
+    def get_resume_point(self, block):
+        return self.get_resume_point_link(block).exitcase
 
     def insert_merge(self, block):
         reds, greens = self.sort_by_color(block.inputargs)
@@ -223,7 +228,7 @@
                                      result_type = lltype.Bool)
         block.exitswitch = v_finished_flag
         [link_f] = block.exits
-        link_t = Link([inputconst(lltype.Void, None)], self.graph.returnblock)
+        link_t = Link([self.c_dummy], self.graph.returnblock)
         link_f.exitcase = False
         link_t.exitcase = True
         block.recloseblock(link_f, link_t)
@@ -261,6 +266,9 @@
         if originalconcretetype(hs_retbox) is lltype.Void:
             self.leave_graph_opname = 'leave_graph_void'
             self.genop(block, 'save_locals', [])
+        elif hs_retbox.is_green():
+            self.leave_graph_opname = 'leave_graph_yellow'
+            self.genop(block, 'save_greens', [v_retbox])
         else:
             self.leave_graph_opname = 'leave_graph_red'
             self.genop(block, 'save_locals', [v_retbox])
@@ -359,3 +367,32 @@
         op = block.operations[pos]
         assert op.opname == 'direct_call'
         op.opname = 'green_call'
+
+    def handle_yellow_call(self, block, pos):
+        link = support.split_block_with_keepalive(block, pos+1,
+                                                  annotator=self.hannotator)
+        op = block.operations.pop(pos)
+        assert len(block.operations) == pos
+        nextblock = link.target
+        varsalive = link.args
+        try:
+            index = varsalive.index(op.result)
+        except ValueError:
+            XXX-later
+
+        del varsalive[index]
+        v_result = nextblock.inputargs.pop(index)
+        nextblock.inputargs.insert(0, v_result)
+
+        reds, greens = self.sort_by_color(varsalive)
+        self.genop(block, 'save_locals', reds)
+        self.genop(block, 'yellow_call', op.args)  # Void result, like red_call
+
+        resumepoint = self.get_resume_point(nextblock)
+        c_resumepoint = inputconst(lltype.Signed, resumepoint)
+        self.genop(block, 'collect_split', [c_resumepoint] + greens)
+        link.args = []
+        link.target = self.get_resume_point_link(nextblock).target
+
+        self.insert_merge(nextblock)  # to merge some of the possibly many
+                                      # return jitstates



More information about the Pypy-commit mailing list