changeset 5127:7b2efb5ff2ea

better inlining debug output avoid inlining if callee is marked to use fewer optimistic optimizations than caller
author Christian Haeubl <christian.haeubl@oracle.com>
date Tue, 20 Mar 2012 17:56:41 -0700
parents 43d5ae1051f7
children ab038e0d6b43 4d8ebb0fc484
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java
diffstat 3 files changed, 85 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- 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<Optimization> 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<Optimization> 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;
     }
 }
--- 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;
         }
 
--- 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);