[pypy-svn] r69037 - in pypy/branch/jit-less-inlining/pypy/jit/metainterp: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Fri Nov 6 16:25:55 CET 2009


Author: cfbolz
Date: Fri Nov  6 16:25:53 2009
New Revision: 69037

Modified:
   pypy/branch/jit-less-inlining/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_pyjitpl.py
   pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_recursive.py
   pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py
   pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmstate.py
Log:
(pedronis, cfbolz, antocuni): If we abort due to a too long trace, we mark the
longest function as non-inlinable.


Modified: pypy/branch/jit-less-inlining/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/jit-less-inlining/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/jit-less-inlining/pypy/jit/metainterp/pyjitpl.py	Fri Nov  6 16:25:53 2009
@@ -648,7 +648,7 @@
             portal_code = self.metainterp.staticdata.portal_code
             greenkey = varargs[1:num_green_args + 1]
             if warmrunnerstate.can_inline_callable(greenkey):
-                return self.perform_call(portal_code, varargs[1:])
+                return self.perform_call(portal_code, varargs[1:], greenkey)
         return self.execute_varargs(rop.CALL, varargs, descr=calldescr, exc=True)
 
     @arguments("descr", "varargs")
@@ -1129,6 +1129,7 @@
         self.staticdata = staticdata
         self.cpu = staticdata.cpu
         self.portal_trace_positions = []
+        self.greenkey_of_huge_function = None
 
     def is_blackholing(self):
         return self.history is None
@@ -1343,6 +1344,8 @@
             warmrunnerstate = self.staticdata.state
             if len(self.history.operations) > warmrunnerstate.trace_limit:
                 self.staticdata.profiler.count(ABORT_TOO_LONG)
+                self.greenkey_of_huge_function = self.find_biggest_function()
+                self.portal_trace_positions = None
                 self.switch_to_blackhole()
 
     def _interpret(self):
@@ -1436,7 +1439,7 @@
         except ContinueRunningNormallyBase:
             if not started_as_blackhole:
                 warmrunnerstate = self.staticdata.state
-                warmrunnerstate.reset_counter_from_failure(key)
+                warmrunnerstate.reset_counter_from_failure(key, self)
             raise
 
     def forget_consts(self, boxes, startindex=0):
@@ -1826,6 +1829,30 @@
                 if boxes[i] is oldbox:
                     boxes[i] = newbox
 
+    def find_biggest_function(self):
+        assert not self.is_blackholing()
+
+        start_stack = []
+        max_size = 0
+        max_key = None
+        for pair in self.portal_trace_positions:
+            key, pos = pair
+            if key is not None:
+                start_stack.append(pair)
+            else:
+                greenkey, startpos = start_stack.pop()
+                size = pos - startpos
+                if size > max_size:
+                    max_size = size
+                    max_key = greenkey
+        if start_stack:
+            key, pos = start_stack[0]
+            size = len(self.history.operations) - pos
+            if size > max_size:
+                max_size = size
+                max_key = key
+        return max_key
+
 
 class GenerateMergePoint(Exception):
     def __init__(self, args, target_loop_token):

Modified: pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_pyjitpl.py
==============================================================================
--- pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_pyjitpl.py	(original)
+++ pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_pyjitpl.py	Fri Nov  6 16:25:53 2009
@@ -88,5 +88,18 @@
     metainterp.popframe()
     history.operations.append(5)
     metainterp.popframe()
+    history.operations.append(6)
     assert metainterp.portal_trace_positions == [("green1", 0), ("green2", 2),
                                                  (None, 3), (None, 5)]
+    assert metainterp.find_biggest_function() == "green1"
+
+    metainterp.newframe(portal, "green3")
+    history.operations.append(7)
+    metainterp.newframe(jitcode)
+    history.operations.append(8)
+    assert metainterp.portal_trace_positions == [("green1", 0), ("green2", 2),
+                                                 (None, 3), (None, 5), ("green3", 6)]
+    assert metainterp.find_biggest_function() == "green1"
+
+    history.operations.extend([9, 10, 11, 12])
+    assert metainterp.find_biggest_function() == "green3"

Modified: pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_recursive.py	(original)
+++ pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_recursive.py	Fri Nov  6 16:25:53 2009
@@ -604,6 +604,49 @@
         self.check_tree_loop_count(3)
         self.check_history(int_add=1)
 
+    def test_dont_inline_huge_stuff(self):
+        def p(code, pc):
+            code = hlstr(code)
+            return "%s %d %s" % (code, pc, code[pc])
+        def c(code, pc):
+            return "l" not in hlstr(code)
+        myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'],
+                                get_printable_location=p, can_inline=c)
+        
+        def f(code, n):
+            pc = 0
+            while pc < len(code):
+
+                myjitdriver.jit_merge_point(n=n, code=code, pc=pc)
+                op = code[pc]
+                if op == "-":
+                    n -= 1
+                elif op == "c":
+                    f('--------------------', n)
+                elif op == "l":
+                    if n > 0:
+                        myjitdriver.can_enter_jit(n=n, code=code, pc=0)
+                        pc = 0
+                        continue
+                else:
+                    assert 0
+                pc += 1
+            return n
+        def g(m):
+            myjitdriver.set_param('inlining', True)
+            # carefully chosen threshold to make sure that the inner function
+            # cannot be inlined, but the inner function on its own is small
+            # enough
+            myjitdriver.set_param('trace_limit', 40)
+            if m > 1000000:
+                f('', 0)
+            result = 0
+            for i in range(m):
+                result += f('-c-----------l-', i+100)
+        self.meta_interp(g, [10], backendopt=True)
+        self.check_aborted_count(1)
+        self.check_history(call=1)
+        self.check_tree_loop_count(3)
         
 
 class TestLLtype(RecursiveTests, LLJitMixin):

Modified: pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py	Fri Nov  6 16:25:53 2009
@@ -358,7 +358,7 @@
             maybe_enter_jit._always_inline_ = True
         self.maybe_enter_jit_fn = maybe_enter_jit
 
-        can_inline = self.jitdriver.can_inline
+        can_inline = self.state.can_inline_greenargs
         def maybe_enter_from_start(*args):
             if can_inline is not None and not can_inline(*args[:self.num_green_args]):
                 maybe_compile_and_run(*args)

Modified: pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmstate.py	Fri Nov  6 16:25:53 2009
@@ -161,8 +161,16 @@
         key.counter += 1
         return key.counter >= self.trace_eagerness
 
-    def reset_counter_from_failure(self, key):
+    def reset_counter_from_failure(self, key, metainterp):
         key.counter = 0
+        self.disable_noninlinable_function(metainterp)
+
+    def disable_noninlinable_function(self, metainterp):
+        greenkey = metainterp.greenkey_of_huge_function
+        if greenkey is not None:
+            cell = self.jit_cell_at_key(greenkey)
+            cell.dont_trace_here = True
+
 
     def attach_unoptimized_bridge_from_interp(self, greenkey,
                                               entry_loop_token):
@@ -220,6 +228,7 @@
                 except ContinueRunningNormally:
                     # the trace got too long, reset the counter
                     cell.counter = 0
+                    self.disable_noninlinable_function(metainterp)
                     raise
             else:
                 # machine code was already compiled for these greenargs
@@ -274,6 +283,7 @@
         class JitCell(BaseJitCell):
             counter = 0
             compiled_merge_points = None
+            dont_trace_here = False
         #
         if self.warmrunnerdesc.get_jitcell_at_ptr is None:
             jit_getter = self._make_jitcell_getter_default(JitCell)
@@ -428,18 +438,27 @@
             return
         #
         can_inline_ptr = self.warmrunnerdesc.can_inline_ptr
+        unwrap_greenkey = self.make_unwrap_greenkey()
         if can_inline_ptr is None:
-            def can_inline_callable(greenkey):
+            def can_inline_callable(*greenargs):
                 return True
         else:
             rtyper = self.warmrunnerdesc.rtyper
-            unwrap_greenkey = self.make_unwrap_greenkey()
             #
-            def can_inline_callable(greenkey):
-                greenargs = unwrap_greenkey(greenkey)
+            def can_inline_callable(*greenargs):
                 fn = support.maybe_on_top_of_llinterp(rtyper, can_inline_ptr)
                 return fn(*greenargs)
-        self.can_inline_callable = can_inline_callable
+        def can_inline(*greenargs):
+            cell = self.jit_getter(*greenargs)
+            if cell.dont_trace_here:
+                return False
+            return can_inline_callable(*greenargs)
+        self.can_inline_greenargs = can_inline
+        def can_inline_greenkey(greenkey):
+            greenargs = unwrap_greenkey(greenkey)
+            return can_inline(*greenargs)
+        self.can_inline_callable = can_inline_greenkey
+
         #
         get_location_ptr = self.warmrunnerdesc.get_printable_location_ptr
         if get_location_ptr is None:



More information about the Pypy-commit mailing list