[pypy-svn] r37932 - in pypy/branch/jit-virtual-world/pypy/jit: hintannotator hintannotator/test timeshifter timeshifter/test

arigo at codespeak.net arigo at codespeak.net
Sun Feb 4 23:12:05 CET 2007


Author: arigo
Date: Sun Feb  4 23:12:02 2007
New Revision: 37932

Modified:
   pypy/branch/jit-virtual-world/pypy/jit/hintannotator/bookkeeper.py
   pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py
   pypy/branch/jit-virtual-world/pypy/jit/hintannotator/test/test_annotator.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_portal.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vdict.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vlist.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vlist.py
Log:
(pedronis, arigo)

* hint-annotation fixes for indirect yellow calls.

* refactor and try to unify a bit more red and yellow calls
  in the transformer.  The result is rather powerful (and
  completely obscure in the transformer).

* deepfrozen lists in the oopspec timeshifting.



Modified: pypy/branch/jit-virtual-world/pypy/jit/hintannotator/bookkeeper.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/hintannotator/bookkeeper.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/hintannotator/bookkeeper.py	Sun Feb  4 23:12:02 2007
@@ -317,7 +317,8 @@
         graph = desc.specialize(args_hs, key=key, alt_name=alt_name)
         return graph
 
-    def graph_call(self, graph, fixed, args_hs, tsgraph_accum=None):
+    def graph_call(self, graph, fixed, args_hs,
+                   tsgraph_accum=None, hs_callable=None):
         input_args_hs = list(args_hs)
         graph = self.get_graph_for_call(graph, fixed, input_args_hs)
         if tsgraph_accum is not None:
@@ -337,27 +338,34 @@
                                               input_args_hs)
         # look on which input args the hs_res result depends on
         if isinstance(hs_res, hintmodel.SomeLLAbstractConstant):
-            deps_hs = []
-            for hs_inputarg, hs_arg in zip(input_args_hs, args_hs):
-                if isinstance(hs_inputarg, hintmodel.SomeLLAbstractConstant):
-                    assert len(hs_inputarg.origins) == 1
-                    [o] = hs_inputarg.origins.keys()
-                    if o in hs_res.origins:
-                        deps_hs.append(hs_arg)
-            if fixed:
-                deps_hs.append(hs_res)
-            hs_res = hintmodel.reorigin(hs_res, *deps_hs)
+            if (hs_callable is not None and
+                not isinstance(hs_callable, hintmodel.SomeLLAbstractConstant)):
+                hs_res = hintmodel.variableoftype(hs_res.concretetype,
+                                                  hs_res.deepfrozen)
+            else:
+                deps_hs = []
+                for hs_inputarg, hs_arg in zip(input_args_hs, args_hs):
+                    if isinstance(hs_inputarg,
+                                  hintmodel.SomeLLAbstractConstant):
+                        assert len(hs_inputarg.origins) == 1
+                        [o] = hs_inputarg.origins.keys()
+                        if o in hs_res.origins:
+                            deps_hs.append(hs_arg)
+                if fixed:
+                    deps_hs.append(hs_res)
+                hs_res = hintmodel.reorigin(hs_res, hs_callable, *deps_hs)
         return hs_res
 
     def graph_family_call(self, graph_list, fixed, args_hs,
-                          tsgraphs_accum=None):
+                          tsgraphs_accum=None, hs_callable=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))
+            results_hs.append(self.graph_call(graph, fixed, args_hs,
+                                              tsgraphs, hs_callable))
         # put the tsgraphs in the same call family
         call_families = self.tsgraph_maximal_call_families
         _, rep, callfamily = call_families.find(tsgraphs[0])

Modified: pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py	Sun Feb  4 23:12:02 2007
@@ -83,6 +83,11 @@
             args = self.spaceop.args[1:]
         elif self.spaceop.opname == 'indirect_call':
             args = self.spaceop.args[1:-1]
+            # indirect_call with a red callable must return a red
+            # (see test_indirect_yellow_call)
+            v_callable = self.spaceop.args[0]
+            retdeps = greenorigindependencies.setdefault(self, [])
+            retdeps.append(v_callable)
         else:
             raise AssertionError(self.spaceop.opname)
 
@@ -182,11 +187,11 @@
         for o in self.origins:
             if not o.fixed:
                 return False
-        return True
+        return self.concretetype is not lltype.Void
 
     def is_green(self):
-        return (self.is_fixed() or self.eager_concrete or
-                self.concretetype is lltype.Void or
+        return (self.concretetype is lltype.Void or
+                self.is_fixed() or self.eager_concrete or
                 (self.myorigin is not None and self.myorigin.greenargs))
 
     def annotationcolor(self):
@@ -349,7 +354,7 @@
         fixed = myorigin.read_fixed()
         tsgraphs_accum = []
         hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs,
-                                              tsgraphs_accum)
+                                              tsgraphs_accum, hs_v1)
         myorigin.any_called_graph = tsgraphs_accum[0]
 
         if isinstance(hs_res, SomeLLAbstractConstant):

Modified: pypy/branch/jit-virtual-world/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/hintannotator/test/test_annotator.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/hintannotator/test/test_annotator.py	Sun Feb  4 23:12:02 2007
@@ -728,3 +728,41 @@
 
     hs = hannotate(ll_function, [int], policy=P_NOVIRTUAL)
     assert hs.deepfrozen
+
+
+def test_concrete_fnptr_for_green_call():
+
+    def h1(n):
+        return n * 10
+
+    def h2(n):
+        return n + 20
+
+    lst = [h1, h2]
+
+    def ll_function(n, m):
+        h = hint(lst, deepfreeze=True)[m]
+        res = h(n)
+        hint(res, concrete=True)   # so 'h' gets green, so 'm' gets green
+        return m
+
+    hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+    assert hs.is_green()
+
+
+def test_indirect_yellow_call():
+
+    def h1(n):
+        return 123
+
+    def h2(n):
+        return 456
+
+    lst = [h1, h2]
+
+    def ll_function(n, m):
+        h = hint(lst, deepfreeze=True)[m]
+        return h(n)
+
+    hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+    assert not hs.is_green()

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py	Sun Feb  4 23:12:02 2007
@@ -198,6 +198,7 @@
             assert self.portal_contains_global_mp, (
                 "No global merge point found.  "
                 "Forgot 'hint(None, global_merge_point=True)'?")
+        #import pdb; pdb.set_trace()
         # only keep the hint-annotated graphs that are really useful
         self.annotator.translator.graphs = [graph
             for graph in self.annotator.translator.graphs
@@ -1415,6 +1416,10 @@
     def translate_op_residual_gray_noexc_call(self, hop):
         self.translate_op_residual_red_call(hop, color='gray', exc=False)
 
+    translate_op_residual_yellow_call       = translate_op_residual_red_call
+    translate_op_residual_yellow_noexc_call = (
+                                        translate_op_residual_red_noexc_call)
+
     def translate_op_after_residual_call(self, hop):
         v_jitstate = hop.llops.getjitstate()        
         return hop.llops.genmixlevelhelpercall(rtimeshift.after_residual_call,

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_portal.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_portal.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_portal.py	Sun Feb  4 23:12:02 2007
@@ -441,3 +441,31 @@
         res = self.timeshift_from_portal(ll_main, ll_function, [5], policy=P_NOVIRTUAL)
         assert not res
 
+    def test_greenmethod_call_nonpromote(self):
+        class Base(object):
+            pass
+        class Int(Base):
+            def __init__(self, n):
+                self.n = n
+            def tag(self):
+                return 123
+        class Str(Base):
+            def __init__(self, s):
+                self.s = s
+            def tag(self):
+                return 456
+
+        def ll_main(n):
+            if n > 0:
+                o = Int(n)
+            else:
+                o = Str('123')
+            return ll_function(o)
+
+        def ll_function(o):
+            hint(None, global_merge_point=True)
+            return o.tag()
+
+        res = self.timeshift_from_portal(ll_main, ll_function, [5], policy=P_NOVIRTUAL)
+        assert res == 123
+        self.check_insns(indirect_call=1)

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py	Sun Feb  4 23:12:02 2007
@@ -1135,6 +1135,10 @@
         assert res == 42
         self.check_insns({})
 
+        res = self.timeshift(f, [0], [], policy=P_NOVIRTUAL)
+        assert res == 42
+        self.check_insns(indirect_call=0)
+
     def test_simple_red_meth(self):
         class Base(object):
             def m(self, n):

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vdict.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vdict.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vdict.py	Sun Feb  4 23:12:02 2007
@@ -1,5 +1,6 @@
 from pypy.jit.hintannotator.annotator import HintAnnotatorPolicy
 from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
+from pypy.rlib.objectmodel import hint
 
 P_OOPSPEC = HintAnnotatorPolicy(novirtualcontainer = True,
                                 oopspec = True)
@@ -40,3 +41,22 @@
         res = self.timeshift(ll_function, [], [], policy=P_OOPSPEC)
         assert res == 39
         self.check_insns({})
+
+    def test_dicts_deepfreeze(self):
+        d1 = {1: 123, 2: 54, 3:84}
+        d2 = {1: 831, 2: 32, 3:81}
+        def getdict(n):
+            if n:
+                return d1
+            else:
+                return d2
+        def ll_function(n, i):
+            d = getdict(n)
+            d = hint(d, deepfreeze=True)
+            res = d[i]
+            res = hint(res, variable=True)
+            return res
+        
+        res = self.timeshift(ll_function, [3, 2], [0, 1], policy=P_OOPSPEC)
+        assert res == 54
+        self.check_insns({})

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vlist.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vlist.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vlist.py	Sun Feb  4 23:12:02 2007
@@ -1,5 +1,6 @@
 from pypy.jit.hintannotator.annotator import HintAnnotatorPolicy
 from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
+from pypy.rlib.objectmodel import hint
 
 P_OOPSPEC = HintAnnotatorPolicy(novirtualcontainer=True, oopspec=True)
 
@@ -110,3 +111,21 @@
         assert res == 9
         self.check_insns({})
         
+    def test_lists_deepfreeze(self):
+        l1 = [1,2,3,4,5]
+        l2 = [6,7,8,9,10]
+        def getlist(n):
+            if n:
+                return l1
+            else:
+                return l2
+        def ll_function(n, i):
+            l = getlist(n)
+            l = hint(l, deepfreeze=True)
+            res = l[i]
+            res = hint(res, variable=True)
+            return res
+        
+        res = self.timeshift(ll_function, [3, 4], [0, 1], policy=P_OOPSPEC)
+        assert res == 5
+        self.check_insns({})

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py	Sun Feb  4 23:12:02 2007
@@ -553,7 +553,8 @@
             args_v = op.args[:1] + args_v + [c_targets]
             hs_func = self.hannotator.binding(args_v[0])
             if not hs_func.is_green():
-                # XXX for now, assume that it will be a constant red box
+                # handle_red_call() has checked with is_constant that
+                # the hs_func is actually a constant red box
                 v_greenfunc = self.genop(block, 'revealconst', [args_v[0]],
                                   resulttype = originalconcretetype(hs_func))
                 args_v[0] = v_greenfunc
@@ -574,8 +575,7 @@
         linkargs = link.args
         varsalive = list(linkargs)
 
-        if color == 'red':
-            assert not self.hannotator.binding(op.result).is_green()
+        if color != 'gray':
             # the result will be either passed as an extra local 0
             # by the caller, or restored by a restore_local
             try:
@@ -622,10 +622,28 @@
         blockset[postconstantblock] = False
         self.make_call(constantblock, op, reds, color)
 
-        resumepoint = self.get_resume_point(nextblock)
+        conversionblock = nextblock
+        if color == 'red':
+            assert not self.hannotator.binding(op.result).is_green()
+        elif color == 'yellow':
+            conversionblock = Block([copyvar(self.hannotator, v)
+                                     for v in nextblock.inputargs])
+            v0 = conversionblock.inputargs[0]
+            already_green = self.hannotator.binding(op.result).is_green()
+            assert already_green == self.hannotator.binding(v0).is_green()
+            if not already_green:
+                RESULT = self.hannotator.binding(v0).concretetype
+                hs = hintmodel.SomeLLAbstractConstant(RESULT, {})
+                self.hannotator.bindings[v0] = hs
+            conversionblock.closeblock(Link(conversionblock.inputargs,
+                                            nextblock))
+            # to merge some of the possibly many return jitstates
+            self.mergepoint_set[nextblock] = 'local'
+
+        resumepoint = self.get_resume_point(conversionblock)
         c_resumepoint = inputconst(lltype.Signed, resumepoint)
         self.genop(postconstantblock, 'collect_split', [c_resumepoint] + greens)
-        resumeblock = self.get_resume_point_link(nextblock).target
+        resumeblock = self.get_resume_point_link(conversionblock).target
         postconstantblock.recloseblock(Link([], resumeblock))
 
         if nonconstantblock is not None:
@@ -633,7 +651,7 @@
             v_res, nonconstantblock2 = self.handle_residual_call_details(
                                             nonconstantblock, 0, op,
                                             color, preserve_res =
-                                            (color == 'red'))
+                                            (color != 'gray'))
 
             #if color == 'red':
             #    linkargs[0] = v_res
@@ -683,55 +701,7 @@
         op.opname = 'green_call'
 
     def handle_yellow_call(self, block, pos):
-        op = block.operations[pos]
-        #if op.opname == 'direct_call':
-        #    f = open('LOG', 'a')
-        #    print >> f, 'handle_yellow_call', op.args[0].value
-        #    f.close()
-        hs_result = self.hannotator.binding(op.result)
-        if not hs_result.is_green():
-            # yellow calls are supposed to return greens,
-            # add an indirection if it's not the case
-            # XXX a bit strange
-            RESULT = originalconcretetype(hs_result)
-            v_tmp = varoftype(RESULT)
-            hs = hintmodel.SomeLLAbstractConstant(RESULT, {})
-            self.hannotator.setbinding(v_tmp, hs)
-            v_real_result = op.result
-            op.result = v_tmp
-            newop = SpaceOperation('same_as', [v_tmp], v_real_result)
-            block.operations.insert(pos+1, newop)
-
-        link = split_block(self.hannotator, block, pos+1)
-        op1 = block.operations.pop(pos)
-        assert op1 is op
-        assert len(block.operations) == pos
-        nextblock = link.target
-        varsalive = link.args
-        try:
-            index = varsalive.index(op.result)
-        except ValueError:
-            XXX-later
-
-        del varsalive[index]
-        v_result = nextblock.inputargs.pop(index)
-        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(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)
+        self.handle_red_call(block, pos, color='yellow')
 
     def handle_residual_call(self, block, pos, qualifiers=[]):
         op = block.operations[pos]        

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vlist.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vlist.py	Sun Feb  4 23:12:02 2007
@@ -288,19 +288,23 @@
     else:
         return oopspecdesc.residual_call(jitstate, [selfbox])
 
-def oop_list_len(jitstate, oopspecdesc, selfbox):
+def oop_list_len(jitstate, oopspecdesc, deepfrozen, selfbox):
     content = selfbox.content
     if isinstance(content, VirtualList):
         return rvalue.ll_fromvalue(jitstate, len(content.item_boxes))
     else:
-        return oopspecdesc.residual_call(jitstate, [selfbox])
+        return oopspecdesc.residual_call(jitstate, [selfbox],
+                                         deepfrozen=deepfrozen)
+oop_list_len.couldfold = True
 
-def oop_list_nonzero(jitstate, oopspecdesc, selfbox):
+def oop_list_nonzero(jitstate, oopspecdesc, deepfrozen, selfbox):
     content = selfbox.content
     if isinstance(content, VirtualList):
         return rvalue.ll_fromvalue(jitstate, bool(content.item_boxes))
     else:
-        return oopspecdesc.residual_call(jitstate, [selfbox])
+        return oopspecdesc.residual_call(jitstate, [selfbox],
+                                         deepfrozen=deepfrozen)
+oop_list_nonzero.couldfold = True
 
 def oop_list_append(jitstate, oopspecdesc, selfbox, itembox):
     content = selfbox.content
@@ -360,7 +364,7 @@
     else:
         oopspecdesc.residual_call(jitstate, [selfbox])
 
-def oop_list_getitem(jitstate, oopspecdesc, selfbox, indexbox):
+def oop_list_getitem(jitstate, oopspecdesc, deepfrozen, selfbox, indexbox):
     content = selfbox.content
     if isinstance(content, VirtualList) and indexbox.is_constant():
         index = rvalue.ll_getvalue(indexbox, lltype.Signed)
@@ -369,7 +373,9 @@
         except IndexError:
             return oopspecdesc.residual_exception(jitstate, IndexError)
     else:
-        return oopspecdesc.residual_call(jitstate, [selfbox, indexbox])
+        return oopspecdesc.residual_call(jitstate, [selfbox, indexbox],
+                                         deepfrozen=deepfrozen)
+oop_list_getitem.couldfold = True
 
 def oop_list_setitem(jitstate, oopspecdesc, selfbox, indexbox, itembox):
     content = selfbox.content


More information about the pypy-svn mailing list