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

pedronis at codespeak.net pedronis at codespeak.net
Fri Oct 6 14:14:48 CEST 2006


Author: pedronis
Date: Fri Oct  6 14:14:40 2006
New Revision: 32952

Modified:
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
   pypy/dist/pypy/jit/timeshifter/rtyper.py
   pypy/dist/pypy/jit/timeshifter/test/test_promotion.py
   pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/dist/pypy/jit/timeshifter/transform.py
Log:
(arre, arigo, pedronis)

new slightly more complicated test we're fighting with since tuesday.

Some progress to get it at least thorugh the first compilation-time phase.

When a call cannot produce any return (compilation interrupted case) it should still
let the parent callers possibly exhaust their dispatch queues.



Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Fri Oct  6 14:14:40 2006
@@ -316,8 +316,7 @@
     return jitstate_chain
     # XXX obscurity++ above
 
-def dispatch_next(oldjitstate):
-    dispatchqueue = oldjitstate.frame.dispatchqueue
+def dispatch_next(oldjitstate, dispatchqueue):
     if dispatchqueue.split_chain is not None:
         jitstate = dispatchqueue.split_chain
         dispatchqueue.split_chain = jitstate.next
@@ -330,6 +329,12 @@
 def getresumepoint(jitstate):
     return jitstate.resumepoint
 
+def pickjitstate(oldjitstate, newjitstate):
+    if newjitstate is not None:
+        return newjitstate
+    else:
+        return oldjitstate
+
 def save_locals(jitstate, *redboxes):
     redboxes = list(redboxes)
     assert None not in redboxes
@@ -782,10 +787,19 @@
         self.exc_value_box = self.exc_value_box.replace(memo)
 
 
-def enter_graph(jitstate, DispatchQueueClass):
-    dispatchqueue = DispatchQueueClass()
-    enter_frame(jitstate, dispatchqueue)
-enter_graph._annspecialcase_ = 'specialize:arg(1)'
+def ensure_queue(jitstate, DispatchQueueClass):
+    return DispatchQueueClass()
+ensure_queue._annspecialcase_ = 'specialize:arg(1)'
+
+def portal_ensure_queue(jitstate, DispatchQueueClass):
+    resuming = jitstate.resuming
+    if resuming is None:
+        return DispatchQueueClass()
+    else:
+        dispatchqueue = jitstate.frame.dispatchqueue
+        assert isinstance(dispatchqueue, DispatchQueueClass)
+        return dispatchqueue
+portal_ensure_queue._annspecialcase_ = 'specialize:arg(1)'
 
 def enter_frame(jitstate, dispatchqueue):
     jitstate.frame = VirtualFrame(jitstate.frame, dispatchqueue)
@@ -806,12 +820,7 @@
                 parent_mergesleft = MC_CALL_NOT_TAKEN
         dispatchqueue.mergecounter = parent_mergesleft
 
-
-class CompilationInterrupted(Exception):
-    pass
-
-def merge_returning_jitstates(jitstate):
-    dispatchqueue = jitstate.frame.dispatchqueue
+def merge_returning_jitstates(jitstate, dispatchqueue):
     return_chain = dispatchqueue.return_chain
     resuming = jitstate.resuming
     return_cache = {}
@@ -824,34 +833,35 @@
         if res is False:    # not finished
             jitstate.next = still_pending
             still_pending = jitstate
-    if still_pending is None:
-        assert resuming is None
-        raise CompilationInterrupted
     most_general_jitstate = still_pending
-    still_pending = still_pending.next
-    while still_pending is not None:
-        jitstate = still_pending
+    # if there are more than one jitstate still left, merge them forcefully
+    if still_pending is not None:
         still_pending = still_pending.next
-        res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
-                                          return_marker)
-        assert res is True   # finished
+        while still_pending is not None:
+            jitstate = still_pending
+            still_pending = still_pending.next
+            res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
+                                              return_marker)
+            assert res is True   # finished
 
     if resuming is not None:
         resuming.leave_call(dispatchqueue)
         
     return most_general_jitstate
 
-def leave_graph_red(jitstate):
-    jitstate = merge_returning_jitstates(jitstate)
-    myframe = jitstate.frame
-    leave_frame(jitstate)
-    jitstate.returnbox = myframe.local_boxes[0]
-    # ^^^ fetched by a 'fetch_return' operation
+def leave_graph_red(jitstate, dispatchqueue):
+    jitstate = merge_returning_jitstates(jitstate, dispatchqueue)
+    if jitstate is not None:
+        myframe = jitstate.frame
+        leave_frame(jitstate)
+        jitstate.returnbox = myframe.local_boxes[0]
+        # ^^^ fetched by a 'fetch_return' operation
     return jitstate
 
-def leave_graph_gray(jitstate):
-    jitstate = merge_returning_jitstates(jitstate)
-    leave_frame(jitstate)
+def leave_graph_gray(jitstate, dispatchqueue):
+    jitstate = merge_returning_jitstates(jitstate, dispatchqueue)
+    if jitstate is not None:
+        leave_frame(jitstate)
     return jitstate
 
 def leave_frame(jitstate):
@@ -871,18 +881,12 @@
         jitstate.promotion_path = node
 
 
-def leave_graph_yellow(jitstate):
-    mydispatchqueue = jitstate.frame.dispatchqueue
-    return_chain = mydispatchqueue.return_chain
+def leave_graph_yellow(jitstate, mydispatchqueue):
     resuming = jitstate.resuming
-    if return_chain is None:
-        assert resuming is None
-        raise CompilationInterrupted
     if resuming is not None:
         resuming.leave_call(mydispatchqueue)
+    return_chain = mydispatchqueue.return_chain
     jitstate = return_chain
-    if resuming is not None:
-        resuming.leave_call(mydispatchqueue)
     while jitstate is not None:
         leave_frame(jitstate)
         jitstate = jitstate.next

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Fri Oct  6 14:14:40 2006
@@ -1,5 +1,7 @@
 import types
 from pypy.objspace.flow import model as flowmodel
+from pypy.translator.unsimplify import varoftype
+from pypy.translator.backendopt.ssa import SSA_to_SSI
 from pypy.annotation import model as annmodel
 from pypy.annotation.pairtype import pair, pairtype
 from pypy.rpython import annlowlevel
@@ -69,6 +71,8 @@
          self.r_ConstOrVar)    = self.s_r_instanceof(cgmodel.GenVarOrConst)
         (self.s_Block,
          self.r_Block)         = self.s_r_instanceof(cgmodel.CodeGenBlock)
+        (self.s_Queue,
+         self.r_Queue)       = self.s_r_instanceof(rtimeshift.BaseDispatchQueue)
 
         self.etrafo = hannotator.exceptiontransformer
         self.cexcdata = self.etrafo.cexcdata
@@ -140,6 +144,8 @@
             jitstate.curbuilder.finish_and_return(graphsigtoken, gv_ret)
         self.ll_finish_jitstate = ll_finish_jitstate
 
+        self.v_queue = varoftype(self.r_Queue.lowleveltype, 'queue')
+
     def specialize(self, view=False):
         """
         Driver for running the timeshifter.
@@ -177,6 +183,7 @@
         # "normalize" the graphs by putting an explicit v_jitstate variable
         # everywhere
         self.insert_v_jitstate_everywhere(graph)
+        SSA_to_SSI(graph, annotator=self.annotator)
         # the graph is now timeshifted, so it is *itself* no longer
         # exception-transformed...
         del graph.exceptiontransformed
@@ -309,7 +316,6 @@
         return result
 
     def insert_v_jitstate_everywhere(self, graph):
-        from pypy.translator.unsimplify import varoftype
         for block in graph.iterblocks():
             v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate')
             if block is graph.returnblock:
@@ -567,40 +573,56 @@
 
     # special operations inserted by the HintGraphTransformer
 
-    def translate_op_enter_graph(self, hop):
+
+    def translate_op_ensure_queue(self, hop, prefix=''):
         mpfamily = hop.args_v[0].value
         subclass = self.get_dispatch_subclass(mpfamily)
         s_subclass = self.rtyper.annotator.bookkeeper.immutablevalue(subclass)
         c_subclass = inputconst(lltype.Void, subclass)
         v_jitstate = hop.llops.getjitstate()
-        hop.llops.genmixlevelhelpercall(rtimeshift.enter_graph,
-                                        [self.s_JITState, s_subclass],
-                                        [v_jitstate     , c_subclass],
+        ensure_queue = getattr(rtimeshift, prefix+'ensure_queue')
+        v_queue =  hop.llops.genmixlevelhelpercall(ensure_queue,
+                             [self.s_JITState, s_subclass],
+                             [v_jitstate     , c_subclass],
+                             self.s_Queue)
+        hop.llops.append(flowmodel.SpaceOperation('same_as', [v_queue],
+                                                  self.v_queue))
+
+
+    def translate_op_portal_ensure_queue(self, hop):
+        return self.translate_op_ensure_queue(hop, prefix='portal_')
+
+        
+    def translate_op_enter_frame(self, hop):
+        v_jitstate = hop.llops.getjitstate()
+        hop.llops.genmixlevelhelpercall(rtimeshift.enter_frame,
+                                        [self.s_JITState, self.s_Queue],
+                                        [v_jitstate     , self.v_queue],
                                         annmodel.s_None)
 
     def translate_op_leave_graph_red(self, hop):
         v_jitstate = hop.llops.getjitstate()
         v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_red,
-                                                  [self.s_JITState],
-                                                  [v_jitstate     ],
-                                                  self.s_JITState)
+                            [self.s_JITState, self.s_Queue],
+                            [v_jitstate     , self.v_queue],
+                            self.s_JITState)
         hop.llops.setjitstate(v_newjs)
 
     def translate_op_leave_graph_gray(self, hop):
         v_jitstate = hop.llops.getjitstate()
         v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_gray,
-                                                  [self.s_JITState],
-                                                  [v_jitstate     ],
-                                                  self.s_JITState)
+                            [self.s_JITState, self.s_Queue],
+                            [v_jitstate     , self.v_queue],
+                            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)
+        v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_yellow,
+                            [self.s_JITState, self.s_Queue],
+                            [v_jitstate     , self.v_queue],
+                            self.s_JITState)
+        hop.llops.setjitstate(v_newjs)
 
     def translate_op_save_locals(self, hop):
         v_jitstate = hop.llops.getjitstate()
@@ -792,11 +814,8 @@
         def call_for_global_resuming(jitstate):
             jitstate.frame.dispatchqueue = DispatchQueueSubclass()
             jitstate.resumepoint = N
-            try:
-                finaljitstate = tsfn(jitstate, *dummy_args)
-            except rtimeshift.CompilationInterrupted:
-                pass
-            else:
+            finaljitstate = tsfn(jitstate, *dummy_args)
+            if finaljitstate is not None:
                 ll_finish_jitstate(finaljitstate, residualSigToken)
 
         return self.translate_op_merge_point(hop,
@@ -812,9 +831,9 @@
     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)
+                            [self.s_JITState, self.s_Queue],
+                            [v_jitstate     , self.v_queue],
+                            self.s_JITState)
         hop.llops.setjitstate(v_newjs)
 
     def translate_op_getresumepoint(self, hop):
@@ -909,7 +928,13 @@
         args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate]
         RESULT = lltype.typeOf(fnptr).TO.RESULT
         v_newjitstate = hop.genop('direct_call', args_v, RESULT)
-        hop.llops.setjitstate(v_newjitstate)
+        v_pickedjs = hop.llops.genmixlevelhelpercall(rtimeshift.pickjitstate,
+                                            [self.s_JITState, self.s_JITState],
+                                            [v_jitstate     , v_newjitstate  ],
+                                            self.s_JITState)
+        hop.llops.setjitstate(v_pickedjs)
+        return hop.genop('ptr_iszero', [v_newjitstate],
+                         resulttype = lltype.Bool)
 
     def translate_op_indirect_red_call(self, hop):
         v_jitstate = hop.llops.getjitstate()
@@ -927,7 +952,13 @@
         RESULT = v_tsfunc.concretetype.TO.RESULT
         args_v.append(hop.inputconst(lltype.Void, graph2ts.values()))
         v_newjitstate = hop.genop('indirect_call', args_v, RESULT)
-        hop.llops.setjitstate(v_newjitstate)
+        v_pickedjs = hop.llops.genmixlevelhelpercall(rtimeshift.pickjitstate,
+                                            [self.s_JITState, self.s_JITState],
+                                            [v_jitstate     , v_newjitstate  ],
+                                            self.s_JITState)
+        hop.llops.setjitstate(v_pickedjs)
+        return hop.genop('ptr_iszero', [v_newjitstate],
+                         resulttype = lltype.Bool)
 
     translate_op_gray_call            = translate_op_red_call
     translate_op_indirect_gray_call   = translate_op_indirect_red_call

Modified: pypy/dist/pypy/jit/timeshifter/test/test_promotion.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_promotion.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_promotion.py	Fri Oct  6 14:14:40 2006
@@ -147,6 +147,43 @@
         assert res == 340
         self.check_insns(int_lt=1, int_mul=0)
 
+    def test_more_promotes(self):
+        py.test.skip("in-progress")
+        S = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed))
+        def ll_two(s, i, m):
+            if i < 4:
+                s.x += i
+                return 10
+            else:
+                s.y = i
+                return s.x + m
+        def ll_three(s, k):
+            k = hint(k, promote=True)
+            if s.x > 6:
+                k *= hint(s.y, promote=True)
+                return k
+            else:
+                return hint(1, concrete=True)
+        def ll_function(n, m):
+            s = lltype.malloc(S)
+            s.x = 0
+            s.y = 0
+            i = 0
+            while i < n:
+                k = ll_two(s, i, m)
+                if m & 1:
+                    k *= 3
+                else:
+                    s.y += 1
+                j = ll_three(s, k)
+                j = hint(j, variable=True)
+                i += j
+            return s.x + s.y * 17
+        ll_function._global_merge_points_ = True
+
+        res = self.timeshift(ll_function, [100, 2], [], policy=P_NOVIRTUAL)
+        assert res == ll_function(100, 2)
+
 
     def test_method_call_nonpromote(self):
         class Base(object):

Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	Fri Oct  6 14:14:40 2006
@@ -175,12 +175,9 @@
                     timeshifted_entrypoint_args += (box,)
 
             top_jitstate = fresh_jitstate(builder)
-            try:
-                top_jitstate = timeshifted_entrypoint(top_jitstate,
+            top_jitstate = timeshifted_entrypoint(top_jitstate,
                                                   *timeshifted_entrypoint_args)
-            except rtimeshift.CompilationInterrupted:
-                pass
-            else:
+            if top_jitstate is not None:
                 finish_jitstate(top_jitstate, sigtoken)
 
             gv_generated = rgenop.gencallableconst(sigtoken, "generated",

Modified: pypy/dist/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/transform.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/transform.py	Fri Oct  6 14:14:40 2006
@@ -54,8 +54,9 @@
         self.split_after_calls()
         self.handle_hints()
         self.insert_merge_points()
-        self.insert_enter_graph()
+        self.insert_enter_frame()
         self.insert_dispatcher()
+        self.insert_ensure_queue()
         self.insert_leave_graph()
 
     def compute_merge_points(self):
@@ -366,9 +367,17 @@
             raise AssertionError(self.graph, self.graphcolor)
         self.genop(block, 'save_return', [])
 
-    def insert_enter_graph(self):
+    def insert_ensure_queue(self):
         entryblock = self.before_start_block()
-        self.genop(entryblock, 'enter_graph', [self.c_mpfamily])
+        if self.mergepointfamily.has_global_mergepoints():
+            prefix = 'portal_'
+        else:
+            prefix = ''
+        self.genop(entryblock, prefix+'ensure_queue', [self.c_mpfamily])
+
+    def insert_enter_frame(self):
+        entryblock = self.before_start_block()
+        self.genop(entryblock, 'enter_frame', [])
 
     def insert_leave_graph(self):
         block = self.before_return_block()
@@ -442,7 +451,9 @@
         if len(targets) == 1:
             [tsgraph] = targets.values()
             c_tsgraph = inputconst(lltype.Void, tsgraph)
-            self.genop(block, '%s_call' % (color,), [c_tsgraph] + args_v)
+            v_finished = self.genop(block, '%s_call' % (color,),
+                                    [c_tsgraph] + args_v,
+                                    resulttype = lltype.Bool)
             # Void result, because the call doesn't return its redbox result,
             # but only has the hidden side-effect of putting it in the jitstate
         else:
@@ -454,7 +465,10 @@
                 v_greenfunc = self.genop(block, 'revealconst', [args_v[0]],
                                   resulttype = originalconcretetype(hs_func))
                 args_v[0] = v_greenfunc
-            self.genop(block, 'indirect_%s_call' % (color,), args_v)
+            v_finished = self.genop(block, 'indirect_%s_call' % (color,),
+                                    args_v,
+                                    resulttype = lltype.Bool)
+        self.go_to_dispatcher_if(block, v_finished)
 
     def handle_red_call(self, block, pos, color='red'):
         varsalive = self.variables_alive(block, pos+1)
@@ -486,19 +500,22 @@
             constantblock.closeblock(Link([], nextblock))
             nonconstantblock.closeblock(Link([], nextblock))
 
+        postconstantblock = self.naive_split_block(constantblock,
+                                                 len(constantblock.operations))
+        blockset[postconstantblock] = False
         self.make_call(constantblock, op, reds, color)
 
         mapping = {}
         for i, var in enumerate(reds):
             c_index = Constant(i, concretetype=lltype.Signed)
-            newvar = self.genop(constantblock, 'restore_local', [c_index],
+            newvar = self.genop(postconstantblock, 'restore_local', [c_index],
                                 result_like = var)
             mapping[var] = newvar
 
         if uses_retval:
             assert not self.hannotator.binding(op.result).is_green()
             var = op.result
-            newvar = self.genop(constantblock, 'fetch_return', [],
+            newvar = self.genop(postconstantblock, 'fetch_return', [],
                                 result_like = var)
             mapping[var] = newvar
 
@@ -515,7 +532,7 @@
 
             oldvars = mapping.keys()
             newvars = [mapping[v] for v in oldvars]
-            constantblock.exits[0].args = newvars
+            postconstantblock.exits[0].args = newvars
             nextblock.inputargs = newvars
 
             mapping2 = dict([(v, copyvar(self.hannotator, v))
@@ -578,17 +595,20 @@
         nextblock.inputargs.insert(0, v_result)
 
         reds, greens = self.sort_by_color(varsalive)
+        postblock = self.naive_split_block(block, len(block.operations))
         self.make_call(block, op, reds, 'yellow')
 
         resumepoint = self.get_resume_point(nextblock)
         c_resumepoint = inputconst(lltype.Signed, resumepoint)
-        self.genop(block, 'collect_split', [c_resumepoint] + greens)
+        self.genop(postblock, 'collect_split', [c_resumepoint] + greens)
         link.args = []
         link.target = self.get_resume_point_link(nextblock).target
 
         # to merge some of the possibly many return jitstates
         self.mergepoint_set[nextblock] = 'local'  
-        
+
+        SSA_to_SSI({block: True,
+                    postblock: False}, self.hannotator)
 
     # __________ hints __________
 



More information about the Pypy-commit mailing list