[pypy-svn] r32528 - in pypy/branch/timeshift-refactoring/pypy/jit: hintannotator timeshifter

arigo at codespeak.net arigo at codespeak.net
Wed Sep 20 16:34:42 CEST 2006


Author: arigo
Date: Wed Sep 20 16:34:40 2006
New Revision: 32528

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

Red and void-returning calls pass again.

We had to compute and cache in the hintannotator, at fix-point, the
green-ness of the OriginFlags objects, because the graphs are now
modified before the hrtyper tries to do the caching.  Should work
nicely, though.



Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py	(original)
+++ pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/bookkeeper.py	Wed Sep 20 16:34:40 2006
@@ -110,6 +110,11 @@
         return origin
 
     def compute_at_fixpoint(self):
+        # compute and cache the green-ness of OriginFlags objects
+        # while we can do so (i.e. before the graphs are modified)
+        for origin in self.originflags.values():
+            if origin.spaceop is not None:
+                origin.greenargs_cached = origin.greenargs()
         # compute and cache the signature of the graphs before they are
         # modified by further code
         ha = self.annotator

Modified: pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py	(original)
+++ pypy/branch/timeshift-refactoring/pypy/jit/hintannotator/model.py	Wed Sep 20 16:34:40 2006
@@ -32,6 +32,7 @@
 
     fixed = False
     read_positions = None
+    greenargs_cached = None
 
     def __init__(self, bookkeeper=None, spaceop=None):
         self.bookkeeper = bookkeeper
@@ -61,6 +62,8 @@
     def greenargs(self, frame=None):
         annotator = self.bookkeeper.annotator
         if frame is None:
+            if self.greenargs_cached is not None:
+                return self.greenargs_cached
             frame = GreenHandlerFrame(annotator)
         if self.spaceop.opname == 'direct_call':     # ah haa
             return frame.greencallresult(self.spaceop)
@@ -229,6 +232,12 @@
     else:
         return hs_v1
 
+def originalconcretetype(hs):
+    if isinstance(hs, annmodel.SomeImpossibleValue):
+        return lltype.Void
+    else:
+        return hs.concretetype
+
 # ____________________________________________________________
 # operations
 

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 16:34:40 2006
@@ -1,5 +1,6 @@
 import operator, weakref
 from pypy.rpython.lltypesystem import lltype, lloperation, llmemory
+from pypy.jit.hintannotator.model import originalconcretetype
 from pypy.jit.timeshifter import rvalue
 from pypy.rpython.unroll import unrolling_iterable
 
@@ -43,7 +44,6 @@
 _opdesc_cache = {}
 
 def make_opdesc(hop):
-    from pypy.jit.timeshifter.rtyper import originalconcretetype
     hrtyper = hop.rtyper
     op_key = (hrtyper.RGenOp, hop.spaceop.opname,
               tuple([originalconcretetype(s_arg) for s_arg in hop.args_s]),
@@ -276,11 +276,11 @@
 def save_return(jitstate):
     jitstate.frame.dispatch_queue.return_queue.append(jitstate)
 
-def ll_gvar_from_redbox(jitstate, redbox):
-    return redbox.getgenvar(jitstate.curbuilder)
+##def ll_gvar_from_redbox(jitstate, redbox):
+##    return redbox.getgenvar(jitstate.curbuilder)
 
-def ll_gvar_from_constant(jitstate, ll_value):
-    return jitstate.curbuilder.rgenop.genconst(ll_value)
+##def ll_gvar_from_constant(jitstate, ll_value):
+##    return jitstate.curbuilder.rgenop.genconst(ll_value)
 
 # ____________________________________________________________
 
@@ -430,7 +430,7 @@
 enter_graph._annspecialcase_ = 'specialize:arg(1)'
 # XXX is that too many specializations? ^^^
 
-def leave_graph_red(jitstate):
+def merge_returning_jitstates(jitstate):
     return_queue = jitstate.frame.dispatch_queue.return_queue
     return_cache = {}
     still_pending = []
@@ -441,10 +441,18 @@
     for jitstate in still_pending[:-1]:
         res = retrieve_jitstate_for_merge(return_cache, jitstate, ())
         assert res is True   # finished
-    jitstate = still_pending[-1]
+    return still_pending[-1]
+
+def leave_graph_red(jitstate):
+    jitstate = merge_returning_jitstates(jitstate)
+    myframe = jitstate.frame
+    jitstate.returnbox = myframe.local_boxes[0]
+    # ^^^ fetched by a 'fetch_return' operation
+    jitstate.frame = myframe.backframe
+    return jitstate
+
+def leave_graph_void(jitstate):
+    jitstate = merge_returning_jitstates(jitstate)
     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
     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	Wed Sep 20 16:34:40 2006
@@ -10,6 +10,7 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.jit.hintannotator import model as hintmodel
 from pypy.jit.hintannotator import container as hintcontainer
+from pypy.jit.hintannotator.model import originalconcretetype
 from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer, oop
 from pypy.jit.timeshifter.transform import HintGraphTransformer
 from pypy.jit.codegen import model as cgmodel
@@ -38,12 +39,6 @@
 # ___________________________________________________________
 
 
-def originalconcretetype(hs):
-    if isinstance(hs, annmodel.SomeImpossibleValue):
-        return lltype.Void
-    else:
-        return hs.concretetype
-
 class HintRTyper(RPythonTyper):
 
     def __init__(self, hannotator, rtyper, RGenOp):
@@ -53,7 +48,7 @@
         self.RGenOp = RGenOp
         self.green_reprs = PRECOMPUTED_GREEN_REPRS.copy()
         self.red_reprs = {}
-        self.color_cache = {}
+        #self.color_cache = {}
 
         self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper)
         self.timeshift_mapping = {}
@@ -216,16 +211,16 @@
             self.red_reprs[lowleveltype] = r
             return r
 
-    def gethscolor(self, hs):
-        try:
-            return self.color_cache[id(hs)]
-        except KeyError:
-            if hs.is_green():
-                color = "green"
-            else:
-                color = "red"
-            self.color_cache[id(hs)] = color
-            return color
+##    def gethscolor(self, hs):
+##        try:
+##            return self.color_cache[id(hs)]
+##        except KeyError:
+##            if hs.is_green():
+##                color = "green"
+##            else:
+##                color = "red"
+##            self.color_cache[id(hs)] = color
+##            return color
 
     def get_dispatch_subclass(self, mergepointfamily):
         try:
@@ -236,6 +231,20 @@
             self.dispatchsubclasses[mergepointfamily] = subclass
             return subclass
 
+    def get_timeshifted_fnptr(self, graph, specialization_key):
+        bk = self.annotator.bookkeeper
+        tsgraph = bk.get_graph_by_key(graph, specialization_key)
+        args_hs, hs_res = self.get_sig_hs(tsgraph)
+        args_r = [self.getrepr(hs_arg) for hs_arg in args_hs]
+        ARGS = [self.r_JITState.lowleveltype]
+        ARGS += [r.lowleveltype for r in args_r]
+        RESULT = self.r_JITState.lowleveltype
+        fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT),
+                                   tsgraph.name,
+                                   graph=tsgraph,
+                                   _callable = graph.func)
+        return fnptr, args_r
+
     def insert_v_jitstate_everywhere(self, graph):
         from pypy.translator.unsimplify import varoftype
         for block in graph.iterblocks():
@@ -511,33 +520,8 @@
         return self.translate_op_ptr_nonzero(hop, reverse=True)
 
 
-    def guess_call_kind(self, spaceop):
-        if spaceop.opname == 'indirect_call':
-            return 'red'  # for now
-        assert spaceop.opname == 'direct_call'
-        c_func = spaceop.args[0]
-        fnobj = c_func.value._obj
-        s_result = self.annotator.binding(spaceop.result)
-        r_result = self.getrepr(s_result)
-        if hasattr(fnobj._callable, 'oopspec'):
-            return 'oopspec'
-        elif (originalconcretetype(s_result) is not lltype.Void and
-              isinstance(r_result, GreenRepr)):
-            for v in spaceop.args:
-                s_arg = self.annotator.binding(v)
-                r_arg = self.getrepr(s_arg)
-                if not isinstance(r_arg, GreenRepr):
-                    return 'yellow'
-            return 'green'
-        else:
-            return 'red'
-
-    def translate_op_direct_call(self, hop):
-        kind = self.guess_call_kind(hop.spaceop)
-        meth = getattr(self, 'handle_%s_call' % (kind,))
-        return meth(hop)
-
     def translate_op_indirect_call(self, hop):
+        XXX
         bk = self.annotator.bookkeeper
         ts = self
         v_jitstate = hop.llops.getjitstate()
@@ -585,6 +569,14 @@
                                                   self.s_JITState)
         hop.llops.setjitstate(v_newjs)
 
+    def translate_op_leave_graph_void(self, hop):
+        v_jitstate = hop.llops.getjitstate()
+        v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_void,
+                                                  [self.s_JITState],
+                                                  [v_jitstate     ],
+                                                  self.s_JITState)
+        hop.llops.setjitstate(v_newjs)
+
     def translate_op_save_locals(self, hop):
         v_jitstate = hop.llops.getjitstate()
         boxes_r = [self.getredrepr(originalconcretetype(hs))
@@ -697,9 +689,17 @@
             return rtimeshift.retrieve_jitstate_for_merge(states_dic,
                                                           jitstate, key)
 
-        greens_v = hop.args_v[2:]
-        greens_s = [annmodel.lltype_to_annotation(originalconcretetype(hs))
-                    for hs in hop.args_s[2:]]
+        greens_v = []
+        greens_s = []
+        for r, v in zip(hop.args_r[2:], hop.args_v[2:]):
+            s_precise_type = r.annotation()
+            s_erased_type  = r.erased_annotation()
+            r_precise_type = self.rtyper.getrepr(s_precise_type)
+            r_erased_type  = self.rtyper.getrepr(s_erased_type)
+            greens_v.append(hop.llops.convertvar(v, r_precise_type,
+                                                    r_erased_type))
+            greens_s.append(s_erased_type)
+
         v_jitstate = hop.llops.getjitstate()
         return hop.llops.genmixlevelhelpercall(merge_point,
                              [self.s_JITState] + greens_s,
@@ -784,7 +784,7 @@
         v = hop.genop('direct_call', hop.args_v, hop.r_result.lowleveltype)
         return v
 
-    def handle_red_call(self, hop):
+    def translate_op_red_call(self, hop):
         bk = self.annotator.bookkeeper
         ts = self
         v_jitstate = hop.llops.getjitstate()
@@ -855,14 +855,14 @@
 class __extend__(pairtype(HintTypeSystem, hintmodel.SomeLLAbstractValue)):
 
     def rtyper_makerepr((ts, hs_c), hrtyper):
-        if hrtyper.gethscolor(hs_c) == 'green':
+        if hs_c.is_green():
             return hrtyper.getgreenrepr(hs_c.concretetype)
         else:
             return hrtyper.getredrepr(hs_c.concretetype)
 
     def rtyper_makekey((ts, hs_c), hrtyper):
-        color = hrtyper.gethscolor(hs_c)
-        return hs_c.__class__, color, hs_c.concretetype
+        is_green = hs_c.is_green()
+        return hs_c.__class__, is_green, hs_c.concretetype
 
 class __extend__(pairtype(HintTypeSystem, hintmodel.SomeLLAbstractContainer)):
 
@@ -909,13 +909,13 @@
         self.lowleveltype = hrtyper.r_RedBox.lowleveltype
         self.hrtyper = hrtyper
 
-    def get_genop_var(self, v, llops):
-        ts = self.hrtyper
-        v_jitstate = hop.llops.getjitstate()
-        return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox,
-                       [ts.s_JITState, llops.hrtyper.s_RedBox],
-                       [v_jitstate,    v],
-                       ts.s_ConstOrVar)
+##    def get_genop_var(self, v, llops):
+##        ts = self.hrtyper
+##        v_jitstate = hop.llops.getjitstate()
+##        return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox,
+##                       [ts.s_JITState, llops.hrtyper.s_RedBox],
+##                       [v_jitstate,    v],
+##                       ts.s_ConstOrVar)
 
     def convert_const(self, ll_value):
         RGenOp = self.hrtyper.RGenOp
@@ -963,13 +963,13 @@
         else:
             return annmodel.SomeInteger()
 
-    def get_genop_var(self, v, llops):
-        ts = self.hrtyper
-        v_jitstate = hop.llops.getjitstate()
-        return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant,
-                                           [ts.s_JITState, self.annotation()],
-                                           [v_jitstate,    v],
-                                           ts.s_ConstOrVar)
+##    def get_genop_var(self, v, llops):
+##        ts = self.hrtyper
+##        v_jitstate = hop.llops.getjitstate()
+##        return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant,
+##                                           [ts.s_JITState, self.annotation()],
+##                                           [v_jitstate,    v],
+##                                           ts.s_ConstOrVar)
 
     def convert_const(self, ll_value):
         return ll_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	Wed Sep 20 16:34:40 2006
@@ -2,6 +2,7 @@
 from pypy.objspace.flow.model import SpaceOperation, mkentrymap
 from pypy.annotation        import model as annmodel
 from pypy.jit.hintannotator import model as hintmodel
+from pypy.jit.hintannotator.model import originalconcretetype
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.rmodel import inputconst
 from pypy.translator.unsimplify import varoftype, copyvar
@@ -35,6 +36,7 @@
         self.insert_splits()
         for block in mergepoints:
             self.insert_merge(block)
+        self.split_after_calls()
         self.insert_dispatcher()
         self.insert_enter_graph()
         self.insert_leave_graph()
@@ -47,20 +49,17 @@
 
     # __________ helpers __________
 
-    def genop(self, block, opname, args, result_type=None):
+    def genop(self, block, opname, args, result_type=None, result_like=None):
         # 'result_type' can be a LowLevelType (for green returns)
         # or a template variable whose hintannotation is copied
-        if result_type is None:
-            v_res = self.new_void_var()
-        elif isinstance(result_type, lltype.LowLevelType):
+        if result_type is not None:
             v_res = varoftype(result_type)
             hs = hintmodel.SomeLLAbstractConstant(result_type, {})
             self.hannotator.setbinding(v_res, hs)
-        elif isinstance(result_type, Variable):
-            var = result_type
-            v_res = copyvar(self.hannotator, var)
+        elif result_like is not None:
+            v_res = copyvar(self.hannotator, result_like)
         else:
-            raise TypeError("result_type=%r" % (result_type,))
+            v_res = self.new_void_var()
 
         spaceop = SpaceOperation(opname, args, v_res)
         if isinstance(block, list):
@@ -100,6 +99,19 @@
         block.recloseblock(Link([], newblock))
         return newblock
 
+    def variables_alive(self, block, before_position):
+        created_before = dict.fromkeys(block.inputargs)
+        for op in block.operations[:before_position]:
+            created_before[op.result] = True
+        used = {}
+        for op in block.operations[before_position:]:
+            for v in op.args:
+                used[v] = True
+        for link in block.exits:
+            for v in link.args:
+                used[v] = True
+        return [v for v in used if v in created_before]
+
     def sort_by_color(self, vars):
         reds = []
         greens = []
@@ -183,12 +195,12 @@
                 if self.hannotator.binding(v).is_green():
                     c = inputconst(lltype.Signed, greencount)
                     v1 = self.genop(resumeblock, 'restore_green', [c],
-                                    result_type = v)
+                                    result_like = v)
                     greencount += 1
                 else:
                     c = inputconst(lltype.Signed, redcount)
                     v1 = self.genop(resumeblock, 'restore_local', [c],
-                                    result_type = v)
+                                    result_like = v)
                     redcount += 1
                 newvars.append(v1)
 
@@ -221,7 +233,7 @@
         for i, v in enumerate(reds):
             c = inputconst(lltype.Signed, i)
             v1 = self.genop(restoreops, 'restore_local', [c],
-                            result_type = v)
+                            result_like = v)
             mapping[v] = v1
         nextblock.renamevariables(mapping)
         nextblock.operations[:0] = restoreops
@@ -245,7 +257,13 @@
     def insert_save_return(self):
         block = self.before_return_block()
         [v_retbox] = block.inputargs
-        self.genop(block, 'save_locals', [v_retbox])
+        hs_retbox = self.hannotator.binding(v_retbox)
+        if originalconcretetype(hs_retbox) is lltype.Void:
+            self.leave_graph_opname = 'leave_graph_void'
+            self.genop(block, 'save_locals', [])
+        else:
+            self.leave_graph_opname = 'leave_graph_red'
+            self.genop(block, 'save_locals', [v_retbox])
         self.genop(block, 'save_return', [])
 
     def insert_enter_graph(self):
@@ -258,4 +276,74 @@
 
     def insert_leave_graph(self):
         block = self.before_return_block()
-        self.genop(block, 'leave_graph_red', [])
+        self.genop(block, self.leave_graph_opname, [])
+
+    # __________ handling of the various kinds of calls __________
+
+    def guess_call_kind(self, spaceop):
+        if spaceop.opname == 'indirect_call':
+            return 'red'  # for now
+        assert spaceop.opname == 'direct_call'
+        c_func = spaceop.args[0]
+        fnobj = c_func.value._obj
+        s_result = self.hannotator.binding(spaceop.result)
+        if hasattr(fnobj._callable, 'oopspec'):
+            return 'oopspec'
+        elif (originalconcretetype(s_result) is not lltype.Void and
+              s_result.is_green()):
+            for v in spaceop.args:
+                s_arg = self.hannotator.binding(v)
+                if not s_arg.is_green():
+                    return 'yellow'
+            return 'green'
+        else:
+            return 'red'
+
+    def split_after_calls(self):
+        for block in list(self.graph.iterblocks()):
+            for i in range(len(block.operations)-1, -1, -1):
+                op = block.operations[i]
+                if op.opname in ('direct_call', 'indirect_call'):
+                    call_kind = self.guess_call_kind(op)
+                    handler = getattr(self, 'handle_%s_call' % (call_kind,))
+                    handler(block, i)
+
+    def handle_red_call(self, block, pos):
+        # the 'save_locals' pseudo-operation is used to save all
+        # alive local variables into the current JITState
+        beforeops = block.operations[:pos]
+        op        = block.operations[pos]
+        afterops  = block.operations[pos+1:]
+
+        varsalive = self.variables_alive(block, pos+1)
+        try:
+            varsalive.remove(op.result)
+            uses_retval = True      # it will be restored by 'fetch_return'
+        except ValueError:
+            uses_retval = False
+        reds, greens = self.sort_by_color(varsalive)
+
+        newops = []
+        self.genop(newops, 'save_locals', reds)
+        self.genop(newops, 'red_call', op.args)    # Void result,
+        # because the call doesn't return its redbox result, but only
+        # has the hidden side-effect of putting it in the jitstate
+        mapping = {}
+        for i, var in enumerate(reds):
+            c_index = Constant(i, concretetype=lltype.Signed)
+            newvar = self.genop(newops, 'restore_local', [c_index],
+                                result_like = var)
+            mapping[var] = newvar
+
+        if uses_retval and not self.hannotator.binding(op.result).is_green():
+            var = op.result
+            newvar = self.genop(newops, 'fetch_return', [],
+                                result_like = var)
+            mapping[var] = newvar
+
+        saved = block.inputargs
+        block.inputargs = []     # don't rename these!
+        block.operations = afterops
+        block.renamevariables(mapping)
+        block.inputargs = saved
+        block.operations[:0] = beforeops + newops



More information about the Pypy-commit mailing list