Commits

Antonio Cuni  committed 359bb4a

a failing test and the fix: it is not enough to manually call inline_function, we need the full auto_inline logic to correctly handle calls to graphs which raise exceptions

  • Participants
  • Parent commits 1244f49
  • Branches autoreds

Comments (0)

Files changed (4)

File pypy/jit/metainterp/test/test_warmspot.py

         self.check_resops(int_eq=4, int_add=8)
         self.check_trace_count(2)
 
+    def test_inline_in_portal_exception(self):
+        myjitdriver = JitDriver(greens = [], reds = 'auto')
+        def inc(n):
+            if n == 1000:
+                raise OverflowError
+            return n+1
+
+        @myjitdriver.inline_in_portal
+        def jitted_inc(n):
+            myjitdriver.jit_merge_point()
+            return inc(n)
+
+        def f():
+            res = 0
+            while True:
+                try:
+                    res = jitted_inc(res)
+                except OverflowError:
+                    break
+            return res
+        res = self.meta_interp(f, [])
+        assert res == 1000
+        self.check_resops(int_add=2)
+
+
 class TestLLWarmspot(WarmspotTests, LLJitMixin):
     CPUClass = runner.LLtypeCPU
     type_system = 'lltype'

File pypy/jit/metainterp/warmspot.py

         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)
+
+        # find all the graphs which call an @inline_in_portal function
         callgraph = inline.inlinable_static_callers(self.translator.graphs)
+        new_callgraph = []
         new_portals = set()
         for caller, callee in callgraph:
             func = getattr(callee, 'func', None)
             _inline_in_portal_ = getattr(func, '_inline_in_portal_', False)
             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_callgraph.append((caller, callee))
                 new_portals.add(caller)
+
+        # inline them!
+        inline_threshold = self.translator.config.translation.backendopt.inline_threshold
+        inline.auto_inlining(self.translator, inline_threshold, callgraph)
+
+        # make a fresh copy of the JitDriver in all newly created
+        # jit_merge_points
         self.clone_inlined_jit_merge_points(new_portals)
 
     def clone_inlined_jit_merge_points(self, graphs):
         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()
+            driver = v_driver.value
+            if not driver.inlined_in_portal:
+                continue
+            new_driver = driver.clone()
             c_new_driver = Constant(new_driver, v_driver.concretetype)
             op.args[1] = c_new_driver
 

File pypy/rlib/jit.py

     def inline_in_portal(self, func):
         assert self.autoreds, "inline_in_portal works only with reds='auto'"
         func._inline_in_portal_ = True
+        func._always_inline_ = True
         self.inlined_in_portal = True
         return func
 

File pypy/rlib/test/test_jit.py

     py.test.raises(AssertionError, "driver.clone()")
     foo = driver.inline_in_portal(foo)
     assert foo._inline_in_portal_ == True
+    assert foo._always_inline_ == True
     #
     driver.foo = 'bar'
     driver2 = driver.clone()