changeset 23262:3fa1b7b2329c

added MethodInlineBailoutLimit option to guard against inlining pathologies that effectively prevent compilation from completing in reasonable time
author Doug Simon <doug.simon@oracle.com>
date Wed, 06 Jan 2016 18:20:54 +0100
parents 2ea1d1979187
children 75150687d044
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java
diffstat 2 files changed, 32 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java	Wed Jan 06 18:06:07 2016 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java	Wed Jan 06 18:20:54 2016 +0100
@@ -24,6 +24,9 @@
 
 import java.util.Map;
 
+import jdk.vm.ci.code.BailoutException;
+
+import com.oracle.graal.compiler.common.util.Util;
 import com.oracle.graal.nodes.Invoke;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.options.Option;
@@ -40,10 +43,16 @@
 
     public static class Options {
 
-        // @formatter:off
-        @Option(help = "Unconditionally inline intrinsics", type = OptionType.Debug)
+        @Option(help = "Unconditionally inline intrinsics", type = OptionType.Debug)//
         public static final OptionValue<Boolean> AlwaysInlineIntrinsics = new OptionValue<>(false);
-        // @formatter:on
+
+        /**
+         * This is a defensive measure against known pathologies of the inliner where the breadth of
+         * the inlining call tree exploration can be wide enough to prevent inlining from completing
+         * in reasonable time.
+         */
+        @Option(help = "Per-compilation method inlining limit before bailing out (use 0 to disable)", type = OptionType.Debug)//
+        public static final OptionValue<Integer> MethodInlineBailoutLimit = new OptionValue<>(5000);
     }
 
     private final InliningPolicy inliningPolicy;
@@ -85,15 +94,21 @@
     protected void run(final StructuredGraph graph, final HighTierContext context) {
         final InliningData data = new InliningData(graph, context, maxMethodPerInlining, canonicalizer, inliningPolicy);
 
+        int count = 0;
         assert data.repOK();
+        int limit = Options.MethodInlineBailoutLimit.getValue();
         while (data.hasUnprocessedGraphs()) {
             boolean wasInlined = data.moveForward();
             assert data.repOK();
             if (wasInlined) {
-                inliningCount++;
+                count++;
+                if (limit > 0 && count == limit) {
+                    throw new BailoutException("Reached method inline limit %d%nInvocation stack:%n  %s", limit, Util.join(data.getInvocationStackTrace(), "\n  "));
+                }
             }
         }
 
+        inliningCount += count;
         assert data.inliningDepth() == 0;
         assert data.graphCount() == 0;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Wed Jan 06 18:06:07 2016 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Wed Jan 06 18:20:54 2016 +0100
@@ -32,6 +32,7 @@
 import java.util.BitSet;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 import jdk.vm.ci.code.BailoutException;
@@ -629,6 +630,18 @@
         return result.toString();
     }
 
+    /**
+     * Gets a stack trace representing the current inlining stack represented by this object.
+     */
+    public Collection<StackTraceElement> getInvocationStackTrace() {
+        List<StackTraceElement> result = new ArrayList<>();
+        for (CallsiteHolder graph : graphQueue) {
+            result.add(graph.method().asStackTraceElement(0));
+        }
+
+        return result;
+    }
+
     private boolean contains(StructuredGraph graph) {
         assert graph != null;
         for (CallsiteHolder info : graphQueue) {