[pypy-svn] r35278 - in pypy/branch/jit-real-world/pypy/jit: hintannotator hintannotator/test timeshifter timeshifter/test

arigo at codespeak.net arigo at codespeak.net
Tue Dec 5 02:02:01 CET 2006


Author: arigo
Date: Tue Dec  5 02:01:56 2006
New Revision: 35278

Modified:
   pypy/branch/jit-real-world/pypy/jit/hintannotator/annotator.py
   pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py
   pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py
   pypy/branch/jit-real-world/pypy/jit/hintannotator/test/test_annotator.py
   pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py
   pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py
Log:
(pedronis, arre on the earlier sweat part, arigo)

Don't use the RPython's normalization in the hint-annotator.  It took
quite some sweat to discover that it was not a good idea.  Instead, for
all the variables whose color is not fixed at the end of
hint-annotation, we proceed by assuming that they are all green and
forcing them to red as needed, in a fixpoint process again.  The "needs"
is based on the dependencies captured by 'myorigin' and by the call
families, which produces the normalization effect.


Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/annotator.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/hintannotator/annotator.py	(original)
+++ pypy/branch/jit-real-world/pypy/jit/hintannotator/annotator.py	Tue Dec  5 02:01:56 2006
@@ -10,9 +10,12 @@
 
 class HintAnnotatorPolicy(policy.AnnotatorPolicy):
 
-    def __init__(self, novirtualcontainer=False, oopspec=False):
-        self.novirtualcontainer = novirtualcontainer
-        self.oopspec            = oopspec
+    def __init__(self, novirtualcontainer     = False,
+                       oopspec                = False,
+                       entrypoint_returns_red = True):
+        self.novirtualcontainer     = novirtualcontainer
+        self.oopspec                = oopspec
+        self.entrypoint_returns_red = entrypoint_returns_red
 
     def look_inside_graph(self, graph):
         return True

Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py	(original)
+++ pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py	Tue Dec  5 02:01:56 2006
@@ -25,12 +25,15 @@
 
         # modify input_args_hs in-place to change their origin
         for i in range(len(input_args_hs)):
-            old = self.bookkeeper.enter((graph, i))
-            try:
-                input_args_hs[i] = hintmodel.reorigin(input_args_hs[i])
-            finally:
-                self.bookkeeper.leave(old)
-
+            hs_v1 = input_args_hs[i]
+            if isinstance(hs_v1, hintmodel.SomeLLAbstractConstant):
+                myorigin = self.bookkeeper.myinputargorigin(graph, i)
+                hs_v1 = hintmodel.SomeLLAbstractConstant(
+                    hs_v1.concretetype, {myorigin: True},
+                    eager_concrete = hs_v1.eager_concrete,
+                    deepfrozen     = hs_v1.deepfrozen,
+                    myorigin       = myorigin)
+                input_args_hs[i] = hs_v1
         return graph
 
     def cachedgraph(self, key, alt_name=None):
@@ -100,31 +103,80 @@
         else:
             self.position_key = old
 
+    def myinputargorigin(self, graph, i):
+        try:
+            origin = self.originflags[graph, i]
+        except KeyError:
+            origin = hintmodel.InputArgOriginFlags(self, graph, i)
+            self.originflags[graph, i] = origin
+        return origin
+
     def myorigin(self):
         try:
             origin = self.originflags[self.position_key]
         except KeyError:
-            if len(self.position_key) == 3:
-                graph, block, i = self.position_key
-                spaceop = block.operations[i]
-                spaceop = SpaceOperation(spaceop.opname,
-                                         list(spaceop.args),
-                                         spaceop.result)
-            else:
-                spaceop = None
+            assert len(self.position_key) == 3
+            graph, block, i = self.position_key
+            spaceop = block.operations[i]
+            spaceop = SpaceOperation(spaceop.opname,
+                                     list(spaceop.args),
+                                     spaceop.result)
             origin = hintmodel.OriginFlags(self, spaceop)
             self.originflags[self.position_key] = origin
         return origin
 
     def compute_at_fixpoint(self):
-        pass
+        binding = self.annotator.binding
 
-    def compute_after_normalization(self):
-        # compute and cache the green-ness of OriginFlags objects
-        # while we can do so (i.e. before the graphs are modified).
+        # for the entry point, we need to remove the 'myorigin' of
+        # the input arguments (otherwise they will always be green,
+        # as there is no call to the entry point to make them red)
+        tsgraph = self.annotator.translator.graphs[0]
+        for v in tsgraph.getargs():
+            hs_arg = binding(v)
+            if isinstance(hs_arg, hintmodel.SomeLLAbstractConstant):
+                hs_arg.myorigin = None
+        # for convenience, force the return var to be red too, as
+        # the timeshifter doesn't support anything else
+        if self.annotator.policy.entrypoint_returns_red:
+            v = tsgraph.getreturnvar()
+            hs_red = hintmodel.variableoftype(v.concretetype)
+            self.annotator.setbinding(v, hs_red)
+
+        # propagate the green/red constraints
+        log.event("Computing maximal green set...")
+        greenorigindependencies = {}
         for origin in self.originflags.values():
-            if origin.spaceop is not None:
-                origin.greenargs_cached = origin.greenargs()
+            origin.greenargs = True
+            origin.record_dependencies(greenorigindependencies)
+
+        while True:
+            progress = False
+            for origin, deps in greenorigindependencies.items():
+                for v in deps:
+                    if not binding(v).is_green():
+                        # not green => force the origin to be red too
+                        origin.greenargs = False
+                        del greenorigindependencies[origin]
+                        progress = True
+                        break
+            if not progress:
+                break
+
+        for callfamily in self.tsgraph_maximal_call_families.infos():
+            if len(callfamily.tsgraphs) > 1:
+                # if at least one graph in the family returns a red,
+                # we force a red as the return of all of them
+                returns_red = False
+                for graph in callfamily.tsgraphs:
+                    if not binding(graph.getreturnvar()).is_green():
+                        returns_red = True
+                if returns_red:
+                    for graph in callfamily.tsgraphs:
+                        v = graph.getreturnvar()
+                        hs_red = hintmodel.variableoftype(v.concretetype)
+                        self.annotator.setbinding(v, hs_red)
+
         # compute and cache the signature of the graphs before they are
         # modified by further code
         ha = self.annotator
@@ -249,8 +301,12 @@
             hs_res = hintmodel.reorigin(hs_res, *deps_hs)
         return hs_res
 
-    def graph_family_call(self, graph_list, fixed, args_hs):
-        tsgraphs = []
+    def graph_family_call(self, graph_list, fixed, args_hs,
+                          tsgraphs_accum=None):
+        if tsgraphs_accum is None:
+            tsgraphs = []
+        else:
+            tsgraphs = tsgraphs_accum
         results_hs = []
         for graph in graph_list:
             results_hs.append(self.graph_call(graph, fixed, args_hs, tsgraphs))

Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py	(original)
+++ pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py	Tue Dec  5 02:01:56 2006
@@ -33,22 +33,26 @@
     pass
 
 class OriginFlags(object):
-
     fixed = False
     read_positions = None
-    greenargs_cached = None
-    is_call_result = False
+    greenargs = False
 
     def __init__(self, bookkeeper=None, spaceop=None):
         self.bookkeeper = bookkeeper
         self.spaceop = spaceop
 
     def __repr__(self):
+        return '<%s %s>' % (getattr(self.spaceop, 'result', '?'),
+                            self.reprstate())
+
+    def reprstate(self):
         if self.fixed:
             s = "fixed "
+        elif self.greenargs:
+            s = "green"
         else:
             s = ""
-        return "<%sorigin>" % (s,)
+        return "%sorigin" % (s,)
 
     def read_fixed(self):
         if self.read_positions is None:
@@ -64,63 +68,66 @@
                 for p in self.read_positions:
                     annotator.reflowfromposition(p)
 
-    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.is_call_result:
-            return frame.greencallresult(self.spaceop)
+    def record_dependencies(self, greenorigindependencies):
+        deps = greenorigindependencies.setdefault(self, [])
+        deps.extend(self.spaceop.args)
+
+
+class CallOpOriginFlags(OriginFlags):
+
+    def record_dependencies(self, greenorigindependencies):
+        bk = self.bookkeeper
+        if self.spaceop.opname == 'direct_call':
+            args = self.spaceop.args[1:]
+        elif self.spaceop.opname == 'indirect_call':
+            args = self.spaceop.args[1:-1]
         else:
-            for v in self.spaceop.args:
-                if not frame.greenvar(v):
-                    return False
-            return True
-
-
-class GreenHandlerFrame(object):
-
-    def __init__(self, annotator, parentframe=None):
-        self.annotator = annotator
-        self.parentframe = parentframe
-        self.inputarg2actualarg = {}    # {origin: annotation}
-
-    def greenvar(self, v):
-        hs = self.annotator.binding(v)
-        if isinstance(hs, SomeLLAbstractConstant) and len(hs.origins) == 1:
-            [o] = hs.origins.keys()
-            if o in self.inputarg2actualarg:
-                hs_actual = self.inputarg2actualarg[o]
-                return hs_actual.is_green(self.parentframe)
-        return hs.is_green(self)
-
-    def greencallresult(self, spaceop):
-##        print spaceop
-##        if str(spaceop.result) == 'v58':
-##            import pdb; pdb.set_trace()
-        args_hs = [self.annotator.binding(v) for v in spaceop.args]
-        hs_result = self.annotator.binding(spaceop.result)
-        if not isinstance(hs_result, SomeLLAbstractConstant):
-            return False     # was generalized, e.g. to SomeLLAbstractVariable
-        hs_f1 = args_hs.pop(0)
-        fnobj = hs_f1.const._obj
-        if (self.annotator.policy.oopspec and
-            hasattr(fnobj._callable, 'oopspec')):
-            assert False     # XXX?
+            raise AssertionError(self.spaceop.opname)
 
-        input_args_hs = list(args_hs)
-        bk = self.annotator.bookkeeper
-        graph = bk.get_graph_for_call(fnobj.graph,
-                                      hs_result.is_fixed(),
-                                      input_args_hs)
-        newframe = GreenHandlerFrame(self.annotator, parentframe=self)
-        for hs_inp_arg, hs_arg in zip(input_args_hs, args_hs):
-            if isinstance(hs_arg, SomeLLAbstractConstant):
-                assert len(hs_inp_arg.origins) == 1
-                [o] = hs_inp_arg.origins.keys()
-                newframe.inputarg2actualarg[o] = hs_arg
-        return newframe.greenvar(graph.getreturnvar())
+        graph = self.any_called_graph
+        call_families = bk.tsgraph_maximal_call_families
+        _, repgraph, callfamily = call_families.find(graph)
+
+        # record the argument and return value dependencies
+        retdeps = greenorigindependencies.setdefault(self, [])
+        for graph in callfamily.tsgraphs:
+            retdeps.append(graph.getreturnvar())
+            for i, v in enumerate(args):
+                argorigin = bk.myinputargorigin(graph, i)
+                deps = greenorigindependencies.setdefault(argorigin, [])
+                deps.append(v)
+
+
+class InputArgOriginFlags(OriginFlags):
+
+    def __init__(self, bookkeeper, graph, i):
+        OriginFlags.__init__(self, bookkeeper)
+        self.graph = graph
+        self.i = i
+
+    def getarg(self):
+        return self.graph.getargs()[self.i]
+
+    def __repr__(self):
+        return '<%s %s>' % (self.getarg(), self.reprstate())
+
+    def record_dependencies(self, greenorigindependencies):
+        bk = self.bookkeeper
+        call_families = bk.tsgraph_maximal_call_families
+        _, repgraph, callfamily = call_families.find(self.graph)
+
+        # record the fact that each graph's input args should be as red
+        # as each other's
+        if self.graph is repgraph:
+            deps = greenorigindependencies.setdefault(self, [])
+            v = self.getarg()
+            for othergraph in callfamily.tsgraphs:
+                if othergraph is not repgraph:
+                    deps.append(othergraph.getargs()[self.i])
+                    otherorigin = bk.myinputargorigin(othergraph, self.i)
+                    otherdeps = greenorigindependencies.setdefault(otherorigin,
+                                                                   [])
+                    otherdeps.append(v)
 
 # ____________________________________________________________
 
@@ -132,7 +139,7 @@
         assert self.__class__ != SomeLLAbstractValue
         self.deepfrozen = deepfrozen
 
-    def is_green(self, frame=None):
+    def is_green(self):
         return False
 
 
@@ -145,12 +152,11 @@
         self.origins = origins
         self.eager_concrete = eager_concrete
         self.myorigin = myorigin
-        assert myorigin is None or myorigin.spaceop is not None
 
     def fmt_origins(self, origins):
         counts = {}
         for o in origins:
-            x = repr(o)
+            x = o.reprstate()
             counts[x] = counts.get(x, 0) + 1
         items = counts.items()
         items.sort()
@@ -167,7 +173,7 @@
         if myorigin is None:
             return None
         else:
-            return str(myorigin.spaceop.result)
+            return repr(myorigin)
 
     def is_fixed(self):
         for o in self.origins:
@@ -175,18 +181,19 @@
                 return False
         return True
 
-    def is_green(self, frame=None):
+    def is_green(self):
         return (self.is_fixed() or self.eager_concrete or
                 self.concretetype is lltype.Void or
-                (self.myorigin is not None and
-                 self.myorigin.greenargs(frame)))
+                (self.myorigin is not None and self.myorigin.greenargs))
 
     def annotationcolor(self):
         """Compute the color of the variables with this annotation
         for the pygame viewer
         """
         try:
-            if self.eager_concrete:
+            if self.concretetype is lltype.Void:
+                return annmodel.s_ImpossibleValue.annotationcolor
+            elif self.eager_concrete:
                 return (0,100,0)     # green
             elif self.is_green():
                 return (50,140,0)    # green-dark-cyan
@@ -328,11 +335,16 @@
             # cannot follow
             return variableoftype(hs_v1.concretetype.TO.RESULT)
 
-        fixed = bookkeeper.myorigin().read_fixed()
-        hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs)
+        myorigin = bookkeeper.myorigin()
+        myorigin.__class__ = CallOpOriginFlags     # thud
+        fixed = myorigin.read_fixed()
+        tsgraphs_accum = []
+        hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs,
+                                              tsgraphs_accum)
+        myorigin.any_called_graph = tsgraphs_accum[0]
 
         if isinstance(hs_res, SomeLLAbstractConstant):
-            hs_res.myorigin = bookkeeper.myorigin()
+            hs_res.myorigin = myorigin
 
         # we need to make sure that hs_res does not become temporarily less
         # general as a result of calling another specialized version of the
@@ -390,12 +402,17 @@
             bookkeeper.annotator.translator.graphs[0]):
             return variableoftype(lltype.typeOf(fnobj).RESULT)
 
-        fixed = bookkeeper.myorigin().read_fixed()
-        hs_res = bookkeeper.graph_call(fnobj.graph, fixed, args_hs)
+        myorigin = bookkeeper.myorigin()
+        myorigin.__class__ = CallOpOriginFlags     # thud
+        fixed = myorigin.read_fixed()
+        tsgraphs_accum = []
+        hs_res = bookkeeper.graph_call(fnobj.graph, fixed, args_hs,
+                                       tsgraphs_accum)
+        myorigin.any_called_graph = tsgraphs_accum[0]
 
         if isinstance(hs_res, SomeLLAbstractConstant):
-            hs_res.myorigin = bookkeeper.myorigin()
-            hs_res.myorigin.is_call_result = True
+            hs_res.myorigin = myorigin
+
 ##        elif fnobj.graph.name.startswith('ll_stritem'):
 ##            if isinstance(hs_res, SomeLLAbstractVariable):
 ##                print hs_res

Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/hintannotator/test/test_annotator.py	(original)
+++ pypy/branch/jit-real-world/pypy/jit/hintannotator/test/test_annotator.py	Tue Dec  5 02:01:56 2006
@@ -10,12 +10,16 @@
 from pypy.translator.backendopt.inline import auto_inlining
 from pypy import conftest
 
-P_OOPSPEC = HintAnnotatorPolicy(oopspec=True)
+P_DEFAULT = HintAnnotatorPolicy(entrypoint_returns_red=False)
+P_OOPSPEC = HintAnnotatorPolicy(oopspec=True,
+                                entrypoint_returns_red=False)
 P_OOPSPEC_NOVIRTUAL = HintAnnotatorPolicy(oopspec=True,
-                                          novirtualcontainer=True)
-P_NOVIRTUAL = HintAnnotatorPolicy(novirtualcontainer=True)
+                                          novirtualcontainer=True,
+                                          entrypoint_returns_red=False)
+P_NOVIRTUAL = HintAnnotatorPolicy(novirtualcontainer=True,
+                                  entrypoint_returns_red=False)
 
-def hannotate(func, argtypes, policy=None, annotator=False, inline=None,
+def hannotate(func, argtypes, policy=P_DEFAULT, annotator=False, inline=None,
               backendoptimize=False):
     # build the normal ll graphs for ll_function
     t = TranslationContext()

Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py	(original)
+++ pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py	Tue Dec  5 02:01:56 2006
@@ -152,9 +152,9 @@
         """
         Driver for running the timeshifter.
         """
-        self.type_system.perform_normalizations(self)
+##        self.type_system.perform_normalizations(self)
         bk = self.annotator.bookkeeper
-        bk.compute_after_normalization()
+##        bk.compute_after_normalization()
         entrygraph = self.annotator.translator.graphs[0]
         self.origportalgraph = origportalgraph
         if origportalgraph:

Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py	Tue Dec  5 02:01:56 2006
@@ -1134,15 +1134,15 @@
         self.check_insns({})
 
     def test_green_red_mismatch_in_call(self):
-        py.test.skip("WIP")
+        #py.test.skip("WIP")
         def add(a,b, u):
             return a+b
 
         def f(x, y, u):
             r = add(x+1,y+1, u)
             z = x+y
-            hint(z, concrete=True)
+            z = hint(z, concrete=True) + r   # this checks that 'r' is green
             return hint(z, variable=True)
 
         res = self.timeshift(f, [4, 5, 0], [], policy=P_NOVIRTUAL)
-        assert res == 9
+        assert res == 20


More information about the pypy-svn mailing list