# HG changeset patch # User Christian Haeubl # Date 1332291401 25200 # Node ID 7b2efb5ff2eaf7f5157d711cacf36c5a87abfb9a # Parent 43d5ae1051f75dac76c5bad02da3d679dad86a20 better inlining debug output avoid inlining if callee is marked to use fewer optimistic optimizations than caller diff -r 43d5ae1051f7 -r 7b2efb5ff2ea graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java Tue Mar 20 16:15:27 2012 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java Tue Mar 20 17:56:41 2012 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.compiler; +import java.util.*; + import com.oracle.graal.debug.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; @@ -30,62 +32,86 @@ public final class OptimisticOptimizations { - public static OptimisticOptimizations ALL = new OptimisticOptimizations(true, true, true, true); - public static OptimisticOptimizations NONE = new OptimisticOptimizations(false, false, false, false); + public static final OptimisticOptimizations ALL = new OptimisticOptimizations(EnumSet.allOf(Optimization.class)); + public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class)); private static final DebugMetric disabledOptimisticOptsMetric = Debug.metric("DisabledOptimisticOpts"); - private final boolean removeNeverExecutedCode; - private final boolean useTypeCheckedInlining; - private final boolean useTypeCheckHints; - private final boolean useExceptionProbability; - - public OptimisticOptimizations(RiResolvedMethod method) { - RiProfilingInfo profilingInfo = method.profilingInfo(); - removeNeverExecutedCode = checkDeoptimization(method, profilingInfo, RiDeoptReason.UnreachedCode); - useTypeCheckedInlining = checkDeoptimization(method, profilingInfo, RiDeoptReason.TypeCheckedInliningViolated); - useTypeCheckHints = checkDeoptimization(method, profilingInfo, RiDeoptReason.OptimizedTypeCheckViolated); - useExceptionProbability = checkDeoptimization(method, profilingInfo, RiDeoptReason.NotCompiledExceptionHandler); + private static enum Optimization { + RemoveNeverExecutedCode, + UseTypeCheckedInlining, + UseTypeCheckHints, + UseExceptionProbability } - private static boolean checkDeoptimization(RiResolvedMethod method, RiProfilingInfo profilingInfo, RiDeoptReason reason) { - boolean result = profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization; - if (!result) { - if (GraalOptions.PrintDisabledOptimisticOptimizations) { - TTY.println("WARN: deactivated optimistic optimizations for %s because of %s", CiUtil.format("%H.%n(%p)", method), reason.name()); - } - disabledOptimisticOptsMetric.increment(); + private final Set enabledOpts; + + public OptimisticOptimizations(RiResolvedMethod method) { + this.enabledOpts = EnumSet.noneOf(Optimization.class); + + RiProfilingInfo profilingInfo = method.profilingInfo(); + if (checkDeoptimizations(profilingInfo, RiDeoptReason.UnreachedCode)) { + enabledOpts.add(Optimization.RemoveNeverExecutedCode); } - return result; + if (checkDeoptimizations(profilingInfo, RiDeoptReason.TypeCheckedInliningViolated)) { + enabledOpts.add(Optimization.UseTypeCheckedInlining); + } + if (checkDeoptimizations(profilingInfo, RiDeoptReason.OptimizedTypeCheckViolated)) { + enabledOpts.add(Optimization.UseTypeCheckHints); + } + if (checkDeoptimizations(profilingInfo, RiDeoptReason.NotCompiledExceptionHandler)) { + enabledOpts.add(Optimization.UseExceptionProbability); + } } - public OptimisticOptimizations(boolean removeNeverExecutedCode, boolean useTypeCheckedInlining, boolean useTypeCheckHints, boolean useExceptionProbability) { - this.removeNeverExecutedCode = removeNeverExecutedCode; - this.useTypeCheckedInlining = useTypeCheckedInlining; - this.useTypeCheckHints = useTypeCheckHints; - this.useExceptionProbability = useExceptionProbability; + private OptimisticOptimizations(Set enabledOpts) { + this.enabledOpts = enabledOpts; + } + + public void log(RiMethod method) { + for (Optimization opt: Optimization.values()) { + if (!enabledOpts.contains(opt)) { + if (GraalOptions.PrintDisabledOptimisticOptimizations) { + TTY.println("WARN: deactivated optimistic optimization %s for %s", opt.name(), CiUtil.format("%H.%n(%p)", method)); + } + disabledOptimisticOptsMetric.increment(); + } + } } public boolean removeNeverExecutedCode() { - return GraalOptions.RemoveNeverExecutedCode && removeNeverExecutedCode; + return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode); } public boolean useUseTypeCheckHints() { - return GraalOptions.UseTypeCheckHints && useTypeCheckHints; + return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints); } public boolean inlineMonomorphicCalls() { - return GraalOptions.InlineMonomorphicCalls && useTypeCheckedInlining; + return GraalOptions.InlineMonomorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining); } public boolean inlinePolymorphicCalls() { - return GraalOptions.InlinePolymorphicCalls && useTypeCheckedInlining; + return GraalOptions.InlinePolymorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining); } public boolean inlineMegamorphicCalls() { - return GraalOptions.InlineMegamorphicCalls && useTypeCheckedInlining; + return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining); } public boolean useExceptionProbability() { - return useExceptionProbability; + return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability); + } + + public boolean lessOptimisticThan(OptimisticOptimizations other) { + for (Optimization opt: Optimization.values()) { + if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) { + return true; + } + } + return false; + } + + private static boolean checkDeoptimizations(RiProfilingInfo profilingInfo, RiDeoptReason reason) { + return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization; } } diff -r 43d5ae1051f7 -r 7b2efb5ff2ea graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Tue Mar 20 16:15:27 2012 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Tue Mar 20 17:56:41 2012 -0700 @@ -51,23 +51,23 @@ void recordConcreteMethodAssumption(RiResolvedMethod method, RiResolvedType context, RiResolvedMethod impl); } - public static String methodName(RiResolvedMethod method) { - return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; - } - private static String methodName(RiResolvedMethod method, Invoke invoke) { if (Debug.isLogEnabled()) { if (invoke != null && invoke.stateAfter() != null) { RiMethod parent = invoke.stateAfter().method(); - return parent.name() + "@" + invoke.bci() + ": " + CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; + return parent.name() + "@" + invoke.bci() + ": " + methodNameAndCodeSize(method); } else { - return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; + return methodNameAndCodeSize(method); } } else { return null; } } + private static String methodNameAndCodeSize(RiResolvedMethod method) { + return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)"; + } + /** * Represents an opportunity for inlining at the given invoke, with the given weight and level. * The weight is the amortized weight of the additional code - so smaller is better. @@ -541,18 +541,18 @@ * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke */ public static InlineInfo getInlineInfo(Invoke invoke, int level, GraalRuntime runtime, CiAssumptions assumptions, InliningCallback callback, OptimisticOptimizations optimisticOpts) { - if (!checkInvokeConditions(invoke)) { - return null; - } RiResolvedMethod parent = invoke.stateAfter().method(); MethodCallTargetNode callTarget = invoke.callTarget(); RiResolvedMethod targetMethod = callTarget.targetMethod(); - if (targetMethod == null) { return null; } + if (!checkInvokeConditions(invoke)) { + return null; + } + if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) { - if (checkTargetConditions(invoke, targetMethod)) { + if (checkTargetConditions(invoke, targetMethod, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, targetMethod, invoke); return new ExactInlineInfo(invoke, weight, level, targetMethod); } @@ -562,7 +562,7 @@ RiResolvedType exact = callTarget.receiver().exactType(); assert exact.isSubtypeOf(targetMethod.holder()) : exact + " subtype of " + targetMethod.holder() + " for " + targetMethod; RiResolvedMethod resolved = exact.resolveMethodImpl(targetMethod); - if (checkTargetConditions(invoke, resolved)) { + if (checkTargetConditions(invoke, resolved, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, resolved, invoke); return new ExactInlineInfo(invoke, weight, level, resolved); } @@ -582,7 +582,7 @@ if (assumptions != null) { RiResolvedMethod concrete = holder.uniqueConcreteMethod(targetMethod); if (concrete != null) { - if (checkTargetConditions(invoke, concrete)) { + if (checkTargetConditions(invoke, concrete, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke); return new AssumptionInlineInfo(invoke, weight, level, holder, concrete); } @@ -608,7 +608,7 @@ if (optimisticOpts.inlineMonomorphicCalls()) { RiResolvedType type = types[0]; RiResolvedMethod concrete = type.resolveMethodImpl(targetMethod); - if (checkTargetConditions(invoke, concrete)) { + if (checkTargetConditions(invoke, concrete, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke); return new TypeGuardInlineInfo(invoke, weight, level, concrete, type); } @@ -647,7 +647,7 @@ double totalWeight = 0; boolean canInline = true; for (RiResolvedMethod concrete: concreteMethods) { - if (!checkTargetConditions(invoke, concrete)) { + if (!checkTargetConditions(invoke, concrete, optimisticOpts)) { canInline = false; break; } @@ -702,7 +702,7 @@ return true; } - private static boolean checkTargetConditions(Invoke invoke, RiMethod method) { + private static boolean checkTargetConditions(Invoke invoke, RiMethod method, OptimisticOptimizations optimisticOpts) { if (method == null) { Debug.log("not inlining because method is not resolved"); return false; @@ -713,23 +713,28 @@ } RiResolvedMethod resolvedMethod = (RiResolvedMethod) method; if (Modifier.isNative(resolvedMethod.accessFlags())) { - Debug.log("not inlining %s because it is a native method", methodName(resolvedMethod)); + Debug.log("not inlining %s because it is a native method", methodName(resolvedMethod, invoke)); return false; } if (Modifier.isAbstract(resolvedMethod.accessFlags())) { - Debug.log("not inlining %s because it is an abstract method", methodName(resolvedMethod)); + Debug.log("not inlining %s because it is an abstract method", methodName(resolvedMethod, invoke)); return false; } if (!resolvedMethod.holder().isInitialized()) { - Debug.log("not inlining %s because of non-initialized class", methodName(resolvedMethod)); + Debug.log("not inlining %s because of non-initialized class", methodName(resolvedMethod, invoke)); return false; } if (!resolvedMethod.canBeInlined()) { - Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod)); + Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod, invoke)); 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)); + Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(resolvedMethod, invoke)); + return false; + } + OptimisticOptimizations calleeOpts = new OptimisticOptimizations(resolvedMethod); + if (calleeOpts.lessOptimisticThan(optimisticOpts)) { + Debug.log("not inlining %s because callee uses less optimistic optimizations than caller", methodName(resolvedMethod, invoke)); return false; } diff -r 43d5ae1051f7 -r 7b2efb5ff2ea graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Mar 20 16:15:27 2012 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Mar 20 17:56:41 2012 -0700 @@ -299,9 +299,6 @@ public void run() { try { - if (method.name().contains("accept") && method.holder().name().contains("ClassReader")) { - throw new AssertionError("Stop compiling"); - } final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method); final PhasePlan plan = createHotSpotSpecificPhasePlan(optimisticOpts); long startTime = System.nanoTime(); @@ -310,6 +307,7 @@ if (printCompilation) { TTY.println(String.format("Graal %4d %-70s %-45s %-50s ...", index, method.holder().name(), method.name(), method.signature().asString())); } + optimisticOpts.log(method); CiTargetMethod result = null; TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);