# HG changeset patch # User Christian Haeubl # Date 1328913379 28800 # Node ID 8fc6920e064b3e2f0a611814fb63c2c972b75999 # Parent b27666ff9bd6db1cfe74a713739cf35d7a0056d7 avoid recursive inlining, escape analysis does no longer restart inlining with level 0, bugfixes diff -r b27666ff9bd6 -r 8fc6920e064b graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiExceptionSeen.java --- 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; diff -r b27666ff9bd6 -r 8fc6920e064b graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- 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; diff -r b27666ff9bd6 -r 8fc6920e064b graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- 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) Util.uncheckedCast(this.hints), 0, graph); + scanInvokes((Iterable) 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(); diff -r b27666ff9bd6 -r 8fc6920e064b graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java --- 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 diff -r b27666ff9bd6 -r 8fc6920e064b graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java --- 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) { diff -r b27666ff9bd6 -r 8fc6920e064b graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotNoProfilingInfo.java --- 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); diff -r b27666ff9bd6 -r 8fc6920e064b graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotProfilingInfo.java --- 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); }