[pypy-svn] r32508 - pypy/branch/timeshift-refactoring/pypy/jit/timeshifter

arigo at codespeak.net arigo at codespeak.net
Tue Sep 19 19:03:27 CEST 2006


Author: arigo
Date: Tue Sep 19 19:03:25 2006
New Revision: 32508

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/rvalue.py
   pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/transform.py
Log:
(arre, arigo)

Reimplemented splits and the dispatcher, in the graph transformer and as
rtyped operations.  There is more work to be done in rtimeshift.



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	Tue Sep 19 19:03:25 2006
@@ -194,8 +194,7 @@
     states_dic[key] = frozen, newblock
 start_new_block._annspecialcase_ = "specialize:arglltype(2)"
 
-def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes):
-    save_locals(jitstate, redboxes)
+def retrieve_jitstate_for_merge(states_dic, jitstate, key):
     if key not in states_dic:
         start_new_block(states_dic, jitstate, key)
         return False   # continue
@@ -229,30 +228,23 @@
     jitstate.enter_block(incoming, memo)
     enter_next_block(jitstate, incoming)
 
-def leave_block_split(jitstate, switchredbox, exitindex,
-                      redboxes_true, redboxes_false):
-    if switchredbox.is_constant():
-        return rvalue.ll_getvalue(switchredbox, lltype.Bool)
-    else:
-        exitgvar = switchredbox.getgenvar(jitstate.curbuilder)
-        later_builder = jitstate.curbuilder.jump_if_false(exitgvar)
-        save_locals(jitstate, redboxes_false)
-        jitstate.split(later_builder, exitindex)
-        save_locals(jitstate, redboxes_true)
-        enter_block(jitstate)
-        return True
+def split(jitstate, switchredbox, resumepoint, *greens_gv):
+    exitgvar = switchredbox.getgenvar(jitstate.curbuilder)
+    later_builder = jitstate.curbuilder.jump_if_false(exitgvar)
+    jitstate.split(later_builder, resumepoint, list(greens_gv))
 
-def dispatch_next(oldjitstate, return_cache):
+def dispatch_next(oldjitstate):
     split_queue = oldjitstate.frame.split_queue
     if split_queue:
         jitstate = split_queue.pop()
         enter_block(jitstate)
         return jitstate
     else:
-        return leave_graph(oldjitstate.frame.return_queue, return_cache)
+        oldjitstate.resumepoint = -1
+        return oldjitstate
 
-def getexitindex(jitstate):
-    return jitstate.exitindex
+def getresumepoint(jitstate):
+    return jitstate.resumepoint
 
 def save_locals(jitstate, *redboxes):
     redboxes = list(redboxes)
@@ -262,6 +254,9 @@
 def getlocalbox(jitstate, i):
     return jitstate.frame.local_boxes[i]
 
+def getgreenbox(jitstate, i, T):
+    return jitstate.greens[i].revealconst(T)
+
 def getreturnbox(jitstate):
     return jitstate.returnbox
 
@@ -380,20 +375,22 @@
     returnbox = None
 
     def __init__(self, builder, frame, exc_type_box, exc_value_box,
-                 exitindex=-1):
+                 resumepoint=-1, newgreens=[]):
         self.curbuilder = builder
         self.frame = frame
         self.exc_type_box = exc_type_box
         self.exc_value_box = exc_value_box
-        self.exitindex = exitindex
+        self.resumepoint = resumepoint
+        self.greens = newgreens
 
-    def split(self, newbuilder, newexitindex):
+    def split(self, newbuilder, newresumepoint, newgreens):
         memo = rvalue.copy_memo()
         later_jitstate = JITState(newbuilder,
                                   self.frame.copy(memo),
                                   self.exc_type_box .copy(memo),
                                   self.exc_value_box.copy(memo),
-                                  newexitindex)
+                                  newresumepoint,
+                                  newgreens)
         self.frame.split_queue.append(later_jitstate)
 
     def enter_block(self, incoming, memo):
@@ -417,17 +414,21 @@
 def enter_graph(jitstate):
     jitstate.frame = VirtualFrame(jitstate.frame, [], [])
 
-def leave_graph(jitstate):
-##    for jitstate in return_queue[:-1]:
-##        res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
-##                                          # XXX strange next argument
-##                                          jitstate.frame.local_boxes)
-##        assert res is True   # finished
-##    frozen, block = return_cache[()]
-##    jitstate = return_queue[-1]
+def leave_graph_red(jitstate):
+    return_queue = jitstate.frame.return_queue
+    return_cache = {}
+    still_pending = []
+    for jitstate in return_queue:
+        res = retrieve_jitstate_for_merge(return_cache, jitstate, ())
+        if res is False:    # not finished
+            still_pending.append(jitstate)
+    for jitstate in still_pending[:-1]:
+        res = retrieve_jitstate_for_merge(return_cache, jitstate, ())
+        assert res is True   # finished
+    jitstate = still_pending[-1]
     myframe = jitstate.frame
     if myframe.local_boxes:             # else it's a green Void return
         jitstate.returnbox = myframe.local_boxes[0]
         # ^^^ fetched by a 'fetch_return' operation
     jitstate.frame = myframe.backframe
-##    jitstate.exitindex = -1
+    return jitstate

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	Tue Sep 19 19:03:25 2006
@@ -563,29 +563,55 @@
                                         [v_jitstate     ],
                                         annmodel.s_None)
 
-    def translate_op_leave_graph(self, hop):
+    def translate_op_leave_graph_red(self, hop):
         v_jitstate = hop.llops.getjitstate()
-        hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph,
-                                        [self.s_JITState],
-                                        [v_jitstate     ],
-                                        annmodel.s_None)
+        v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_red,
+                                                  [self.s_JITState],
+                                                  [v_jitstate     ],
+                                                  self.s_JITState)
+        hop.llops.setjitstate(v_newjs)
 
     def translate_op_save_locals(self, hop):
-        ts = self
         v_jitstate = hop.llops.getjitstate()
-        boxes_s = [ts.s_RedBox] * len(hop.args_v)
-        boxes_v = hop.args_v
+        boxes_r = [self.getredrepr(originalconcretetype(hs))
+                   for hs in hop.args_s]
+        boxes_v = hop.inputargs(*boxes_r)
+        boxes_s = [self.s_RedBox] * len(hop.args_v)
         hop.llops.genmixlevelhelpercall(rtimeshift.save_locals,
-                                        [ts.s_JITState] + boxes_s,
-                                        [v_jitstate   ] + boxes_v,
+                                        [self.s_JITState] + boxes_s,
+                                        [v_jitstate     ] + boxes_v,
+                                        annmodel.s_None)
+
+    def translate_op_enter_block(self, hop):
+        v_jitstate = hop.llops.getjitstate()
+        hop.llops.genmixlevelhelpercall(rtimeshift.enter_block,
+                                        [self.s_JITState],
+                                        [v_jitstate     ],
                                         annmodel.s_None)
 
     def translate_op_restore_local(self, hop):
-        ts = self
         assert isinstance(hop.args_v[0], flowmodel.Constant)
         index = hop.args_v[0].value
+        c_index = hop.inputconst(lltype.Signed, index)
         v_jitstate = hop.llops.getjitstate()
-        return ts.read_out_box(hop.llops, v_jitstate, index)
+        return hop.llops.genmixlevelhelpercall(rtimeshift.getlocalbox,
+                    [self.s_JITState, annmodel.SomeInteger(nonneg=True)],
+                    [v_jitstate     , c_index                          ],
+                    self.s_RedBox)
+
+    def translate_op_restore_green(self, hop):
+        assert isinstance(hop.args_v[0], flowmodel.Constant)
+        index = hop.args_v[0].value
+        c_index = hop.inputconst(lltype.Signed, index)
+        TYPE = originalconcretetype(hop.s_result)
+        s_TYPE = self.rtyper.annotator.bookkeeper.immutablevalue(TYPE)
+        c_TYPE = hop.inputconst(lltype.Void, TYPE)
+        s_result = annmodel.lltype_to_annotation(TYPE)
+        v_jitstate = hop.llops.getjitstate()
+        return hop.llops.genmixlevelhelpercall(rtimeshift.getgreenbox,
+                  [self.s_JITState, annmodel.SomeInteger(nonneg=True), s_TYPE],
+                  [v_jitstate     , c_index                          , c_TYPE],
+                  s_result)
 
     def translate_op_fetch_return(self, hop):
         ts = self
@@ -595,6 +621,77 @@
                                                [v_jitstate   ],
                                                ts.s_RedBox)
 
+    def translate_op_is_constant(self, hop):
+        hs = hop.args_s[0]
+        r_arg = self.getredrepr(originalconcretetype(hs))
+        [v_arg] = hop.inputargs(r_arg)
+        return hop.llops.genmixlevelhelpercall(rvalue.ll_is_constant,
+                                               [self.s_RedBox],
+                                               [v_arg        ],
+                                               annmodel.SomeBool())
+
+    def translate_op_revealconst(self, hop):
+        hs = hop.args_s[0]
+        TYPE = originalconcretetype(hs)
+        r_arg = self.getredrepr(TYPE)
+        [v_arg] = hop.inputargs(r_arg)
+        s_TYPE = self.rtyper.annotator.bookkeeper.immutablevalue(TYPE)
+        c_TYPE = hop.inputconst(lltype.Void, TYPE)
+        s_result = annmodel.lltype_to_annotation(TYPE)
+        return hop.llops.genmixlevelhelpercall(rvalue.ll_getvalue,
+                                               [self.s_RedBox, s_TYPE],
+                                               [v_arg        , c_TYPE],
+                                               s_result)
+
+    def wrap_green_vars(self, llops, vars):
+        v_jitstate = llops.getjitstate()
+        for var in vars:
+            s_var = annmodel.lltype_to_annotation(var.concretetype)
+            yield llops.genmixlevelhelpercall(rvalue.ll_gv_fromvalue,
+                                              [self.s_JITState, s_var],
+                                              [v_jitstate,      var  ],
+                                              self.s_ConstOrVar)
+
+    def translate_op_split(self, hop):
+        r_switch = self.getredrepr(lltype.Bool)
+        GREENS = [v.concretetype for v in hop.args_v[2:]]
+        greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS]
+        vlist = hop.inputargs(r_switch, lltype.Signed, *greens_r)
+
+        v_jitstate = hop.llops.getjitstate()
+        v_switch = vlist[0]
+        c_resumepoint = vlist[1]
+        greens_v = list(self.wrap_green_vars(hop.llops, vlist[2:]))
+
+        s_Int = annmodel.SomeInteger(nonneg=True)
+        args_s = [self.s_JITState, self.s_RedBox, s_Int]
+        args_s += [self.s_ConstOrVar] * len(greens_v)
+        args_v = [v_jitstate, v_switch, c_resumepoint]
+        args_v += greens_v
+        hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v,
+                                        annmodel.s_None)
+
+    def translate_op_save_return(self, hop):
+        v_jitstate = hop.llops.getjitstate()
+        return hop.llops.genmixlevelhelpercall(rtimeshift.save_return,
+                                               [self.s_JITState],
+                                               [v_jitstate     ],
+                                               annmodel.s_None)
+
+    def translate_op_dispatch_next(self, hop):
+        v_jitstate = hop.llops.getjitstate()
+        v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.dispatch_next,
+                                                  [self.s_JITState],
+                                                  [v_jitstate     ],
+                                                  self.s_JITState)
+        hop.llops.setjitstate(v_newjs)
+        return hop.llops.genmixlevelhelpercall(rtimeshift.getresumepoint,
+                                               [self.s_JITState],
+                                               [v_newjs        ],
+                                               annmodel.SomeInteger())
+
+    # handling of the various kinds of calls
+
     def handle_oopspec_call(self, hop):
         # special-cased call, for things like list methods
         from pypy.jit.timeshifter.oop import OopSpecDesc, Index

Modified: pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/branch/timeshift-refactoring/pypy/jit/timeshifter/rvalue.py	Tue Sep 19 19:03:25 2006
@@ -90,10 +90,9 @@
 
 def ll_fromvalue(jitstate, value):
     "Make a constant RedBox from a low-level value."
-    rgenop = jitstate.curbuilder.rgenop
+    gv = ll_gv_fromvalue(jitstate, value)
     T = lltype.typeOf(value)
-    kind = rgenop.kindToken(T)
-    gv = rgenop.genconst(value)
+    kind = jitstate.curbuilder.rgenop.kindToken(T)
     cls = ll_redboxcls(T)
     return cls(kind, gv)
 
@@ -104,10 +103,19 @@
     cls = ll_redboxcls(T)
     return cls(kind, gv)
 
+def ll_gv_fromvalue(jitstate, value):
+    rgenop = jitstate.curbuilder.rgenop
+    gv = rgenop.genconst(value)
+    return gv
+
 def ll_getvalue(box, T):
     "Return the content of a known-to-be-constant RedBox."
     return box.genvar.revealconst(T)
 
+def ll_is_constant(box):
+    "Check if a red box is known to be constant."
+    return box.is_constant()
+
 
 class IntRedBox(RedBox):
     "A red box that contains a constant integer-like value."

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	Tue Sep 19 19:03:25 2006
@@ -1,10 +1,12 @@
-from pypy.objspace.flow     import model as flowmodel
+from pypy.objspace.flow.model import Variable, Constant, Block, Link
+from pypy.objspace.flow.model import SpaceOperation
 from pypy.annotation        import model as annmodel
 from pypy.jit.hintannotator import model as hintmodel
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.rmodel import inputconst
 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
 
 
 class HintGraphTransformer(object):
@@ -12,16 +14,18 @@
     def __init__(self, hannotator, graph):
         self.hannotator = hannotator
         self.graph = graph
-        self.dispatch_to = []
-        self.latestexitindex = -1
+        self.resumepoints = {}
 
     def transform(self):
+        self.insert_save_return()
+        self.insert_splits()
+        self.insert_dispatcher()
         self.insert_enter_graph()
         self.insert_leave_graph()
 
     # __________ helpers __________
 
-    def genop(self, llops, opname, args, result_type=None):
+    def genop(self, block, opname, args, result_type=None):
         # 'result_type' can be a LowLevelType (for green returns)
         # or a template variable whose hintannotation is copied
         if result_type is None:
@@ -30,16 +34,24 @@
             v_res = varoftype(result_type)
             hs = hintmodel.SomeLLAbstractConstant(result_type, {})
             self.hannotator.setbinding(v_res, hs)
-        elif isinstance(result_type, flowmodel.Variable):
+        elif isinstance(result_type, Variable):
             var = result_type
             v_res = copyvar(self.hannotator, var)
         else:
             raise TypeError("result_type=%r" % (result_type,))
 
-        spaceop = flowmodel.SpaceOperation(opname, args, v_res)
-        llops.append(spaceop)
+        spaceop = SpaceOperation(opname, args, v_res)
+        block.operations.append(spaceop)
         return v_res
 
+    def genswitch(self, block, v_exitswitch, false, true):
+        block.exitswitch = v_exitswitch
+        link_f = Link([], false)
+        link_f.exitcase = False
+        link_t = Link([], true)
+        link_t.exitcase = True
+        block.recloseblock(link_f, link_t)
+
     def new_void_var(self, name=None):
         v_res = varoftype(lltype.Void, name)
         self.hannotator.setbinding(v_res, annmodel.s_ImpossibleValue)
@@ -48,24 +60,23 @@
     def new_block_before(self, block):
         newinputargs = [copyvar(self.hannotator, var)
                         for var in block.inputargs]
-        newblock = flowmodel.Block(newinputargs)
-        bridge = flowmodel.Link(newinputargs, block)
+        newblock = Block(newinputargs)
+        bridge = Link(newinputargs, block)
         newblock.closeblock(bridge)
         return newblock
 
-    # __________ transformation steps __________
-
-    def insert_enter_graph(self):
-        entryblock = self.new_block_before(self.graph.startblock)
-        entryblock.isstartblock = True
-        self.graph.startblock.isstartblock = False
-        self.graph.startblock = entryblock
-
-        self.genop(entryblock.operations, 'enter_graph', [])
+    def sort_by_color(self, vars):
+        reds = []
+        greens = []
+        for v in vars:
+            if self.hannotator.binding(v).is_green():
+                greens.append(v)
+            else:
+                reds.append(v)
+        return reds, greens
 
-    def insert_leave_graph(self):
+    def before_return_block(self):
         block = self.graph.returnblock
-        [v_retbox] = block.inputargs
         block.operations = []
         split_block(self.hannotator, block, 0)
         [link] = block.exits
@@ -74,6 +85,112 @@
         link.target.inputargs = [self.new_void_var('dummy')]
         self.graph.returnblock = link.target
         self.graph.returnblock.operations = ()
+        return block
+
+    # __________ transformation steps __________
+
+    def insert_splits(self):
+        hannotator = self.hannotator
+        for block in self.graph.iterblocks():
+            if block.exitswitch is not None:
+                assert isinstance(block.exitswitch, Variable)
+                hs_switch = hannotator.binding(block.exitswitch)
+                if not hs_switch.is_green():
+                    self.insert_split_handling(block)
+
+    def insert_split_handling(self, block):
+        v_redswitch = block.exitswitch
+        link_f, link_t = block.exits
+        if link_f.exitcase:
+            link_f, link_t = link_t, link_f
+        assert link_f.exitcase is False
+        assert link_t.exitcase is True
+
+        constant_block = Block([])
+        nonconstant_block = Block([])
+
+        v_flag = self.genop(block, 'is_constant', [v_redswitch],
+                            result_type = lltype.Bool)
+        self.genswitch(block, v_flag, true  = constant_block,
+                                      false = nonconstant_block)
+
+        v_greenswitch = self.genop(constant_block, 'revealconst',
+                                   [v_redswitch],
+                                   result_type = lltype.Bool)
+        constant_block.exitswitch = v_greenswitch
+        constant_block.closeblock(link_f, link_t)
+
+        reds, greens = self.sort_by_color(link_f.args)
+        self.genop(nonconstant_block, 'save_locals', reds)
+        resumepoint = self.get_resume_point(link_f.target)
+        c_resumepoint = inputconst(lltype.Signed, resumepoint)
+        self.genop(nonconstant_block, 'split',
+                   [v_redswitch, c_resumepoint] + greens)
+
+        reds, greens = self.sort_by_color(link_t.args)
+        self.genop(nonconstant_block, 'save_locals', reds)
+        self.genop(nonconstant_block, 'enter_block', [])
+        nonconstant_block.closeblock(Link(link_t.args, link_t.target))
+
+        SSA_to_SSI({block            : True,    # reachable from outside
+                    constant_block   : False,
+                    nonconstant_block: False}, self.hannotator)
+
+    def get_resume_point(self, block):
+        try:
+            reenter_link = self.resumepoints[block]
+        except KeyError:
+            resumeblock = Block([])
+            redcount   = 0
+            greencount = 0
+            newvars = []
+            for v in block.inputargs:
+                if self.hannotator.binding(v).is_green():
+                    c = inputconst(lltype.Signed, greencount)
+                    v1 = self.genop(resumeblock, 'restore_green', [c],
+                                    result_type = v)
+                    greencount += 1
+                else:
+                    c = inputconst(lltype.Signed, redcount)
+                    v1 = self.genop(resumeblock, 'restore_local', [c],
+                                    result_type = v)
+                    redcount += 1
+                newvars.append(v1)
+
+            resumeblock.closeblock(Link(newvars, block))
+            reenter_link = Link([], resumeblock)
+            N = len(self.resumepoints)
+            reenter_link.exitcase = N
+            self.resumepoints[block] = reenter_link
+        return reenter_link.exitcase
+
+    def insert_dispatcher(self):
+        if self.resumepoints:
+            block = self.before_return_block()
+            v_switchcase = self.genop(block, 'dispatch_next', [],
+                                      result_type = lltype.Signed)
+            block.exitswitch = v_switchcase
+            defaultlink = block.exits[0]
+            defaultlink.exitcase = 'default'
+            links = self.resumepoints.values()
+            links.sort(lambda l, r: cmp(l.exitcase, r.exitcase))
+            links.append(defaultlink)
+            block.recloseblock(*links)
+
+    def insert_save_return(self):
+        block = self.before_return_block()
+        [v_retbox] = block.inputargs
+        self.genop(block, 'save_locals', [v_retbox])
+        self.genop(block, 'save_return', [])
+
+    def insert_enter_graph(self):
+        entryblock = self.new_block_before(self.graph.startblock)
+        entryblock.isstartblock = True
+        self.graph.startblock.isstartblock = False
+        self.graph.startblock = entryblock
+
+        self.genop(entryblock, 'enter_graph', [])
 
-        self.genop(block.operations, 'save_locals', [v_retbox])
-        self.genop(block.operations, 'leave_graph', [])
+    def insert_leave_graph(self):
+        block = self.before_return_block()
+        self.genop(block, 'leave_graph_red', [])



More information about the Pypy-commit mailing list