[pypy-svn] r37560 - in pypy/dist/pypy: jit/hintannotator jit/hintannotator/test jit/timeshifter jit/timeshifter/test rpython/lltypesystem

arigo at codespeak.net arigo at codespeak.net
Mon Jan 29 19:06:52 CET 2007


Author: arigo
Date: Mon Jan 29 19:06:48 2007
New Revision: 37560

Modified:
   pypy/dist/pypy/jit/hintannotator/bookkeeper.py
   pypy/dist/pypy/jit/hintannotator/model.py
   pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
   pypy/dist/pypy/jit/timeshifter/test/test_portal.py
   pypy/dist/pypy/jit/timeshifter/transform.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
Log:
Detect green calls in compute_at_fixpoint() already.  This allows helper
functions like isinstance() to return a green result for green arguments,
as expected.


Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/bookkeeper.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py	Mon Jan 29 19:06:48 2007
@@ -3,8 +3,9 @@
 from pypy.tool.ansi_print import ansi_log
 from pypy.objspace.flow.model import copygraph, SpaceOperation, Constant
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, lloperation
 from pypy.tool.algo.unionfind import UnionFind
+from pypy.translator.backendopt import graphanalyze
 
 TLS = tlsobject()
 
@@ -66,6 +67,20 @@
         self.tsgraphs.update(other.tsgraphs)
 
 
+class ImpurityAnalyzer(graphanalyze.GraphAnalyzer):
+    """An impure graph has side-effects or depends on state that
+    can be mutated.  A pure graph always gives the same answer for
+    given arguments."""
+
+    def analyze_exceptblock(self, block, seen=None):
+        raise AssertionError("graphs here should be exception-transformed")
+
+    def operation_is_true(self, op):
+        operation = lloperation.LL_OPERATIONS[op.opname]
+        ARGTYPES = [v.concretetype for v in op.args]
+        return not operation.is_pure(*ARGTYPES)
+
+
 class HintBookkeeper(object):
 
     def __init__(self, hannotator):
@@ -143,15 +158,34 @@
             hs_red = hintmodel.variableoftype(v.concretetype)
             self.annotator.setbinding(v, hs_red)
 
+        # is_green_call() is only meaningful at fixpoint,
+        # so initialize the state here
+        t = self.annotator.base_translator
+        self.impurity_analyzer = ImpurityAnalyzer(t)
+
         # propagate the green/red constraints
         log.event("Computing maximal green set...")
         greenorigindependencies = {}
+        callreturndependencies = {}
         for origin in self.originflags.values():
             origin.greenargs = True
-            origin.record_dependencies(greenorigindependencies)
+            origin.record_dependencies(greenorigindependencies,
+                                       callreturndependencies)
 
         while True:
             progress = False
+            # check all calls to see if they are green calls or not
+            for origin, graphs in callreturndependencies.items():
+                if self.is_green_call(origin.spaceop):
+                    pass   # green call => don't force spaceop.result to red
+                else:
+                    # non-green calls: replace the dependency with a regular
+                    # dependency from graph.getreturnvar() to spaceop.result
+                    del callreturndependencies[origin]
+                    retdeps = greenorigindependencies.setdefault(origin, [])
+                    for graph in graphs:
+                        retdeps.append(graph.getreturnvar())
+            # propagate normal dependencies
             for origin, deps in greenorigindependencies.items():
                 for v in deps:
                     if not binding(v).is_green():
@@ -185,6 +219,17 @@
                       ha.binding(tsgraph.getreturnvar()))
             self.tsgraphsigs[tsgraph] = sig_hs
 
+    def is_green_call(self, callop):
+        "Is the given call operation completely computable at compile-time?"
+        for v in callop.args:
+            hs_arg = self.annotator.binding(v)
+            if not hs_arg.is_green():
+                return False
+        # all-green arguments.  Note that we can return True even if the
+        # result appears to be red; it's not a real red result then.
+        impure = self.impurity_analyzer.analyze(callop)
+        return not impure
+
     def immutableconstant(self, const):
         res = hintmodel.SomeLLAbstractConstant(const.concretetype, {})
         res.const = const.value

Modified: pypy/dist/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/model.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/model.py	Mon Jan 29 19:06:48 2007
@@ -68,14 +68,16 @@
                 for p in self.read_positions:
                     annotator.reflowfromposition(p)
 
-    def record_dependencies(self, greenorigindependencies):
+    def record_dependencies(self, greenorigindependencies,
+                                  callreturndependencies):
         deps = greenorigindependencies.setdefault(self, [])
         deps.extend(self.spaceop.args)
 
 
 class CallOpOriginFlags(OriginFlags):
 
-    def record_dependencies(self, greenorigindependencies):
+    def record_dependencies(self, greenorigindependencies,
+                                  callreturndependencies):
         bk = self.bookkeeper
         if self.spaceop.opname == 'direct_call':
             args = self.spaceop.args[1:]
@@ -89,9 +91,9 @@
         _, repgraph, callfamily = call_families.find(graph)
 
         # record the argument and return value dependencies
-        retdeps = greenorigindependencies.setdefault(self, [])
+        retdeps = callreturndependencies.setdefault(self, [])
         for graph in callfamily.tsgraphs:
-            retdeps.append(graph.getreturnvar())
+            retdeps.append(graph)
             for i, v in enumerate(args):
                 argorigin = bk.myinputargorigin(graph, i)
                 deps = greenorigindependencies.setdefault(argorigin, [])
@@ -111,7 +113,8 @@
     def __repr__(self):
         return '<%s %s>' % (self.getarg(), self.reprstate())
 
-    def record_dependencies(self, greenorigindependencies):
+    def record_dependencies(self, greenorigindependencies,
+                                  callreturndependencies):
         bk = self.bookkeeper
         call_families = bk.tsgraph_maximal_call_families
         _, repgraph, callfamily = call_families.find(self.graph)

Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py	Mon Jan 29 19:06:48 2007
@@ -688,3 +688,17 @@
         return o.m()
 
     hs = hannotate(f, [bool], policy=P_OOPSPEC_NOVIRTUAL)
+
+
+def test_green_isinstance():
+    class Base(object):
+        pass
+    class Concrete(Base):
+        pass
+
+    def f(o):
+        hint(o, concrete=True)
+        return isinstance(o, Concrete)
+
+    hs = hannotate(f, [Base], policy=P_OOPSPEC_NOVIRTUAL)
+    assert hs.is_green()

Modified: pypy/dist/pypy/jit/timeshifter/test/test_portal.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_portal.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_portal.py	Mon Jan 29 19:06:48 2007
@@ -401,7 +401,6 @@
         assert res == 11
     
     def test_isinstance(self):
-        py.test.skip("(cfbolz) don't get it")
         class Base(object):
             pass
         class Int(Base):
@@ -426,5 +425,5 @@
             
 
         res = self.timeshift_from_portal(ll_main, ll_function, [5], policy=P_NOVIRTUAL)
-        assert res == 10
+        assert res is False
 

Modified: pypy/dist/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/transform.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/transform.py	Mon Jan 29 19:06:48 2007
@@ -3,30 +3,14 @@
 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, lloperation
+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.simplify import rec_op_has_side_effects
-from pypy.translator.backendopt import graphanalyze
 from pypy.translator.backendopt.ssa import SSA_to_SSI
 from pypy.translator.unsimplify import split_block
 
 
-class HasSideeffects(graphanalyze.GraphAnalyzer):
-
-    EXCEPTIONS = ('debug_assert',)
-
-    def analyze_exceptblock(self, block, seen=None):
-        # graphs explicitly raising have side-effects
-        return True
-
-    def operation_is_true(self, op):
-        opname = op.opname
-        return (lloperation.LL_OPERATIONS[opname].sideeffects and
-                opname not in self.EXCEPTIONS)
-
-
 class MergePointFamily(object):
     def __init__(self, tsgraph):
         self.tsgraph = tsgraph
@@ -63,13 +47,8 @@
         self.c_mpfamily = inputconst(lltype.Void, self.mergepointfamily)
         self.tsgraphs_seen = []
 
-        t = self.hannotator.base_translator
-        self.sideeffects_analyzer = HasSideeffects(t)
         self.raise_analyzer = hannotator.exceptiontransformer.raise_analyzer
 
-    def has_sideeffects(self, op):
-        return self.sideeffects_analyzer.analyze(op)
-
     def can_raise(self, op):
         return self.raise_analyzer.analyze(op)
 
@@ -496,18 +475,8 @@
                 if fnobj._callable.oopspec.startswith('vable.'):
                     return 'vable'
                 return 'oopspec'
-
-        for v in spaceop.args:
-            hs_arg = self.hannotator.binding(v)
-            if not hs_arg.is_green():
-                break
-        else:
-            hs_res = self.hannotator.binding(spaceop.result)
-            if hs_res.is_green():
-                # all-green arguments and result.
-                # Does the function have side-effects?
-                if not self.has_sideeffects(spaceop):
-                    return 'green'
+        if self.hannotator.bookkeeper.is_green_call(spaceop):
+            return 'green'
         colors = {}
         for graph, tsgraph in self.graphs_from(spaceop):
             color = self.graph_calling_color(tsgraph)

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Mon Jan 29 19:06:48 2007
@@ -80,6 +80,13 @@
         return op_impl
     fold = roproperty(get_fold_impl)
 
+    def is_pure(self, *ARGTYPES):
+        return (self.canfold or                # canfold => pure operation
+                self is llop.debug_assert or   # debug_assert is pure enough
+                                               # reading from immutable
+                (self in (llop.getfield, llop.getarrayitem) and
+                 ARGTYPES[0].TO._hints.get('immutable')))
+
 
 def enum_ops_without_sideeffects(raising_is_ok=False):
     """Enumerate operations that have no side-effects



More information about the Pypy-commit mailing list