[pypy-svn] r23427 - in pypy/dist/pypy/jit: . test

ac at codespeak.net ac at codespeak.net
Thu Feb 16 21:05:01 CET 2006


Author: ac
Date: Thu Feb 16 21:05:00 2006
New Revision: 23427

Modified:
   pypy/dist/pypy/jit/hinttimeshift.py
   pypy/dist/pypy/jit/rtimeshift.py
   pypy/dist/pypy/jit/test/test_hint_timeshift.py
Log:
(pedronis, arre)
- Initial work thowards supporting spliting on a red exitswitch.
Inserted special dispatch and return blocks. The latter collects all returning
links and their return value. The former closes the returnlinks into a final
block and merges their values to fill a final proper jitstate.



Modified: pypy/dist/pypy/jit/hinttimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/hinttimeshift.py	(original)
+++ pypy/dist/pypy/jit/hinttimeshift.py	Thu Feb 16 21:05:00 2006
@@ -2,7 +2,7 @@
 from pypy.objspace.flow import model as flowmodel
 from pypy.annotation import model as annmodel
 from pypy.annotation import listdef, dictdef
-from pypy.jit.rtimeshift import STATE_PTR, REDBOX_PTR, VARLIST
+from pypy.jit.rtimeshift import STATE, STATE_PTR, REDBOX_PTR, VARLIST
 from pypy.jit.rtimeshift import make_types_const
 from pypy.rpython import rmodel, rtuple, rlist, rdict, rgenop
 from pypy.jit import rtimeshift
@@ -18,6 +18,55 @@
         self.rtyper = rtyper
         self.hrtyper = HintRTyper(hannotator, self)
 
+
+        # XXX refactor this more nicely
+        s_return_info = annmodel.SomeTuple([annmodel.SomePtr(rgenop.LINK),
+                                           annmodel.SomePtr(REDBOX_PTR)])
+
+        returrn_queue_def = listdef.ListDef(None,
+                                            s_return_info)
+        returrn_queue_def.resize()
+        returrn_queue_def.mutate()
+        
+        s_return_queue = annmodel.SomeList(returrn_queue_def)
+        
+        r_return_queue = rtyper.getrepr(s_return_queue)
+        r_return_queue.setup()
+        RETURN_QUEUE = r_return_queue.lowleveltype
+
+        def ll_get_return_queue(questate):
+            pass
+        def _ll_get_return_queue(questate):
+            return questate.return_queue
+
+        llgetq = ll_get_return_queue
+
+        def ll_get_return_queue_annotation(queustate_s):
+            return s_return_queue
+
+        llgetq.compute_result_annotation = ll_get_return_queue_annotation
+
+        def ll_get_return_queue_specialize(hop):
+            return hop.gendirectcall(_ll_get_return_queue, hop.args_v[0])
+
+        llgetq.specialize = ll_get_return_queue_specialize
+
+        def ll_newstate():
+            questate = lltype.malloc(QUESTATE)
+            questate.return_queue = RETURN_QUEUE.TO.ll_newlist(0)
+            return questate
+        
+        QUESTATE = lltype.GcStruct("quejistate",
+                                   ('basestate', STATE),
+                                   ("return_queue", RETURN_QUEUE),
+                                   adtmeths = {
+            'll_get_return_queue': ll_get_return_queue,
+            'll_newstate': ll_newstate,
+            'll_basestate': lambda questate: questate.basestate})
+
+        self.s_return_queue = s_return_queue # for the test
+        self.QUESTATE_PTR = lltype.Ptr(QUESTATE)
+                
     def timeshift(self):
         for graph in self.hannotator.translator.graphs:
             self.timeshift_graph(graph)
@@ -31,7 +80,11 @@
         originalblocks = list(graph.iterblocks())
         returnblock = graph.returnblock
         # we need to get the jitstate to the before block of the return block
-        before_returnblock = self.insert_before_block(returnblock, entering_links[returnblock])
+        self.dispatchblock = flowmodel.Block([])
+        self.pre_process_block(self.dispatchblock)
+        before_returnblock = self.insert_before_block(returnblock,
+                                 entering_links[returnblock],
+                                 closeblock=False)
         self.pre_process_block(before_returnblock)
         for block in originalblocks:
             self.pre_process_block(block)            
@@ -49,8 +102,12 @@
         self.hrtyper.setup_block_entry(before_returnblock)
         self.hrtyper.insert_link_conversions(before_returnblock)
         # add booking logic
-        self.insert_bookkeeping_enter(returnblock, before_returnblock,
-                                      len(entering_links[returnblock]))
+        self.insert_return_bookkeeping(before_returnblock)
+
+        # fix its concretetypes
+        self.hrtyper.setup_block_entry(self.dispatchblock)
+        self.insert_dispatch_logic(returnblock)
+
 
     def pre_process_block(self, block):
         # pass 'jitstate' as an extra argument around the whole graph
@@ -61,14 +118,13 @@
             for link in block.exits:
                 if link.target.operations != ():
                     link.args.insert(0, v_jitstate)
-                elif len(link.args) == 1: # pass the jitstate instead of the return value
-                                          # to the return block!
+                elif len(link.args) == 1:
                     link.args[0] = v_jitstate
-                    v_returnjitstate = flowmodel.Variable('jitstate')                    
+                    v_returnjitstate = flowmodel.Variable('jitstate')
                     self.hannotator.bindings[v_returnjitstate] = s_JITState
                     link.target.inputargs = [v_returnjitstate]
                     
-    def insert_before_block(self, block, entering_links):
+    def insert_before_block(self, block, entering_links, closeblock=True):
         newinputargs = []
         for var in block.inputargs:
             newvar = flowmodel.Variable(var)
@@ -83,9 +139,10 @@
         else:
             for link in entering_links:
                 link.settarget(newblock)
-            
-        bridge = flowmodel.Link(newinputargs, block)
-        newblock.closeblock(bridge)
+
+        if closeblock:
+            bridge = flowmodel.Link(newinputargs, block)
+            newblock.closeblock(bridge)
         return newblock
                                                          
     def insert_bookkeeping_enter(self, block, before_block, nentrylinks):
@@ -285,6 +342,66 @@
 
         newblock.operations[:] = llops
 
+    def insert_return_bookkeeping(self, before_returnblock):
+        v_jitstate, v_value = before_returnblock.inputargs
+        r_value = self.hrtyper.bindingrepr(v_value)
+        llops = HintLowLevelOpList(self, None)
+        if isinstance(r_value, GreenRepr):
+            v_value = llops.gendirectcall(rtimeshift.REDBOX.ll_make_from_const,
+                                          v_value)
+
+        v_quejitstate = llops.genop('cast_pointer', [v_jitstate],
+                                    resulttype=self.QUESTATE_PTR)
+            
+        llops.genmixlevelhelpercall(rtimeshift.schedule_return,
+                                    [annmodel.SomePtr(self.QUESTATE_PTR),
+                                     annmodel.SomePtr(REDBOX_PTR)],
+                                    [v_quejitstate, v_value])
+
+        before_returnblock.operations[:] = llops
+        bridge = flowmodel.Link([v_jitstate], self.dispatchblock)
+        before_returnblock.closeblock(bridge)
+
+    def insert_dispatch_logic(self, returnblock):
+        dispatchblock = self.dispatchblock
+        [v_jitstate] = dispatchblock.inputargs
+        llops = HintLowLevelOpList(self, None)
+        s_box_list = annmodel.SomeList(listdef.ListDef(None,
+                                                       annmodel.SomePtr(REDBOX_PTR)))
+        getrepr = self.rtyper.getrepr
+
+        r_box_list = getrepr(s_box_list)
+        r_box_list.setup()        
+        v_boxes = rlist.newlist(llops, r_box_list, [])
+
+        v_quejitstate = llops.genop('cast_pointer', [v_jitstate],
+                                    resulttype=self.QUESTATE_PTR)
+        
+        v_next = llops.genmixlevelhelpercall(rtimeshift.dispatch_next,
+                     [annmodel.SomePtr(self.QUESTATE_PTR), s_box_list],
+                     [v_quejitstate, v_boxes])
+
+        dispatchblock.operations[:] = llops
+
+        dispatch_to = []
+        finishedlink = flowmodel.Link([v_jitstate], returnblock)
+        dispatch_to.append(('default', finishedlink))
+
+        if len(dispatch_to) == 1:
+            dispatchblock.closeblock(finishedlink)
+        else:        
+            dispatchblock.exitswitch = v_next
+            exitlinks = []
+            for case, link in dispatch_to:
+                link.exitcase = link.llexitcase = case
+                exitlinks.append(link)
+            dispatchblock.closeblock(*exitlinks)
+
+        v_returnjitstate = flowmodel.Variable('jitstate')
+        returnblock.inputargs = [v_returnjitstate]
+        v_returnjitstate.concretetype = STATE_PTR
+
+        
     def timeshift_block(self, block):
         self.hrtyper.specialize_block(block)
 

Modified: pypy/dist/pypy/jit/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/rtimeshift.py	Thu Feb 16 21:05:00 2006
@@ -56,7 +56,6 @@
                                     ('basebox', REDBOX),
                                     ("value", lltype.Signed))
 REDBOX_FOR_SIGNED_PTR = lltype.Ptr(REDBOX_FOR_SIGNED)
-
 STATE = lltype.GcStruct("jitstate", ("curblock", rgenop.BLOCK),
                                     ("curoutgoinglink", rgenop.LINK),
                                     ("curvalue", REDBOX_PTR))
@@ -227,8 +226,47 @@
     jitstate.curoutgoinglink = rgenop.closeblock1(jitstate.curblock)
     return jitstate
 
-def ll_setup_jitstate():
-    jitstate = lltype.malloc(STATE)
+def schedule_return(jitstate, redbox):
+    return_queue = jitstate.ll_get_return_queue()
+    curoutgoinglink = jitstate.ll_basestate().curoutgoinglink
+    return_queue.append((curoutgoinglink, redbox))
+
+novars = lltype.malloc(VARLIST.TO, 0)
+
+def dispatch_next(jitstate, outredboxes):
+    return_queue = jitstate.ll_get_return_queue()
+    basestate = jitstate.ll_basestate()
+    first_redbox = return_queue[0][1]
+    finalblock = rgenop.newblock()
+    basestate.curblock = finalblock
+    if not first_redbox.isvar:
+        for link, redbox in return_queue:
+            if (redbox.isvar or
+                redbox.ll_getvalue(lltype.Signed) !=
+                first_redbox.ll_getvalue(lltype.Signed)):
+                break
+        else:
+            for link, _ in return_queue:
+                rgenop.closelink(link, novars, finalblock)
+            finallink = rgenop.closeblock1(finalblock)
+            basestate.curoutgoinglink = finallink
+            basestate.curvalue = first_redbox
+            return -1
+
+    finalvar = rgenop.geninputarg(finalblock,
+                                  rgenop.constTYPE(lltype.Signed))
+    for link, redbox in return_queue:
+        gvar = ll_gvar_from_redbox(jitstate, redbox, lltype.Signed)
+        rgenop.closelink(link, [gvar], finalblock)
+    finallink = rgenop.closeblock1(finalblock)
+    basestate.curoutgoinglink = finallink
+    basestate.curvalue = REDBOX.ll_make_for_gvar(finalvar)
+    return -1
+
+
+def ll_setup_jitstate(EXT_STATE_PTR):
+    jitstate = EXT_STATE_PTR.TO.ll_newstate()
+    jitstate = lltype.cast_pointer(STATE_PTR, jitstate)
     jitstate.curblock = rgenop.newblock()
     return jitstate
 
@@ -236,8 +274,7 @@
     jitstate.curoutgoinglink = rgenop.closeblock1(jitstate.curblock)
 
 def ll_close_jitstate(final_jitstate, return_gvar):
-    link = rgenop.closeblock1(final_jitstate.curblock)
-    rgenop.closereturnlink(link, return_gvar)
+    rgenop.closereturnlink(final_jitstate.curoutgoinglink, return_gvar)
 
 def ll_input_redbox(jitstate, TYPE):
     genvar = rgenop.geninputarg(jitstate.curblock,

Modified: pypy/dist/pypy/jit/test/test_hint_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/test/test_hint_timeshift.py	(original)
+++ pypy/dist/pypy/jit/test/test_hint_timeshift.py	Thu Feb 16 21:05:00 2006
@@ -46,7 +46,7 @@
         t.view()
     # run the time-shifted graph-producing graphs
     graph1 = ha.translator.graphs[0]
-    jitstate = rtimeshift.ll_setup_jitstate()
+    jitstate = rtimeshift.ll_setup_jitstate(htshift.QUESTATE_PTR)
     graph1args = [jitstate]
     residual_graph_args = []
     assert len(graph1.getargs()) == 1 + len(values)
@@ -80,6 +80,35 @@
                               viewbefore = conftest.option.view)
     return insns, res
 
+def test_ll_get_return_queue():
+    t = TranslationContext()
+    a = t.buildannotator()
+    rtyper = t.buildrtyper()
+    rtyper.specialize() # XXX
+
+    htshift = HintTimeshift(None, rtyper)
+
+    questate = htshift.QUESTATE_PTR.TO.ll_newstate()
+
+    def llf(questate):
+        return questate.ll_get_return_queue()
+
+    from pypy.rpython import annlowlevel
+
+    graph = annlowlevel.annotate_mixlevel_helper(rtyper, llf, [
+        annmodel.SomePtr(htshift.QUESTATE_PTR)])
+
+    s = a.binding(graph.getreturnvar())
+
+    assert s == htshift.s_return_queue
+
+    rtyper.specialize_more_blocks()
+
+    llinterp = LLInterpreter(rtyper)
+    rq = llinterp.eval_graph(graph, [questate])
+    assert lltype.typeOf(rq) == rtyper.getrepr(s).lowleveltype
+
+
 def test_simple_fixed():
     def ll_function(x, y):
         return hint(x + y, concrete=True)
@@ -131,3 +160,15 @@
     insns, res = timeshift(ll_function, [7, 2], [0, 1])
     assert res == 14
     assert insns == {}
+
+def test_loop_merging():
+    py.test.skip('Work in progress')
+    def ll_function(x, y):
+        tot = 0
+        while x:
+            tot += y
+            x -= 1
+        return tot
+    insns, res = timeshift(ll_function, [7, 2], [])
+    assert res == 14
+    # assert insns == {}



More information about the Pypy-commit mailing list