changeset 4564:8fc6920e064b

avoid recursive inlining, escape analysis does no longer restart inlining with level 0, bugfixes
author Christian Haeubl <christian.haeubl@oracle.com>
date Fri, 10 Feb 2012 14:36:19 -0800
parents b27666ff9bd6
children e0f4a398fb11
files graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiExceptionSeen.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotNoProfilingInfo.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotProfilingInfo.java
diffstat 7 files changed, 52 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiExceptionSeen.java	Fri Feb 10 11:14:51 2012 -0800
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiExceptionSeen.java	Fri Feb 10 14:36:19 2012 -0800
@@ -29,7 +29,7 @@
 public enum RiExceptionSeen {
     TRUE,
     FALSE,
-    UNKNOWN;
+    NOT_SUPPORTED;
 
     public static RiExceptionSeen get(boolean value) {
         return value ? TRUE : FALSE;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Fri Feb 10 11:14:51 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Fri Feb 10 14:36:19 2012 -0800
@@ -49,6 +49,7 @@
     public static int     MaximumTrivialSize                 = 6;
     public static int     MaximumInlineLevel                 = 30;
     public static int     MaximumDesiredSize                 = 6000;
+    public static int     MaximumRecursiveInlining           = 1;
     // WeightBasedInliningPolicy (0)
     public static boolean ParseBeforeInlining                = ____;
     public static float   InliningSizePenaltyExp             = 20;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Feb 10 11:14:51 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Feb 10 14:36:19 2012 -0800
@@ -74,7 +74,7 @@
         graph.createNodeMap();
 
         if (hints != null) {
-            scanInvokes((Iterable<? extends Node>) Util.uncheckedCast(this.hints), 0, graph);
+            scanInvokes((Iterable<? extends Node>) Util.uncheckedCast(this.hints), -1, graph);
         } else {
             scanInvokes(graph.getNodes(InvokeNode.class), 0, graph);
             scanInvokes(graph.getNodes(InvokeWithExceptionNode.class), 0, graph);
@@ -109,7 +109,7 @@
                         throw e.addContext(info.toString());
                     }
                 }
-                if (newNodes != null && info.level <= GraalOptions.MaximumInlineLevel) {
+                if (newNodes != null && info.level < GraalOptions.MaximumInlineLevel) {
                     scanInvokes(newNodes, info.level + 1, graph);
                 }
             }
@@ -132,8 +132,9 @@
     }
 
     private void scanInvoke(Invoke invoke, int level) {
-        InlineInfo info = InliningUtil.getInlineInfo(invoke, level, runtime, assumptions, this);
+        InlineInfo info = InliningUtil.getInlineInfo(invoke, level >= 0 ? level : computeInliningLevel(invoke), runtime, assumptions, this);
         if (info != null) {
+            assert level == -1 || computeInliningLevel(invoke) == level : "outer FramesStates must match inlining level";
             metricInliningConsidered.increment();
             inlineCandidates.add(info);
         }
@@ -187,6 +188,16 @@
         assumptions.recordConcreteMethod(method, context, impl);
     }
 
+    private static int computeInliningLevel(Invoke invoke) {
+        int count = 0;
+        FrameState curState = invoke.stateAfter();
+        while (curState != null) {
+            count++;
+            curState = curState.outerFrameState();
+        }
+        return count - 1;
+    }
+
     private InliningPolicy createInliningPolicy() {
         if (GraalOptions.InliningPolicy == 0) {
             return new WeightBasedInliningPolicy();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Fri Feb 10 11:14:51 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Fri Feb 10 14:36:19 2012 -0800
@@ -499,7 +499,7 @@
         MethodCallTargetNode callTarget = invoke.callTarget();
 
         if (callTarget.invokeKind() == InvokeKind.Special || callTarget.targetMethod().canBeStaticallyBound()) {
-            if (checkTargetConditions(callTarget.targetMethod())) {
+            if (checkTargetConditions(invoke, callTarget.targetMethod())) {
                 double weight = callback == null ? 0 : callback.inliningWeight(parent, callTarget.targetMethod(), invoke);
                 return new ExactInlineInfo(invoke, weight, level, callTarget.targetMethod());
             }
@@ -509,7 +509,7 @@
             RiResolvedType exact = callTarget.receiver().exactType();
             assert exact.isSubtypeOf(callTarget.targetMethod().holder()) : exact + " subtype of " + callTarget.targetMethod().holder();
             RiResolvedMethod resolved = exact.resolveMethodImpl(callTarget.targetMethod());
-            if (checkTargetConditions(resolved)) {
+            if (checkTargetConditions(invoke, resolved)) {
                 double weight = callback == null ? 0 : callback.inliningWeight(parent, resolved, invoke);
                 return new ExactInlineInfo(invoke, weight, level, resolved);
             }
@@ -529,7 +529,7 @@
         if (assumptions != null) {
             RiResolvedMethod concrete = holder.uniqueConcreteMethod(callTarget.targetMethod());
             if (concrete != null) {
-                if (checkTargetConditions(concrete)) {
+                if (checkTargetConditions(invoke, concrete)) {
                     double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
                     return new AssumptionInlineInfo(invoke, weight, level, holder, concrete);
                 }
@@ -551,7 +551,7 @@
                     if (GraalOptions.InlineMonomorphicCalls) {
                         RiResolvedType type = types[0];
                         RiResolvedMethod concrete = type.resolveMethodImpl(callTarget.targetMethod());
-                        if (checkTargetConditions(concrete)) {
+                        if (checkTargetConditions(invoke, concrete)) {
                             double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
                             return new TypeGuardInlineInfo(invoke, weight, level, concrete, type);
                         }
@@ -589,7 +589,7 @@
                         double totalWeight = 0;
                         boolean canInline = true;
                         for (RiResolvedMethod concrete: concreteMethods) {
-                            if (!checkTargetConditions(concrete)) {
+                            if (!checkTargetConditions(invoke, concrete)) {
                                 canInline = false;
                                 break;
                             }
@@ -645,9 +645,9 @@
         return true;
     }
 
-    private static boolean checkTargetConditions(RiMethod method) {
+    private static boolean checkTargetConditions(Invoke invoke, RiMethod method) {
         if (method == null) {
-            Debug.log("method not resolved");
+            Debug.log("not inlining because method is not resolved");
             return false;
         }
         if (!(method instanceof RiResolvedMethod)) {
@@ -671,9 +671,28 @@
             Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod));
             return false;
         }
+        if (computeRecursiveInliningLevel(invoke.stateAfter(), (RiResolvedMethod) method) > GraalOptions.MaximumRecursiveInlining) {
+            Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(resolvedMethod));
+            return false;
+        }
+
         return true;
     }
 
+    private static int computeRecursiveInliningLevel(FrameState state, RiResolvedMethod method) {
+        assert state != null;
+
+        int count = 0;
+        FrameState curState = state;
+        while (curState != null) {
+            if (curState.method() == method) {
+                count++;
+            }
+            curState = curState.outerFrameState();
+        }
+        return count;
+    }
+
     /**
      * Performs an actual inlining, thereby replacing the given invoke with the given inlineGraph.
      * @param invoke the invoke that will be replaced
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java	Fri Feb 10 11:14:51 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java	Fri Feb 10 14:36:19 2012 -0800
@@ -46,7 +46,7 @@
     // TODO (ch) use same logic as in NodeClass?
     private static final Unsafe unsafe = Unsafe.getUnsafe();
     private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(RiExceptionSeen.FALSE);
-    private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLE_ACCESSOR = new NoMethodData(RiExceptionSeen.UNKNOWN);
+    private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(RiExceptionSeen.NOT_SUPPORTED);
     private static final HotSpotVMConfig config;
     // sorted by tag
     private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
@@ -97,12 +97,12 @@
         return getData(position);
     }
 
-    public static HotSpotMethodDataAccessor getNoDataNoExceptionAccessor() {
-        return NO_DATA_NO_EXCEPTION_ACCESSOR;
-    }
-
-    public static HotSpotMethodDataAccessor getNoDataExceptionPossibleAccessor() {
-        return NO_DATA_EXCEPTION_POSSIBLE_ACCESSOR;
+    public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) {
+        if (exceptionPossiblyNotRecorded) {
+            return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR;
+        } else {
+            return NO_DATA_NO_EXCEPTION_ACCESSOR;
+        }
     }
 
     private HotSpotMethodDataAccessor getData(int position) {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotNoProfilingInfo.java	Fri Feb 10 11:14:51 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotNoProfilingInfo.java	Fri Feb 10 14:36:19 2012 -0800
@@ -36,7 +36,7 @@
      */
     private static final long serialVersionUID = 4357945025049704109L;
     // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in case of a deoptimization.
-    private static final HotSpotMethodDataAccessor noData = HotSpotMethodData.getNoDataNoExceptionAccessor();
+    private static final HotSpotMethodDataAccessor noData = HotSpotMethodData.getNoDataAccessor(false);
 
     public HotSpotNoProfilingInfo(Compiler compiler) {
         super(compiler);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotProfilingInfo.java	Fri Feb 10 11:14:51 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotProfilingInfo.java	Fri Feb 10 14:36:19 2012 -0800
@@ -129,8 +129,8 @@
         setCurrentData(data, pos);
     }
 
-    private void noDataFound(boolean exceptionPossible) {
-        HotSpotMethodDataAccessor accessor = exceptionPossible ? HotSpotMethodData.getNoDataNoExceptionAccessor() : HotSpotMethodData.getNoDataNoExceptionAccessor();
+    private void noDataFound(boolean exceptionPossiblyNotRecorded) {
+        HotSpotMethodDataAccessor accessor = HotSpotMethodData.getNoDataAccessor(exceptionPossiblyNotRecorded);
         setCurrentData(accessor, -1);
     }