[pypy-svn] r74457 - in pypy/branch/blackhole-improvement/pypy: jit/codewriter jit/codewriter/test objspace/flow

arigo at codespeak.net arigo at codespeak.net
Mon May 10 11:56:52 CEST 2010


Author: arigo
Date: Mon May 10 11:56:50 2010
New Revision: 74457

Added:
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py
      - copied, changed from r74453, pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitter.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py
      - copied, changed from r74453, pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jitter.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_policy.py   (contents, props changed)
Removed:
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitter.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jitter.py
Modified:
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/support.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_call.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py
   pypy/branch/blackhole-improvement/pypy/objspace/flow/model.py
Log:
Rename 'jitter' into 'jtransform'.  Add policy tests.


Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py	Mon May 10 11:56:50 2010
@@ -13,14 +13,24 @@
         self.insns = {}
         self.descrs = []
         self._descr_dict = {}
+        self._count_jitcodes = 0
 
-    def assemble(self, ssarepr):
+    def assemble(self, ssarepr, jitcode=None):
+        """Take the 'ssarepr' representation of the code and assemble
+        it inside the 'jitcode'.  If jitcode is None, make a new one.
+        """
         self.setup()
         for insn in ssarepr.insns:
             self.write_insn(insn)
         self.fix_labels()
         self.check_result()
-        return self.make_jitcode(ssarepr)
+        if jitcode is None:
+            jitcode = JitCode(ssarepr.name)
+        self.make_jitcode(jitcode)
+        if self._count_jitcodes < 20:    # stop if we have a lot of them
+            jitcode._dump = format_assembler(ssarepr)
+        self._count_jitcodes += 1
+        return jitcode
 
     def setup(self):
         self.code = []
@@ -163,8 +173,7 @@
         assert self.count_regs['ref'] + len(self.constants_r) <= 256
         assert self.count_regs['float'] + len(self.constants_f) <= 256
 
-    def make_jitcode(self, ssarepr):
-        jitcode = JitCode(ssarepr.name, assembler=self)
+    def make_jitcode(self, jitcode):
         jitcode.setup(''.join(self.code),
                       self.constants_i,
                       self.constants_r,
@@ -172,8 +181,5 @@
                       self.count_regs['int'],
                       self.count_regs['ref'],
                       self.count_regs['float'],
-                      liveness=self.liveness)
-        #if self._count_jitcodes < 50:    # stop if we have a lot of them
-        #    jitcode._dump = format_assembler(ssarepr)
-        #self._count_jitcodes += 1
-        return jitcode
+                      liveness=self.liveness,
+                      assembler=self)

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py	Mon May 10 11:56:50 2010
@@ -5,19 +5,23 @@
 
 from pypy.jit.codewriter import support
 from pypy.translator.simplify import get_funcobj
+from pypy.jit.codewriter.jitcode import JitCode
 
 
 class CallControl(object):
 
-    def __init__(self, rtyper=None, portal_runner_obj=None):
+    def __init__(self, rtyper=None, portal_graph=None):
         self.rtyper = rtyper
-        self.portal_runner_obj = portal_runner_obj
+        self.portal_graph = portal_graph
+        self.jitcodes = {}             # map {graph: jitcode}
+        self.unfinished_graphs = []    # list of graphs with pending jitcodes
 
-    def find_all_graphs(self, portal_graph, policy):
+    def find_all_graphs(self, policy):
         def is_candidate(graph):
             return policy.look_inside_graph(graph)
-        
-        todo = [portal_graph]
+
+        assert self.portal_graph is not None
+        todo = [self.portal_graph]
         candidate_graphs = set(todo)
 
         def callers():
@@ -94,9 +98,9 @@
             funcobj = get_funcobj(funcptr)
             if getattr(funcobj, 'graph', None) is None:
                 return 'residual'
-            if funcobj is self.portal_runner_obj:
-                return 'recursive'
             targetgraph = funcobj.graph
+            if targetgraph is self.portal_graph:
+                return 'recursive'
             if (hasattr(targetgraph, 'func') and
                 hasattr(targetgraph.func, 'oopspec')):
                 return 'builtin'
@@ -111,3 +115,18 @@
     def is_candidate(self, graph):
         # used only after find_all_graphs()
         return graph in self.candidate_graphs
+
+    def enum_pending_graphs(self):
+        while self.unfinished_graphs:
+            graph = self.unfinished_graphs.pop()
+            yield graph, self.jitcodes[graph]
+
+    def get_jitcode(self, graph, called_from=None):
+        # 'called_from' is only one of the callers, used for debugging.
+        try:
+            return self.jitcodes[graph]
+        except KeyError:
+            jitcode = JitCode(graph.name, called_from=called_from)
+            self.jitcodes[graph] = jitcode
+            self.unfinished_graphs.append(graph)
+            return jitcode

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py	Mon May 10 11:56:50 2010
@@ -2,14 +2,17 @@
 from pypy.jit.codewriter.regalloc import perform_register_allocation
 from pypy.jit.codewriter.flatten import flatten_graph, KINDS
 from pypy.jit.codewriter.assembler import Assembler, JitCode
-from pypy.jit.codewriter.jitter import transform_graph
+from pypy.jit.codewriter.jtransform import transform_graph
 from pypy.jit.codewriter.format import format_assembler
 from pypy.jit.codewriter.liveness import compute_liveness
+from pypy.jit.codewriter.call import CallControl
 from pypy.jit.codewriter.policy import log
+from pypy.objspace.flow.model import copygraph
 from pypy.tool.udir import udir
 
 
 class CodeWriter(object):
+    callcontrol = None    # for tests
 
     def __init__(self, cpu=None):
         self.cpu = cpu
@@ -19,17 +22,19 @@
         """For testing."""
         rtyper = support.annotate(func, values, type_system=type_system)
         graph = rtyper.annotator.translator.graphs[0]
-        return self.transform_graph_to_jitcode(graph, True, True)
+        jitcode = JitCode("test")
+        self.transform_graph_to_jitcode(graph, jitcode, True, True)
+        return jitcode
 
-    def transform_graph_to_jitcode(self, graph, portal, verbose):
+    def transform_graph_to_jitcode(self, graph, jitcode, portal, verbose):
         """Transform a graph into a JitCode containing the same bytecode
-        in a different format.  Note that the original 'graph' is mangled
-        by the process and should not be used any more.
+        in a different format.
         """
+        graph = copygraph(graph, shallowvars=True)
         #
         # step 1: mangle the graph so that it contains the final instructions
         # that we want in the JitCode, but still as a control flow graph
-        transform_graph(graph, self.cpu, portal)
+        transform_graph(graph, self.cpu, self.callcontrol, portal)
         #
         # step 2a: perform register allocation on it
         regallocs = {}
@@ -52,12 +57,16 @@
         # of bytes and lists of constants.  It's during this step that
         # constants are cast to their normalized type (Signed, GCREF or
         # Float).
-        jitcode = self.assembler.assemble(ssarepr)
-        return jitcode
+        self.assembler.assemble(ssarepr, jitcode)
 
-    def make_jitcodes(self, maingraph, verbose=False):
-        self.portal_graph = maingraph
-        return self.transform_graph_to_jitcode(maingraph, True, verbose)
+    def make_jitcodes(self, maingraph, policy, verbose=False):
+        self.callcontrol = CallControl(self.cpu.rtyper, maingraph)
+        self.callcontrol.find_all_graphs(policy)
+        mainjitcode = self.callcontrol.get_jitcode(maingraph)
+        for graph, jitcode in self.callcontrol.enum_pending_graphs():
+            self.transform_graph_to_jitcode(graph, jitcode,
+                                            graph is maingraph, verbose)
+        return mainjitcode
 
     def print_ssa_repr(self, ssarepr, portal, verbose):
         if verbose:

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py	Mon May 10 11:56:50 2010
@@ -1,23 +1,21 @@
-from pypy.jit.metainterp.history import AbstractValue, AbstractDescr
+from pypy.jit.metainterp.history import AbstractDescr
 from pypy.rlib.objectmodel import we_are_translated
 
 
-class JitCode(AbstractValue):
+class JitCode(AbstractDescr):
     _empty_i = []
     _empty_r = []
     _empty_f = []
 
-    def __init__(self, name, fnaddr=None, calldescr=None, called_from=None,
-                 assembler=None):
+    def __init__(self, name, fnaddr=None, calldescr=None, called_from=None):
         self.name = name
         self.fnaddr = fnaddr
         self.calldescr = calldescr
         self._called_from = called_from   # debugging
-        self._assembler = assembler       # debugging
 
     def setup(self, code='', constants_i=[], constants_r=[], constants_f=[],
               num_regs_i=256, num_regs_r=256, num_regs_f=256,
-              liveness=None):
+              liveness=None, assembler=None):
         self.code = code
         # if the following lists are empty, use a single shared empty list
         self.constants_i = constants_i or self._empty_i
@@ -28,6 +26,7 @@
                                  (num_regs_r << 9) |
                                  (num_regs_f << 0))
         self.liveness = liveness
+        self._assembler = assembler       # debugging
 
     def num_regs_i(self):
         return self.num_regs_encoded >> 18
@@ -98,6 +97,13 @@
         raise KeyError("missing liveness[%d], corresponding to %r" % (
             pc, insn))
 
+    def __repr__(self):
+        return '<JitCode %r>' % self.name
+
 
 class SwitchDictDescr(AbstractDescr):
     "Get a 'dict' attribute mapping integer values to bytecode positions."
+
+    def __repr__(self):
+        dict = getattr(self, 'dict', '?')
+        return '<SwitchDictDescr %s>' % (dict,)

Copied: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py (from r74453, pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitter.py)
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitter.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py	Mon May 10 11:56:50 2010
@@ -7,11 +7,11 @@
 from pypy.jit.codewriter import support, heaptracker
 
 
-def transform_graph(graph, cpu=None, portal=True):
+def transform_graph(graph, cpu=None, callcontrol=None, portal=True):
     """Transform a control flow graph to make it suitable for
     being flattened in a JitCode.
     """
-    t = Transformer(cpu)
+    t = Transformer(cpu, callcontrol)
     t.transform(graph, portal)
 
 
@@ -21,8 +21,9 @@
 
 class Transformer(object):
 
-    def __init__(self, cpu=None):
+    def __init__(self, cpu=None, callcontrol=None):
         self.cpu = cpu
+        self.callcontrol = callcontrol
 
     def transform(self, graph, portal):
         self.graph = graph
@@ -173,10 +174,21 @@
     rewrite_op_float_gt  = _rewrite_symmetric
     rewrite_op_float_ge  = _rewrite_symmetric
 
+    # ----------
+    # Various kinds of calls
+
     def rewrite_op_direct_call(self, op):
+        kind = self.callcontrol.guess_call_kind(op)
+        return getattr(self, 'handle_%s_call' % kind)(op)
+
+    def rewrite_op_indirect_call(self, op):
+        kind = self.callcontrol.guess_call_kind(op)
+        return getattr(self, 'handle_%s_indirect_call' % kind)(op)
+
+    def rewrite_call(self, op, namebase, initialargs):
         """Turn 'i0 = direct_call(fn, i1, i2, ref1, ref2)'
-           into e.g. 'i0 = residual_call_ir_i(fn, [i1, i2], [ref1, ref2])'.
-           The name is one of 'residual_call_{r,ir,irf}_{i,r,f,v}'."""
+           into 'i0 = xxx_call_ir_i(fn, descr, [i1,i2], [ref1,ref2])'.
+           The name is one of '{residual,direct}_call_{r,ir,irf}_{i,r,f,v}'."""
         args_i = []
         args_r = []
         args_f = []
@@ -190,16 +202,8 @@
         if 'r' in kinds: sublists.append(ListOfKind('ref', args_r))
         if 'f' in kinds: sublists.append(ListOfKind('float', args_f))
         reskind = getkind(op.result.concretetype)[0]
-        FUNC = op.args[0].concretetype.TO
-        NONVOIDARGS = tuple([ARG for ARG in FUNC.ARGS if ARG != lltype.Void])
-        calldescr = self.cpu.calldescrof(FUNC, NONVOIDARGS, FUNC.RESULT)
-        return SpaceOperation('G_residual_call_%s_%s' % (kinds, reskind),
-                              [op.args[0], calldescr] + sublists,
-                              op.result)
-
-    def rewrite_op_indirect_call(self, op):
-        op1 = SpaceOperation('direct_call', op.args[:-1], op.result)
-        return self.rewrite_op_direct_call(op1)
+        return SpaceOperation('G_%s_call_%s_%s' % (namebase, kinds, reskind),
+                              initialargs + sublists, op.result)
 
     def add_in_correct_list(self, v, lst_i, lst_r, lst_f):
         kind = getkind(v.concretetype)
@@ -210,6 +214,25 @@
         else: raise AssertionError(kind)
         lst.append(v)
 
+    def handle_residual_call(self, op):
+        """A direct_call turns into the operation 'residual_call_xxx' if it
+        is calling a function that we don't want to JIT.  The initial args
+        of 'residual_call_xxx' are the constant function to call, and its
+        calldescr."""
+        FUNC = op.args[0].concretetype.TO
+        NONVOIDARGS = tuple([ARG for ARG in FUNC.ARGS if ARG != lltype.Void])
+        calldescr = self.cpu.calldescrof(FUNC, NONVOIDARGS, FUNC.RESULT)
+        return self.rewrite_call(op, 'residual', [op.args[0], calldescr])
+
+    def handle_regular_call(self, op):
+        """A direct_call turns into the operation 'inline_call_xxx' if it
+        is calling a function that we want to JIT.  The initial arg of
+        'inline_call_xxx' is the JitCode of the called function."""
+        [targetgraph] = self.callcontrol.graphs_from(op)
+        jitcode = self.callcontrol.get_jitcode(targetgraph,
+                                               called_from=self.graph)
+        return self.rewrite_call(op, 'inline', [jitcode])
+
     def _do_builtin_call(self, op, oopspec_name=None, args=None, extra=None):
         if oopspec_name is None: oopspec_name = op.opname
         if args is None: args = op.args
@@ -230,6 +253,9 @@
     rewrite_op_int_lshift_ovf  = _do_builtin_call
     rewrite_op_gc_identityhash = _do_builtin_call
 
+    # ----------
+    # getfield/setfield/mallocs etc.
+
     def rewrite_op_hint(self, op):
         hints = op.args[1].value
         if hints.get('promote') and op.args[0].concretetype is not lltype.Void:

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/support.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/support.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/support.py	Mon May 10 11:56:50 2010
@@ -55,6 +55,10 @@
     #    t.view()
     return rtyper
 
+def getgraph(func, values):
+    rtyper = annotate(func, values)
+    return rtyper.annotator.translator.graphs[0]
+
 def split_before_jit_merge_point(graph, portalblock, portalopindex):
     """Find the block with 'jit_merge_point' and split just before,
     making sure the input args are in the canonical order.

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_call.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_call.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_call.py	Mon May 10 11:56:50 2010
@@ -4,7 +4,10 @@
 from pypy.rlib import jit
 from pypy.jit.codewriter.call import CallControl
 from pypy.jit.codewriter import support
-from pypy.jit.codewriter.policy import JitPolicy
+
+class FakePolicy:
+    def look_inside_graph(self, graph):
+        return True
 
 
 def test_graphs_from_direct_call():
@@ -49,106 +52,30 @@
 # ____________________________________________________________
 
 def test_find_all_graphs():
-    def f(x):
-        if x < 0:
-            return f(-x)
-        return x + 1
-    @jit.purefunction
     def g(x):
         return x + 2
-    @jit.dont_look_inside
-    def h(x):
-        return x + 3
-    def i(x):
-        return f(x) * g(x) * h(x)
-
-    rtyper = support.annotate(i, [7])
-    cc = CallControl()
-    jitpolicy = JitPolicy()
-    res = cc.find_all_graphs(rtyper.annotator.translator.graphs[0],
-                             jitpolicy)
-    translator = rtyper.annotator.translator
-
-    funcs = set([graph.func for graph in res])
-    assert funcs == set([i, f])
-
-def test_find_all_graphs_without_floats():
-    def g(x):
-        return int(x * 12.5)
     def f(x):
         return g(x) + 1
     rtyper = support.annotate(f, [7])
-    cc = CallControl()
-    jitpolicy = JitPolicy()
-    jitpolicy.set_supports_floats(True)
-    translator = rtyper.annotator.translator
-    res = cc.find_all_graphs(translator.graphs[0], jitpolicy)
+    cc = CallControl(portal_graph=rtyper.annotator.translator.graphs[0])
+    res = cc.find_all_graphs(FakePolicy())
     funcs = set([graph.func for graph in res])
     assert funcs == set([f, g])
 
-    cc = CallControl()
-    jitpolicy.set_supports_floats(False)
-    res = cc.find_all_graphs(translator.graphs[0], jitpolicy)
-    funcs = [graph.func for graph in res]
-    assert funcs == [f]
-
-def test_find_all_graphs_loops():
+def test_find_all_graphs_without_g():
     def g(x):
-        i = 0
-        while i < x:
-            i += 1
-        return i
-    @jit.unroll_safe
-    def h(x):
-        i = 0
-        while i < x:
-            i += 1
-        return i
-
+        return x + 2
     def f(x):
-        i = 0
-        while i < x*x:
-            i += g(x) + h(x)
-        return i
-
+        return g(x) + 1
     rtyper = support.annotate(f, [7])
-    cc = CallControl()
-    jitpolicy = JitPolicy()
-    translator = rtyper.annotator.translator
-    res = cc.find_all_graphs(translator.graphs[0], jitpolicy)
-    funcs = set([graph.func for graph in res])
-    assert funcs == set([f, h])
-
-def test_unroll_safe_and_inline():
-    @jit.unroll_safe
-    def h(x):
-        i = 0
-        while i < x:
-            i += 1
-        return i
-    h._always_inline_ = True
-
-    def g(x):
-        return h(x)
-
-    rtyper = support.annotate(g, [7])
-    cc = CallControl()
-    jitpolicy = JitPolicy()
-    translator = rtyper.annotator.translator
-    res = cc.find_all_graphs(translator.graphs[0], jitpolicy)
-    funcs = set([graph.func for graph in res])
-    assert funcs == set([g, h])
-
-def test_find_all_graphs_str_join():
-    def i(x, y):
-        return "hello".join([str(x), str(y), "bye"])
-
-    rtyper = support.annotate(i, [7, 100])
-    cc = CallControl()
-    jitpolicy = JitPolicy()
-    translator = rtyper.annotator.translator
-    # does not explode
-    cc.find_all_graphs(translator.graphs[0], jitpolicy)
+    cc = CallControl(portal_graph=rtyper.annotator.translator.graphs[0])
+    class CustomFakePolicy:
+        def look_inside_graph(self, graph):
+            assert graph.name == 'g'
+            return False
+    res = cc.find_all_graphs(CustomFakePolicy())
+    funcs = [graph.func for graph in res]
+    assert funcs == [f]
 
 # ____________________________________________________________
 
@@ -157,7 +84,7 @@
         graph = object()
     g = object()
     g1 = object()
-    cc = CallControl(portal_runner_obj=portal_runner_obj)
+    cc = CallControl(portal_graph=portal_runner_obj.graph)
     cc.candidate_graphs = [g, g1]
 
     op = SpaceOperation('direct_call', [Constant(portal_runner_obj)],
@@ -206,3 +133,15 @@
     res = cc.graphs_from(op)
     assert res is None
     assert cc.guess_call_kind(op) == 'residual'        
+
+# ____________________________________________________________
+
+def test_get_jitcode():
+    cc = CallControl()
+    class somegraph:
+        name = "foo"
+    jitcode = cc.get_jitcode(somegraph)
+    assert jitcode is cc.get_jitcode(somegraph)    # caching
+    assert jitcode.name == "foo"
+    pending = list(cc.enum_pending_graphs())
+    assert pending == [(somegraph, jitcode)]

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py	Mon May 10 11:56:50 2010
@@ -1,5 +1,13 @@
 import py
 from pypy.jit.codewriter.codewriter import CodeWriter
+from pypy.jit.codewriter import support
+
+class FakeCPU:
+    rtyper = None
+
+class FakePolicy:
+    def look_inside_graph(self, graph):
+        return True
 
 
 def test_loop():
@@ -27,6 +35,23 @@
     for i in range(1, len(jitcode.code)):
         py.test.raises(KeyError, jitcode._live_vars, i)
 
+def test_call():
+    def ggg(x):
+        return x * 2
+    def fff(a, b):
+        return ggg(b) - ggg(a)
+    rtyper = support.annotate(fff, [35, 42])
+    maingraph = rtyper.annotator.translator.graphs[0]
+    cw = CodeWriter(FakeCPU())
+    jitcode = cw.make_jitcodes(maingraph, FakePolicy(), verbose=True)
+    print jitcode._dump
+    [jitcode2] = cw.assembler.descrs
+    print jitcode2._dump
+    assert jitcode is not jitcode2
+    assert jitcode.name == 'fff'
+    assert jitcode2.name == 'ggg'
+    assert 'ggg' in jitcode._dump
+
 def test_integration():
     from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
     def f(a, b):

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py	Mon May 10 11:56:50 2010
@@ -43,6 +43,10 @@
     def fielddescrof(self, STRUCT, name):
         return FakeDescr()
 
+class FakePolicy:
+    def guess_call_kind(self, op):
+        return 'residual'
+
 def fake_regallocs():
     return {'int': FakeRegAlloc(),
             'ref': FakeRegAlloc(),
@@ -76,8 +80,8 @@
                       transform=False, liveness=False):
         graphs = self.make_graphs(func, args)
         if transform:
-            from pypy.jit.codewriter.jitter import transform_graph
-            transform_graph(graphs[0], FakeCPU())
+            from pypy.jit.codewriter.jtransform import transform_graph
+            transform_graph(graphs[0], FakeCPU(), FakePolicy())
         if liveness:
             from pypy.jit.codewriter.liveness import compute_liveness
             compute_liveness(graphs[0])

Copied: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py (from r74453, pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jitter.py)
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jitter.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_jtransform.py	Mon May 10 11:56:50 2010
@@ -1,7 +1,7 @@
 import random
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
-from pypy.jit.codewriter.jitter import Transformer
+from pypy.jit.codewriter.jtransform import Transformer
 from pypy.jit.metainterp.history import getkind
 from pypy.rpython.lltypesystem import lltype, rclass, rstr
 from pypy.translator.unsimplify import varoftype
@@ -27,6 +27,20 @@
     def __init__(self, exitcase):
         self.exitcase = self.llexitcase = exitcase
 
+class FakeResidualCallControl:
+    def guess_call_kind(self, op):
+        return 'residual'
+
+class FakeRegularCallControl:
+    def guess_call_kind(self, op):
+        return 'regular'
+    def graphs_from(self, op):
+        return ['somegraph']
+    def get_jitcode(self, graph, called_from=None):
+        assert graph == 'somegraph'
+        return 'somejitcode'
+
+
 def test_optimize_goto_if_not():
     v1 = Variable()
     v2 = Variable()
@@ -127,7 +141,7 @@
                     assert op1.result == v3
                     assert op1.opname == name2[0]
 
-def test_residual_call():
+def test_calls():
     for RESTYPE in [lltype.Signed, rclass.OBJECTPTR,
                     lltype.Float, lltype.Void]:
       for with_void in [False, True]:
@@ -144,6 +158,7 @@
               elif with_i: expectedkind = 'ir'  # integers and references
               else: expectedkind = 'r'          # only references
               yield residual_call_test, ARGS, RESTYPE, expectedkind
+              yield direct_call_test, ARGS, RESTYPE, expectedkind
 
 def get_direct_call_op(argtypes, restype):
     FUNC = lltype.FuncType(argtypes, restype)
@@ -156,7 +171,8 @@
 
 def residual_call_test(argtypes, restype, expectedkind):
     op = get_direct_call_op(argtypes, restype)
-    op1 = Transformer(FakeCPU()).rewrite_operation(op)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op1 = tr.rewrite_operation(op)
     reskind = getkind(restype)[0]
     assert op1.opname == 'G_residual_call_%s_%s' % (expectedkind, reskind)
     assert op1.result == op.result
@@ -173,6 +189,24 @@
         kind = getkind(v.concretetype)
         assert kind == 'void' or kind[0] in expectedkind
 
+def direct_call_test(argtypes, restype, expectedkind):
+    op = get_direct_call_op(argtypes, restype)
+    tr = Transformer(FakeCPU(), FakeRegularCallControl())
+    tr.graph = 'someinitialgraph'
+    op1 = tr.rewrite_operation(op)
+    reskind = getkind(restype)[0]
+    assert op1.opname == 'G_inline_call_%s_%s' % (expectedkind, reskind)
+    assert op1.result == op.result
+    assert op1.args[0] == 'somejitcode'
+    assert len(op1.args) == 1 + len(expectedkind)
+    for sublist, kind1 in zip(op1.args[1:], expectedkind):
+        assert sublist.kind.startswith(kind1)
+        assert list(sublist) == [v for v in op.args[1:]
+                                 if getkind(v.concretetype) == sublist.kind]
+    for v in op.args[1:]:
+        kind = getkind(v.concretetype)
+        assert kind == 'void' or kind[0] in expectedkind
+
 def test_getfield():
     # XXX a more compact encoding would be possible, something along
     # the lines of  getfield_gc_r %r0, $offset, %r1
@@ -272,7 +306,8 @@
     v = varoftype(lltype.Ptr(S))
     op = SpaceOperation('malloc', [Constant(S, lltype.Void),
                                    Constant({'flavor': 'gc'}, lltype.Void)], v)
-    op1 = Transformer(FakeCPU()).rewrite_operation(op)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op1 = tr.rewrite_operation(op)
     assert op1.opname == 'G_residual_call_r_r'
     assert op1.args[0].value == 'alloc_with_del'    # pseudo-function as a str
     assert list(op1.args[2]) == []

Added: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_policy.py
==============================================================================
--- (empty file)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_policy.py	Mon May 10 11:56:50 2010
@@ -0,0 +1,98 @@
+from pypy.jit.codewriter.policy import contains_unsupported_variable_type
+from pypy.jit.codewriter.policy import JitPolicy
+from pypy.jit.codewriter import support
+from pypy.rlib.rarithmetic import r_singlefloat
+from pypy.rlib import jit
+
+def test_contains_unsupported_variable_type():
+    def f(x):
+        return x
+    graph = support.getgraph(f, [5])
+    assert not contains_unsupported_variable_type(graph, True)
+    assert not contains_unsupported_variable_type(graph, False)
+    #
+    graph = support.getgraph(f, [5.5])
+    assert not contains_unsupported_variable_type(graph, True)
+    assert contains_unsupported_variable_type(graph, False)
+    #
+    graph = support.getgraph(f, [r_singlefloat(5.5)])
+    assert contains_unsupported_variable_type(graph, True)
+    assert contains_unsupported_variable_type(graph, False)
+
+
+def test_regular_function():
+    graph = support.getgraph(lambda x: x+3, [5])
+    assert JitPolicy().look_inside_graph(graph)
+
+def test_without_floats():
+    graph = support.getgraph(lambda x: x+3.2, [5.4])
+    policy = JitPolicy()
+    policy.set_supports_floats(True)
+    assert policy.look_inside_graph(graph)
+    policy = JitPolicy()
+    policy.set_supports_floats(False)
+    assert not policy.look_inside_graph(graph)
+
+def test_purefunction():
+    @jit.purefunction
+    def g(x):
+        return x + 2
+    graph = support.getgraph(g, [5])
+    assert not JitPolicy().look_inside_graph(graph)
+
+def test_dont_look_inside():
+    @jit.dont_look_inside
+    def h(x):
+        return x + 3
+    graph = support.getgraph(h, [5])
+    assert not JitPolicy().look_inside_graph(graph)
+
+def test_loops():
+    def g(x):
+        i = 0
+        while i < x:
+            i += 1
+        return i
+    graph = support.getgraph(g, [5])
+    assert not JitPolicy().look_inside_graph(graph)
+
+def test_unroll_safe():
+    @jit.unroll_safe
+    def h(x):
+        i = 0
+        while i < x:
+            i += 1
+        return i
+    graph = support.getgraph(h, [5])
+    assert JitPolicy().look_inside_graph(graph)
+
+def test_unroll_safe_and_inline():
+    @jit.unroll_safe
+    def h(x):
+        i = 0
+        while i < x:
+            i += 1
+        return i
+    h._always_inline_ = True
+
+    def g(x):
+        return h(x)
+
+    graph = support.getgraph(h, [5])
+    assert JitPolicy().look_inside_graph(graph)
+
+def test_str_join():
+    def f(x, y):
+        return "hello".join([str(x), str(y), "bye"])
+
+    graph = support.getgraph(f, [5, 83])
+    for block in graph.iterblocks():
+        for op in block.operations:
+            if op.opname == 'direct_call':
+                funcptr = op.args[0].value
+                called_graph = funcptr._obj.graph
+                if JitPolicy().look_inside_graph(called_graph):
+                    # the calls to join() and str() should be residual
+                    mod = called_graph.func.__module__
+                    assert (mod == 'pypy.rpython.rlist' or
+                            mod == 'pypy.rpython.lltypesystem.rlist')

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_regalloc.py	Mon May 10 11:56:50 2010
@@ -3,7 +3,6 @@
 from pypy.jit.codewriter.regalloc import perform_register_allocation
 from pypy.jit.codewriter.flatten import flatten_graph, ListOfKind
 from pypy.jit.codewriter.format import format_assembler
-from pypy.jit.codewriter.jitter import transform_graph
 from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
 from pypy.objspace.flow.model import c_last_exception
@@ -22,6 +21,7 @@
         # graphs must first be transformed by jitter.py before they can be
         # subjected to register allocation and flattening.
         if transform:
+            from pypy.jit.codewriter.jtransform import transform_graph
             transform_graph(graph)
         regalloc = perform_register_allocation(graph, 'int')
         ssarepr = flatten_graph(graph, {'int': regalloc})

Modified: pypy/branch/blackhole-improvement/pypy/objspace/flow/model.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/objspace/flow/model.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/objspace/flow/model.py	Mon May 10 11:56:50 2010
@@ -414,13 +414,14 @@
         lst.append(link)
     return result
 
-def copygraph(graph, shallow=False, varmap={}):
+def copygraph(graph, shallow=False, varmap={}, shallowvars=False):
     "Make a copy of a flow graph."
     blockmap = {}
     varmap = varmap.copy()
+    shallowvars = shallowvars or shallow
 
     def copyvar(v):
-        if shallow:
+        if shallowvars:
             return v
         try:
             return varmap[v]



More information about the Pypy-commit mailing list