Author: Antonio Cuni <[email protected]>
Branch: autoreds
Changeset: r58858:5a4708d22296
Date: 2012-11-13 20:38 +0100
http://bitbucket.org/pypy/pypy/changeset/5a4708d22296/

Log:    the test to show the whole point of the excercise, i.e. the
        possibility to automatically create jit portals by iterating over a
        specially-decorated RPython iterator

diff --git a/pypy/jit/metainterp/test/test_ajit.py 
b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -3123,7 +3123,34 @@
         res = self.meta_interp(f, [32])
         assert res == f(32)
 
-
+    def test_inline_in_portal(self):
+        myjitdriver = JitDriver(greens = [], reds = 'auto')
+        class MyRange(object):
+            def __init__(self, n):
+                self.cur = 0
+                self.n = n
+
+            def __iter__(self):
+                return self
+
+            @myjitdriver.inline_in_portal
+            def next(self):
+                myjitdriver.jit_merge_point()
+                if self.cur == self.n:
+                    raise StopIteration
+                self.cur += 1
+                return self.cur
+
+        def f(n, m):
+            res = 0
+            for i in MyRange(100):
+                res += i
+            return res
+        expected = f(21, 5)
+        res = self.meta_interp(f, [21, 5])
+        assert res == expected
+        self.check_resops(int_eq=2, int_add=4)
+        
 class XXXDisabledTestOOtype(BasicTests, OOJitMixin):
 
     def test_oohash(self):
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -186,6 +186,7 @@
         self.set_translator(translator)
         self.memory_manager = memmgr.MemoryManager()
         self.build_cpu(CPUClass, **kwds)
+        self.inline_inlineable_portals()
         self.find_portals()
         self.codewriter = codewriter.CodeWriter(self.cpu, self.jitdrivers_sd)
         if policy is None:
@@ -241,6 +242,46 @@
         self.rtyper = translator.rtyper
         self.gcdescr = gc.get_description(translator.config)
 
+    def inline_inlineable_portals(self):
+        """
+        Find all the graphs which have been decorated with
+        @jitdriver.inline_in_portal and inline them in the callers, making
+        them JIT portals. Then, create a fresh copy of the jitdriver for each
+        of those new portals, because they cannot share the same one.  See
+        test_ajit::test_inline_in_portal.
+        """
+        from pypy.translator.backendopt import inline
+        lltype_to_classdef = 
self.translator.rtyper.lltype_to_classdef_mapping()
+        raise_analyzer = inline.RaiseAnalyzer(self.translator)
+        callgraph = inline.inlinable_static_callers(self.translator.graphs)
+        new_portals = set()
+        for caller, callee in callgraph:
+            func = getattr(callee, 'func', None)
+            _inline_in_portal_ = getattr(func, '_inline_in_portal_', True)
+            if _inline_in_portal_:
+                count = inline.inline_function(self.translator, callee, caller,
+                                               lltype_to_classdef, 
raise_analyzer)
+                assert count > 0, ('The function has been decorated with '
+                                   '@inline_in_portal, but it is not possible '
+                                   'to inline it')
+                new_portals.add(caller)
+        self.clone_inlined_jit_merge_points(new_portals)
+
+    def clone_inlined_jit_merge_points(self, graphs):
+        """
+        Find all the jit_merge_points in the given graphs, and replace the
+        original JitDriver with a fresh clone.
+        """
+        if not graphs:
+            return
+        for graph, block, pos in find_jit_merge_points(graphs):
+            op = block.operations[pos]
+            v_driver = op.args[1]
+            new_driver = v_driver.value.clone()
+            c_new_driver = Constant(new_driver, v_driver.concretetype)
+            op.args[1] = c_new_driver
+
+
     def find_portals(self):
         self.jitdrivers_sd = []
         graphs = self.translator.graphs
@@ -294,7 +335,13 @@
         jd._jit_merge_point_in = graph
         args = op.args[2:]
         s_binding = self.translator.annotator.binding
-        jd._portal_args_s = [s_binding(v) for v in args]
+        if op.args[1].value.autoreds:
+            # _portal_args_s is used only by _make_hook_graph, but for now we
+            # declare the various set_jitcell_at, get_printable_location,
+            # etc. as incompatible with autoreds
+            jd._portal_args_s = None
+        else:
+            jd._portal_args_s = [s_binding(v) for v in args]
         graph = copygraph(graph)
         [jmpp] = find_jit_merge_points([graph])
         graph.startblock = support.split_before_jit_merge_point(*jmpp)
@@ -546,6 +593,7 @@
         if func is None:
             return None
         #
+        assert not jitdriver_sd.jitdriver.autoreds
         extra_args_s = []
         if s_first_arg is not None:
             extra_args_s.append(s_first_arg)
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -443,6 +443,7 @@
     active = True          # if set to False, this JitDriver is ignored
     virtualizables = []
     name = 'jitdriver'
+    inlined_in_portal = False
 
     def __init__(self, greens=None, reds=None, virtualizables=None,
                  get_jitcell_at=None, set_jitcell_at=None,
@@ -547,6 +548,18 @@
         # special-cased by ExtRegistryEntry
         pass
 
+    def inline_in_portal(self, func):
+        assert self.autoreds, "inline_in_portal works only with reds='auto'"
+        func._inline_in_portal_ = True
+        self.inlined_in_portal = True
+        return func
+
+    def clone(self):
+        assert self.inlined_in_portal, 'JitDriver.clone works only after 
@inline_in_portal'
+        newdriver = object.__new__(self.__class__)
+        newdriver.__dict__ = self.__dict__.copy()
+        return newdriver
+
     def _make_extregistryentries(self):
         # workaround: we cannot declare ExtRegistryEntries for functions
         # used as methods of a frozen object, but we can attach the
diff --git a/pypy/rlib/test/test_jit.py b/pypy/rlib/test/test_jit.py
--- a/pypy/rlib/test/test_jit.py
+++ b/pypy/rlib/test/test_jit.py
@@ -23,7 +23,24 @@
     py.test.raises(TypeError, "driver.can_enter_jit(foo='something')")
     #
     py.test.raises(AssertionError, "JitDriver(greens=['foo'], reds='auto', 
confirm_enter_jit='something')")
-    
+
+def test_jitdriver_clone():
+    def foo():
+        pass
+    driver = JitDriver(greens=[], reds=[])
+    py.test.raises(AssertionError, "driver.inline_in_portal(foo)")
+    #
+    driver = JitDriver(greens=[], reds='auto')
+    py.test.raises(AssertionError, "driver.clone()")
+    foo = driver.inline_in_portal(foo)
+    assert foo._inline_in_portal_ == True
+    #
+    driver.foo = 'bar'
+    driver2 = driver.clone()
+    assert driver is not driver2
+    assert driver2.foo == 'bar'
+    driver.foo = 'xxx'
+    assert driver2.foo == 'bar'
     
 
 class BaseTestJIT(BaseRtypingTest):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to