Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r59076:c782efd2c6a1
Date: 2012-11-23 21:07 +0100
http://bitbucket.org/pypy/pypy/changeset/c782efd2c6a1/

Log:    Change _always_inline_=True to crash if inlining fails. Use
        _always_inline_='try' to not crash if it fails. Fixes left and
        right.

diff --git a/pypy/interpreter/astcompiler/optimize.py 
b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -141,7 +141,7 @@
 unrolling_unary_folders = unrolling_iterable(unary_folders.items())
 
 for folder in binary_folders.values() + unary_folders.values():
-    folder._always_inline_ = True
+    folder._always_inline_ = 'try'
 del folder
 
 opposite_compare_operations = misc.dict_to_switch({
diff --git a/pypy/interpreter/executioncontext.py 
b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -144,7 +144,10 @@
         actionflag = self.space.actionflag
         if actionflag.get_ticker() < 0:
             actionflag.action_dispatcher(self, frame)     # slow path
-    bytecode_trace_after_exception._always_inline_ = True
+    bytecode_trace_after_exception._always_inline_ = 'try'
+    # NB. this function is not inlined right now.  backendopt.inline would
+    # need some improvements to handle this case, but it's not really an
+    # issue
 
     def exception_trace(self, frame, operationerr):
         "Trace function called upon OperationError."
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -320,7 +320,7 @@
                         Py_DecRef(space, arg)
             unwrapper.func = func
             unwrapper.api_func = api_function
-            unwrapper._always_inline_ = True
+            unwrapper._always_inline_ = 'try'
             return unwrapper
 
         unwrapper_catch = make_unwrapper(True)
@@ -625,7 +625,7 @@
                 pypy_debug_catch_fatal_exception()
         rffi.stackcounter.stacks_counter -= 1
         return retval
-    callable._always_inline_ = True
+    callable._always_inline_ = 'try'
     wrapper.__name__ = "wrapper for %r" % (callable, )
     return wrapper
 
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -797,7 +797,7 @@
             wordshift += 1
         z._normalize()
         return z
-    rshift._always_inline_ = True # It's so fast that it's always benefitial.
+    rshift._always_inline_ = 'try' # It's so fast that it's always benefitial.
     
     @jit.elidable
     def and_(self, other):
diff --git a/pypy/rpython/lltypesystem/rffi.py 
b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -250,7 +250,7 @@
                 return cast(lltype.Unsigned, res)
         return res
     wrapper._annspecialcase_ = 'specialize:ll'
-    wrapper._always_inline_ = True
+    wrapper._always_inline_ = 'try'
     # for debugging, stick ll func ptr to that
     wrapper._ptr = funcptr
     wrapper = func_with_new_name(wrapper, name)
@@ -772,7 +772,7 @@
         """
         raw_buf = lltype.malloc(TYPEP.TO, count, flavor='raw')
         return raw_buf, lltype.nullptr(STRTYPE)
-    alloc_buffer._always_inline_ = True # to get rid of the returned tuple
+    alloc_buffer._always_inline_ = 'try' # to get rid of the returned tuple
     alloc_buffer._annenforceargs_ = [int]
 
     # (char*, str, int, int) -> None
diff --git a/pypy/translator/backendopt/inline.py 
b/pypy/translator/backendopt/inline.py
--- a/pypy/translator/backendopt/inline.py
+++ b/pypy/translator/backendopt/inline.py
@@ -676,6 +676,10 @@
                         n += 1
     log.inlining("%d call sites instrumented" % n)
 
+def always_inline(graph):
+    return (hasattr(graph, 'func') and
+            getattr(graph.func, '_always_inline_', None))
+
 def auto_inlining(translator, threshold=None,
                   callgraph=None,
                   call_count_pred=None,
@@ -701,8 +705,7 @@
     while heap:
         weight, _, graph = heap[0]
         if not valid_weight.get(graph):
-            if hasattr(graph, 'func') and \
-                   getattr(graph.func, '_always_inline_', None):
+            if always_inline(graph):
                 weight, fixed = 0.0, True
             else:
                 weight, fixed = heuristic(graph)
@@ -710,7 +713,7 @@
             heapreplace(heap, (weight, -len(callers[graph]), graph))
             valid_weight[graph] = True
             if not fixed:
-                try_again[graph] = True
+                try_again[graph] = 'initial'
             continue
 
         if weight >= threshold:
@@ -745,8 +748,8 @@
                                            call_count_pred, cleanup=False)
                 to_cleanup[parentgraph] = True
                 res = bool(subcount)
-            except CannotInline:
-                try_again[graph] = True
+            except CannotInline, e:
+                try_again[graph] = str(e)
                 res = CannotInline
             if res is True:
                 count += subcount
@@ -762,6 +765,15 @@
                     del try_again[parentgraph]
                     heappush(heap, (0.0, -len(callers[parentgraph]), 
parentgraph))
                 valid_weight[parentgraph] = False
+
+    invalid = [(graph, msg) for graph, msg in try_again.items()
+                            if always_inline(graph) is True]
+    if invalid:
+        message = '\n'.join([
+            "%s has _always_inline_=True but inlining failed:\n\t%s" %
+            (graph, msg) for (graph, msg) in invalid])
+        raise CannotInline(message)
+
     for graph in to_cleanup:
         cleanup_graph(graph)
     return count
diff --git a/pypy/translator/backendopt/test/test_inline.py 
b/pypy/translator/backendopt/test/test_inline.py
--- a/pypy/translator/backendopt/test/test_inline.py
+++ b/pypy/translator/backendopt/test/test_inline.py
@@ -759,3 +759,23 @@
         eval_func = self.check_inline(g, f, [int, int])
         res = eval_func([10, 173])
         assert res == f(10, 173)
+
+    def test_cannot_inline_1(self):
+        from pypy.rpython.lltypesystem import lltype, rffi
+        for attr in [None, 'try', True]:
+            def h1(n):
+                return lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+            if attr is not None:
+                h1._always_inline_ = attr
+            def f(x):
+                try:
+                    return h1(x)
+                except Exception:
+                    return lltype.nullptr(rffi.INTP.TO)
+            #
+            def compile():
+                self.check_auto_inlining(f, [int])
+            if attr is True:
+                py.test.raises(CannotInline, compile)
+            else:
+                compile()    # assert does not raise
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to