[pypy-svn] r69047 - in pypy/trunk/pypy/jit/metainterp: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Nov 7 16:02:19 CET 2009


Author: cfbolz
Date: Sat Nov  7 16:02:16 2009
New Revision: 69047

Modified:
   pypy/trunk/pypy/jit/metainterp/pyjitpl.py
   pypy/trunk/pypy/jit/metainterp/test/test_basic.py
   pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py
   pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py
   pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py
   pypy/trunk/pypy/jit/metainterp/test/test_recursive.py
   pypy/trunk/pypy/jit/metainterp/test/test_slist.py
   pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py
   pypy/trunk/pypy/jit/metainterp/warmspot.py
   pypy/trunk/pypy/jit/metainterp/warmstate.py
Log:
(pedronis, cfbolz): merge the jit-less-inlining branch:

    ------------------------------------------------------------------------
    r69045 | cfbolz | 2009-11-07 12:27:08 +0100 (Sat, 07 Nov 2009) | 2 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmstate.py

    (pedronis, cfbolz): add a debug print for disabling inlining of a function

    ------------------------------------------------------------------------
    r69040 | cfbolz | 2009-11-06 16:51:18 +0100 (Fri, 06 Nov 2009) | 2 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_warmstate.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py

    (cfbolz, antocuni): fix some more tests

    ------------------------------------------------------------------------
    r69039 | cfbolz | 2009-11-06 16:32:41 +0100 (Fri, 06 Nov 2009) | 2 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_slist.py

    fix test_slist

    ------------------------------------------------------------------------
    r69038 | cfbolz | 2009-11-06 16:30:51 +0100 (Fri, 06 Nov 2009) | 2 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_blackhole.py

    fix test_blackhole

    ------------------------------------------------------------------------
    r69037 | cfbolz | 2009-11-06 16:25:53 +0100 (Fri, 06 Nov 2009) | 3 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_pyjitpl.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_recursive.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmstate.py

    (pedronis, cfbolz, antocuni): If we abort due to a too long trace, we mark the
    longest function as non-inlinable.

    ------------------------------------------------------------------------
    r69036 | cfbolz | 2009-11-06 15:12:48 +0100 (Fri, 06 Nov 2009) | 3 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_pyjitpl.py

    (pedronis, cfbolz): make the metainterp keep track of where in the history the
    high-level functions start and return.

    ------------------------------------------------------------------------
    r69035 | cfbolz | 2009-11-06 15:11:26 +0100 (Fri, 06 Nov 2009) | 3 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py

    (pedronis, cfbolz): push and pull to order things in such a way that the
    translation tests work again.

    ------------------------------------------------------------------------
    r69034 | cfbolz | 2009-11-06 15:10:51 +0100 (Fri, 06 Nov 2009) | 2 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_codewriter.py

    (pedronis, cfbolz): forgot to fix those

    ------------------------------------------------------------------------
    r69033 | cfbolz | 2009-11-06 14:18:03 +0100 (Fri, 06 Nov 2009) | 2 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/history.py

    (pedronis, cfbolz): this was not meant to be checked in at all.

    ------------------------------------------------------------------------
    r69032 | cfbolz | 2009-11-06 14:07:06 +0100 (Fri, 06 Nov 2009) | 2 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py

    (pedronis, cfbolz): oops, can_inline can be None

    ------------------------------------------------------------------------
    r69031 | cfbolz | 2009-11-06 14:02:46 +0100 (Fri, 06 Nov 2009) | 3 lines
    Changed paths:
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/history.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_basic.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/test/test_recursive.py
       M /pypy/branch/jit-less-inlining/pypy/jit/metainterp/warmspot.py

    (pedronis, cfbolz): a first step towards nirvana: start tracing from the
    beginning of functions that cannot be inlined.



Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py	Sat Nov  7 16:02:16 2009
@@ -106,7 +106,7 @@
     parent_resumedata_snapshot = None
     parent_resumedata_frame_info_list = None
 
-    def __init__(self, metainterp, jitcode):
+    def __init__(self, metainterp, jitcode, greenkey=None):
         assert isinstance(jitcode, codewriter.JitCode)
         self.metainterp = metainterp
         self.jitcode = jitcode
@@ -114,6 +114,8 @@
         self.constants = jitcode.constants
         self.exception_target = -1
         self.name = jitcode.name # purely for having name attribute
+        # this is not None for frames that are recursive portal calls
+        self.greenkey = greenkey
 
     # ------------------------------
     # Decoding of the JitCode
@@ -589,7 +591,7 @@
         result = vinfo.get_array_length(virtualizable, arrayindex)
         self.make_result_box(ConstInt(result))
 
-    def perform_call(self, jitcode, varargs):
+    def perform_call(self, jitcode, varargs, greenkey=None):
         if (self.metainterp.is_blackholing() and
             jitcode.calldescr is not None):
             # when producing only a BlackHole, we can implement this by
@@ -613,7 +615,7 @@
             return res
         else:
             # when tracing, this bytecode causes the subfunction to be entered
-            f = self.metainterp.newframe(jitcode)
+            f = self.metainterp.newframe(jitcode, greenkey)
             f.setup_call(varargs)
             return True
 
@@ -646,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")
@@ -1126,14 +1128,19 @@
     def __init__(self, staticdata):
         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
 
-    def newframe(self, jitcode):
+    def newframe(self, jitcode, greenkey=None):
         if jitcode is self.staticdata.portal_code:
             self.in_recursion += 1
-        f = MIFrame(self, jitcode)
+        if greenkey is not None and not self.is_blackholing():
+            self.portal_trace_positions.append(
+                    (greenkey, len(self.history.operations)))
+        f = MIFrame(self, jitcode, greenkey)
         self.framestack.append(f)
         return f
 
@@ -1141,6 +1148,9 @@
         frame = self.framestack.pop()
         if frame.jitcode is self.staticdata.portal_code:
             self.in_recursion -= 1
+        if frame.greenkey is not None and not self.is_blackholing():
+            self.portal_trace_positions.append(
+                    (None, len(self.history.operations)))
         return frame
 
     def finishframe(self, resultbox):
@@ -1334,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):
@@ -1427,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):
@@ -1817,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/trunk/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_basic.py	Sat Nov  7 16:02:16 2009
@@ -109,7 +109,12 @@
         else:
             raise Exception("FAILED")
 
-    def check_history_(self, expected=None, **isns):
+    def check_history(self, expected=None, **isns):
+        # this can be used after calling meta_interp
+        get_stats().check_history(expected, **isns)
+
+    def check_operations_history(self, expected=None, **isns):
+        # this can be used after interp_operations
         self.metainterp.staticdata.stats.check_history(expected, **isns)
 
 
@@ -304,7 +309,7 @@
             return externfn(n, n+1)
         res = self.interp_operations(f, [6])
         assert res == 42
-        self.check_history_(int_add=1, int_mul=0, call=1, guard_no_exception=0)
+        self.check_operations_history(int_add=1, int_mul=0, call=1, guard_no_exception=0)
 
     def test_residual_call_pure(self):
         def externfn(x, y):
@@ -315,7 +320,7 @@
             return externfn(n, n+1)
         res = self.interp_operations(f, [6])
         assert res == 42
-        self.check_history_(int_add=0, int_mul=0, call=0)
+        self.check_operations_history(int_add=0, int_mul=0, call=0)
 
     def test_constant_across_mp(self):
         myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -417,7 +422,7 @@
             return a.foo * x
         res = self.interp_operations(f, [42])
         assert res == 210
-        self.check_history_(getfield_gc=1)
+        self.check_operations_history(getfield_gc=1)
 
     def test_getfield_immutable(self):
         class A:
@@ -434,7 +439,7 @@
             return a.foo * x
         res = self.interp_operations(f, [42])
         assert res == 210
-        self.check_history_(getfield_gc=0)
+        self.check_operations_history(getfield_gc=0)
 
     def test_setfield_bool(self):
         class A:
@@ -748,7 +753,7 @@
             return isinstance(obj, B)
         res = self.interp_operations(fn, [0])
         assert res
-        self.check_history_(guard_class=1)
+        self.check_operations_history(guard_class=1)
         res = self.interp_operations(fn, [1])
         assert not res
 
@@ -769,7 +774,7 @@
             return obj.a
         res = self.interp_operations(fn, [1])
         assert res == 1
-        self.check_history_(guard_class=0, instanceof=0)
+        self.check_operations_history(guard_class=0, instanceof=0)
 
     def test_r_dict(self):
         from pypy.rlib.objectmodel import r_dict
@@ -901,7 +906,7 @@
             return g(a, b)
         res = self.interp_operations(f, [3, 5])
         assert res == 8
-        self.check_history_(int_add=0, call=1)
+        self.check_operations_history(int_add=0, call=1)
 
     def test_listcomp(self):
         myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'lst'])
@@ -925,7 +930,7 @@
             return tup[1]
         res = self.interp_operations(f, [3, 5])
         assert res == 5
-        self.check_history_(setfield_gc=2, getfield_gc_pure=1)
+        self.check_operations_history(setfield_gc=2, getfield_gc_pure=1)
 
     def test_oosend_look_inside_only_one(self):
         class A:

Modified: pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_blackhole.py	Sat Nov  7 16:02:16 2009
@@ -6,8 +6,8 @@
 class BlackholeTests(object):
 
     def meta_interp(self, *args):
-        def counting_init(frame, metainterp, jitcode):
-            previnit(frame, metainterp, jitcode)
+        def counting_init(frame, metainterp, jitcode, greenkey=None):
+            previnit(frame, metainterp, jitcode, greenkey)
             self.seen_frames.append(jitcode.name)
         #
         previnit = pyjitpl.MIFrame.__init__.im_func

Modified: pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_codewriter.py	Sat Nov  7 16:02:16 2009
@@ -356,7 +356,7 @@
             return y.x + 5
         res = self.interp_operations(f, [23])
         assert res == 28
-        self.check_history_(getfield_gc=0, getfield_gc_pure=1, int_add=1)
+        self.check_operations_history(getfield_gc=0, getfield_gc_pure=1, int_add=1)
 
     def test_array(self):
         class X(object):
@@ -371,7 +371,7 @@
             return a.y[index]
         res = self.interp_operations(f, [2], listops=True)
         assert res == 30
-        self.check_history_(getfield_gc=0, getfield_gc_pure=1,
+        self.check_operations_history(getfield_gc=0, getfield_gc_pure=1,
                             getarrayitem_gc=0, getarrayitem_gc_pure=1)
 
 
@@ -389,7 +389,7 @@
             return y.lst[index] + y.y + 5
         res = self.interp_operations(f, [23, 0], listops=True)
         assert res == 23 + 24 + 5
-        self.check_history_(getfield_gc=0, getfield_gc_pure=2,
+        self.check_operations_history(getfield_gc=0, getfield_gc_pure=2,
                             getarrayitem_gc=0, getarrayitem_gc_pure=1,
                             int_add=3)
 

Modified: pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_pyjitpl.py	Sat Nov  7 16:02:16 2009
@@ -62,3 +62,44 @@
     # doesn't provide interning on its own
     n1_1 = gd.get_fail_descr_number(fail_descr1)
     assert n1_1 != n1
+
+def test_portal_trace_positions():
+    jitcode = codewriter.JitCode("f")
+    jitcode.code = jitcode.constants = None
+    portal = codewriter.JitCode("portal")
+    portal.code = portal.constants = None
+    class FakeStaticData:
+        cpu = None
+        portal_code = portal
+
+    metainterp = pyjitpl.MetaInterp(FakeStaticData())
+    metainterp.framestack = []
+    class FakeHistory:
+        operations = []
+    history = metainterp.history = FakeHistory()
+    metainterp.newframe(portal, "green1")
+    history.operations.append(1)
+    metainterp.newframe(jitcode)
+    history.operations.append(2)
+    metainterp.newframe(portal, "green2")
+    history.operations.append(3)
+    metainterp.popframe()
+    history.operations.append(4)
+    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/trunk/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_recursive.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_recursive.py	Sat Nov  7 16:02:16 2009
@@ -564,6 +564,91 @@
         res = self.meta_interp(main, [100], optimizer=OPTIMIZER_SIMPLE, inline=True)
         assert res == main(100)
 
+    def test_trace_from_start(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 += 7
+                if op == "-":
+                    n -= 1
+                if op == "c":
+                    n = f('---', n)
+                elif op == "l":
+                    if n > 0:
+                        myjitdriver.can_enter_jit(n=n, code=code, pc=1)
+                        pc = 1
+                        continue
+                else:
+                    assert 0
+                pc += 1
+            return n
+        def g(m):
+            if m > 1000000:
+                f('', 0)
+            result = 0
+            for i in range(m):
+                result += f('+-cl--', i)
+        self.meta_interp(g, [50], backendopt=True)
+        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):
     pass
 

Modified: pypy/trunk/pypy/jit/metainterp/test/test_slist.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_slist.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_slist.py	Sat Nov  7 16:02:16 2009
@@ -35,7 +35,7 @@
             return m
         res = self.interp_operations(f, [11], listops=True)
         assert res == 49
-        self.check_history_(call=5)
+        self.check_operations_history(call=5)
 
     def test_list_of_voids(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'lst'])
@@ -88,7 +88,7 @@
             return lst[n]
         res = self.interp_operations(f, [-2], listops=True)
         assert res == 41
-        self.check_history_(call=1)
+        self.check_operations_history(call=1)
 
 # we don't support resizable lists on ootype
 #class TestOOtype(ListTests, OOJitMixin):

Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py	Sat Nov  7 16:02:16 2009
@@ -165,7 +165,13 @@
     class FakeWarmRunnerDesc:
         can_inline_ptr = None
         get_printable_location_ptr = None
+        green_args_spec = [lltype.Signed, lltype.Float]
+    class FakeCell:
+        dont_trace_here = False
     state = WarmEnterState(FakeWarmRunnerDesc())
+    def jit_getter(*args):
+        return FakeCell()
+    state.jit_getter = jit_getter
     state.make_jitdriver_callbacks()
     res = state.can_inline_callable([BoxInt(5), BoxFloat(42.5)])
     assert res is True
@@ -179,12 +185,17 @@
         return False
     CAN_INLINE = lltype.Ptr(lltype.FuncType([lltype.Signed, lltype.Float],
                                             lltype.Bool))
+    class FakeCell:
+        dont_trace_here = False
     class FakeWarmRunnerDesc:
         rtyper = None
         green_args_spec = [lltype.Signed, lltype.Float]
         can_inline_ptr = llhelper(CAN_INLINE, can_inline)
         get_printable_location_ptr = None
     state = WarmEnterState(FakeWarmRunnerDesc())
+    def jit_getter(*args):
+        return FakeCell()
+    state.jit_getter = jit_getter
     state.make_jitdriver_callbacks()
     res = state.can_inline_callable([BoxInt(5), BoxFloat(42.5)])
     assert res is False

Modified: pypy/trunk/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/warmspot.py	Sat Nov  7 16:02:16 2009
@@ -161,18 +161,19 @@
 
         self.build_meta_interp(CPUClass, **kwds)
         self.make_args_specification()
-        self.rewrite_jit_merge_point(policy)
-        self.make_driverhook_graphs()
         if self.jitdriver.virtualizables:
             from pypy.jit.metainterp.virtualizable import VirtualizableInfo
             self.metainterp_sd.virtualizable_info = VirtualizableInfo(self)
+        self.make_exception_classes()
+        self.make_driverhook_graphs()
+        self.make_enter_function()
+        self.rewrite_jit_merge_point(policy)
                 
         self.codewriter.generate_bytecode(self.metainterp_sd,
                                           self.portal_graph,
                                           self.leave_graph,
                                           self.portal_runner_ptr
                                           )
-        self.make_enter_function()
         self.rewrite_can_enter_jit()
         self.rewrite_set_param()
         self.add_profiler_finish()
@@ -262,7 +263,68 @@
                                                   self.stats, opt,
                                                   ProfilerClass=ProfilerClass,
                                                   warmrunnerdesc=self)
-        
+
+    def make_exception_classes(self):
+        portalfunc_ARGS = unrolling_iterable(
+            [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(self.PORTAL_FUNCTYPE.ARGS)])
+        class DoneWithThisFrameVoid(JitException):
+            def __str__(self):
+                return 'DoneWithThisFrameVoid()'
+
+        class DoneWithThisFrameInt(JitException):
+            def __init__(self, result):
+                assert lltype.typeOf(result) is lltype.Signed
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFrameInt(%s)' % (self.result,)
+
+        class DoneWithThisFrameRef(JitException):
+            def __init__(self, cpu, result):
+                assert lltype.typeOf(result) == cpu.ts.BASETYPE
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFrameRef(%s)' % (self.result,)
+
+        class DoneWithThisFrameFloat(JitException):
+            def __init__(self, result):
+                assert lltype.typeOf(result) is lltype.Float
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFrameFloat(%s)' % (self.result,)
+
+        class ExitFrameWithExceptionRef(JitException):
+            def __init__(self, cpu, value):
+                assert lltype.typeOf(value) == cpu.ts.BASETYPE
+                self.value = value
+            def __str__(self):
+                return 'ExitFrameWithExceptionRef(%s)' % (self.value,)
+
+        class ContinueRunningNormally(ContinueRunningNormallyBase):
+            def __init__(self, argboxes):
+                # accepts boxes as argument, but unpacks them immediately
+                # before we raise the exception -- the boxes' values will
+                # be modified in a 'finally' by restore_patched_boxes().
+                from pypy.jit.metainterp.warmstate import unwrap
+                for i, name, ARG in portalfunc_ARGS:
+                    v = unwrap(ARG, argboxes[i])
+                    setattr(self, name, v)
+
+            def __str__(self):
+                return 'ContinueRunningNormally(%s)' % (
+                    ', '.join(map(str, self.args)),)
+
+        self.DoneWithThisFrameVoid = DoneWithThisFrameVoid
+        self.DoneWithThisFrameInt = DoneWithThisFrameInt
+        self.DoneWithThisFrameRef = DoneWithThisFrameRef
+        self.DoneWithThisFrameFloat = DoneWithThisFrameFloat
+        self.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
+        self.ContinueRunningNormally = ContinueRunningNormally
+        self.metainterp_sd.DoneWithThisFrameVoid = DoneWithThisFrameVoid
+        self.metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrameInt
+        self.metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
+        self.metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrameFloat
+        self.metainterp_sd.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
+        self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
     def make_enter_function(self):
         from pypy.jit.metainterp.warmstate import WarmEnterState
         state = WarmEnterState(self)
@@ -294,9 +356,16 @@
             def maybe_enter_jit(*args):
                 maybe_compile_and_run(*args)
             maybe_enter_jit._always_inline_ = True
-
         self.maybe_enter_jit_fn = maybe_enter_jit
 
+        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)
+        maybe_enter_from_start._always_inline_ = True
+        self.maybe_enter_from_start_fn = maybe_enter_from_start
+
+
     def make_leave_jit_graph(self):
         self.leave_graph = None
         if self.jitdriver.leave:
@@ -439,64 +508,7 @@
         portalfunc_ARGS = unrolling_iterable(
             [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(PORTALFUNC.ARGS)])
 
-        class DoneWithThisFrameVoid(JitException):
-            def __str__(self):
-                return 'DoneWithThisFrameVoid()'
-
-        class DoneWithThisFrameInt(JitException):
-            def __init__(self, result):
-                assert lltype.typeOf(result) is lltype.Signed
-                self.result = result
-            def __str__(self):
-                return 'DoneWithThisFrameInt(%s)' % (self.result,)
-
-        class DoneWithThisFrameRef(JitException):
-            def __init__(self, cpu, result):
-                assert lltype.typeOf(result) == cpu.ts.BASETYPE
-                self.result = result
-            def __str__(self):
-                return 'DoneWithThisFrameRef(%s)' % (self.result,)
-
-        class DoneWithThisFrameFloat(JitException):
-            def __init__(self, result):
-                assert lltype.typeOf(result) is lltype.Float
-                self.result = result
-            def __str__(self):
-                return 'DoneWithThisFrameFloat(%s)' % (self.result,)
-
-        class ExitFrameWithExceptionRef(JitException):
-            def __init__(self, cpu, value):
-                assert lltype.typeOf(value) == cpu.ts.BASETYPE
-                self.value = value
-            def __str__(self):
-                return 'ExitFrameWithExceptionRef(%s)' % (self.value,)
-
-        class ContinueRunningNormally(ContinueRunningNormallyBase):
-            def __init__(self, argboxes):
-                # accepts boxes as argument, but unpacks them immediately
-                # before we raise the exception -- the boxes' values will
-                # be modified in a 'finally' by restore_patched_boxes().
-                from pypy.jit.metainterp.warmstate import unwrap
-                for i, name, ARG in portalfunc_ARGS:
-                    v = unwrap(ARG, argboxes[i])
-                    setattr(self, name, v)
 
-            def __str__(self):
-                return 'ContinueRunningNormally(%s)' % (
-                    ', '.join(map(str, self.args)),)
-
-        self.DoneWithThisFrameVoid = DoneWithThisFrameVoid
-        self.DoneWithThisFrameInt = DoneWithThisFrameInt
-        self.DoneWithThisFrameRef = DoneWithThisFrameRef
-        self.DoneWithThisFrameFloat = DoneWithThisFrameFloat
-        self.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
-        self.ContinueRunningNormally = ContinueRunningNormally
-        self.metainterp_sd.DoneWithThisFrameVoid = DoneWithThisFrameVoid
-        self.metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrameInt
-        self.metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
-        self.metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrameFloat
-        self.metainterp_sd.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
-        self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
         rtyper = self.translator.rtyper
         RESULT = PORTALFUNC.RESULT
         result_kind = history.getkind(RESULT)
@@ -505,26 +517,27 @@
         def ll_portal_runner(*args):
             while 1:
                 try:
+                    self.maybe_enter_from_start_fn(*args)
                     return support.maybe_on_top_of_llinterp(rtyper,
                                                       portal_ptr)(*args)
-                except ContinueRunningNormally, e:
+                except self.ContinueRunningNormally, e:
                     args = ()
                     for _, name, _ in portalfunc_ARGS:
                         v = getattr(e, name)
                         args = args + (v,)
-                except DoneWithThisFrameVoid:
+                except self.DoneWithThisFrameVoid:
                     assert result_kind == 'void'
                     return
-                except DoneWithThisFrameInt, e:
+                except self.DoneWithThisFrameInt, e:
                     assert result_kind == 'int'
                     return lltype.cast_primitive(RESULT, e.result)
-                except DoneWithThisFrameRef, e:
+                except self.DoneWithThisFrameRef, e:
                     assert result_kind == 'ref'
                     return ts.cast_from_ref(RESULT, e.result)
-                except DoneWithThisFrameFloat, e:
+                except self.DoneWithThisFrameFloat, e:
                     assert result_kind == 'float'
                     return e.result
-                except ExitFrameWithExceptionRef, e:
+                except self.ExitFrameWithExceptionRef, e:
                     value = ts.cast_to_baseclass(e.value)
                     if not we_are_translated():
                         raise LLException(ts.get_typeptr(value), value)

Modified: pypy/trunk/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/warmstate.py	Sat Nov  7 16:02:16 2009
@@ -10,7 +10,7 @@
 from pypy.rlib.jit import PARAMETERS, OPTIMIZER_SIMPLE, OPTIMIZER_FULL
 from pypy.rlib.jit import DEBUG_PROFILE
 from pypy.rlib.jit import BaseJitCell
-from pypy.rlib.debug import debug_start, debug_stop
+from pypy.rlib.debug import debug_start, debug_stop, debug_print
 from pypy.jit.metainterp import support, history
 
 # ____________________________________________________________
@@ -161,8 +161,20 @@
         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
+            debug_start("jit-disableinlining")
+            sd = self.warmrunnerdesc.metainterp_sd
+            loc = sd.state.get_location_str(greenkey)
+            debug_print("disabled inlining", loc)
+            debug_stop("jit-disableinlining")
 
     def attach_unoptimized_bridge_from_interp(self, greenkey,
                                               entry_loop_token):
@@ -220,6 +232,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 +287,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 +442,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