changeset 7065:cfacf5d5bade

fixed logging of inlining decisions
author Christian Haeubl <haeubl@ssw.jku.at>
date Fri, 23 Nov 2012 11:40:17 +0100
parents 8d16b9b2c51e
children 7d815d842ee0
files graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java
diffstat 3 files changed, 113 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Thu Nov 22 13:30:14 2012 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Fri Nov 23 11:40:17 2012 +0100
@@ -106,7 +106,7 @@
 
     public void log(String msg, Object... args) {
         if (isLogEnabled()) {
-            if (lastLogScope.get() != this) {
+            if (lastLogScope.get() == null || !lastLogScope.get().qualifiedName.equals(this.qualifiedName)) {
                 output.println("scope: " + qualifiedName);
                 lastLogScope.set(this);
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Nov 22 13:30:14 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Fri Nov 23 11:40:17 2012 +0100
@@ -28,7 +28,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -148,16 +147,16 @@
     private abstract static class AbstractInliningDecision implements InliningDecision {
         public static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) {
             boolean success = info.weight() <= maxSize;
-            if (DebugScope.getInstance().isLogEnabled()) {
-                String formatterString = success ? "inlining %s (size %f <= %f)" : "not inlining %s (too large %f > %f)";
-                Debug.log(formatterString, InliningUtil.methodName(info), info.weight(), maxSize);
+            if (GraalOptions.Debug) {
+                String formatterString = success ? "(size %f <= %f)" : "(too large %f > %f)";
+                InliningUtil.logInliningDecision(info, success, formatterString, info.weight(), maxSize);
             }
             return success;
         }
 
         public static boolean checkCompiledCodeSize(InlineInfo info) {
             if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) {
-                Debug.log("not inlining %s (CompiledCodeSize %d > %d)", InliningUtil.methodName(info), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize);
+                InliningUtil.logNotInlinedMethod(info, "(CompiledCodeSize %d > %d)", info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize);
                 return false;
             }
             return true;
@@ -231,6 +230,20 @@
         }
     }
 
+    private static class GreedyMachineCodeInliningDecision extends AbstractInliningDecision {
+        @Override
+        public boolean isWorthInlining(InlineInfo info) {
+            assert GraalOptions.ProbabilityAnalysis;
+
+            double maxSize = GraalOptions.MaximumGreedyInlineSize;
+            double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability());
+            maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio;
+            maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
+
+            return decideSizeBasedInlining(info, maxSize);
+        }
+    }
+
     private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy {
         @Override
         public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
@@ -253,6 +266,14 @@
         }
     }
 
+    private static class CompiledCodeSizeWeightComputationPolicy implements WeightComputationPolicy {
+        @Override
+        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
+            int compiledCodeSize = method.getCompiledCodeSize();
+            return compiledCodeSize > 0 ? compiledCodeSize : method.getCodeSize() * 10;
+        }
+    }
+
     private static class CFInliningPolicy implements InliningPolicy {
         private final InliningDecision inliningDecision;
         private final WeightComputationPolicy weightComputationPolicy;
@@ -516,6 +537,7 @@
             case 2: return new MinimumCodeSizeBasedInliningDecision();
             case 3: return new DynamicSizeBasedInliningDecision();
             case 4: return new GreedySizeBasedInliningDecision();
+            case 5: return new GreedyMachineCodeInliningDecision();
             default:
                 GraalInternalError.shouldNotReachHere();
                 return null;
@@ -527,6 +549,7 @@
             case 0: throw new GraalInternalError("removed because of invokation counter changes");
             case 1: return new BytecodeSizeBasedWeightComputationPolicy();
             case 2: return new ComplexityBasedWeightComputationPolicy();
+            case 3: return new CompiledCodeSizeWeightComputationPolicy();
             default:
                 GraalInternalError.shouldNotReachHere();
                 return null;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Nov 22 13:30:14 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Nov 23 11:40:17 2012 +0100
@@ -44,6 +44,7 @@
 
 public class InliningUtil {
     private static final DebugMetric metricInliningTailDuplication = Debug.metric("InliningTailDuplication");
+    private static final String inliningDecisionsScopeString = "InliningDecisions";
 
     public interface InliningCallback {
         StructuredGraph buildGraph(final ResolvedJavaMethod method);
@@ -62,39 +63,75 @@
         double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke);
     }
 
-    public static String methodName(ResolvedJavaMethod method, Invoke invoke) {
-        if (!Debug.isLogEnabled()) {
-            return null;
-        } else if (invoke != null && invoke.stateAfter() != null) {
+    public static void logNotInlinedMethod(InlineInfo info, String msg, Object... args) {
+        logInliningDecision(info, false, msg, args);
+    }
+
+    public static void logInliningDecision(InlineInfo info, boolean success, String msg, final Object... args) {
+        if (shouldLogInliningDecision()) {
+            logInliningDecision(methodName(info), success, msg, args);
+        }
+    }
+
+    public static void logInliningDecision(final String msg, final Object... args) {
+        Debug.scope(inliningDecisionsScopeString, new Runnable() {
+            public void run() {
+                Debug.log(msg, args);
+            }
+        });
+    }
+
+    private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) {
+        if (shouldLogInliningDecision()) {
+            String methodString = invoke.callTarget() == null ? "callTarget=null" : invoke.callTarget().targetName();
+            logInliningDecision(methodString, false, msg);
+        }
+        return false;
+    }
+
+    private static InlineInfo logNotInlinedMethodAndReturnNull(Invoke invoke, ResolvedJavaMethod method, String msg) {
+        if (shouldLogInliningDecision()) {
+            String methodString = methodName(method, invoke);
+            logInliningDecision(methodString, false, msg);
+        }
+        return null;
+    }
+
+    private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, ResolvedJavaMethod method, String msg) {
+        if (shouldLogInliningDecision()) {
+            String methodString = methodName(method, invoke);
+            logInliningDecision(methodString, false, msg);
+        }
+        return false;
+    }
+
+    private static void logInliningDecision(final String methodString, final boolean success, final String msg, final Object... args) {
+        String inliningMsg = "inlining " + methodString + ": " + msg;
+        if (!success) {
+            inliningMsg = "not " + inliningMsg;
+        }
+        logInliningDecision(inliningMsg, args);
+    }
+
+    private static boolean shouldLogInliningDecision() {
+        return Debug.scope(inliningDecisionsScopeString, new Callable<Boolean>() {
+            public Boolean call() {
+                return Debug.isLogEnabled();
+            }
+        });
+    }
+
+    private static String methodName(ResolvedJavaMethod method, Invoke invoke) {
+        if (invoke != null && invoke.stateAfter() != null) {
             return methodName(invoke.stateAfter(), invoke.bci()) + ": " + MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.getCodeSize() + " bytes)";
         } else {
             return MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.getCodeSize() + " bytes)";
         }
     }
 
-    public static void logInliningDecision(final String msg, final Object... args) {
-        if (GraalOptions.Debug) {
-            Debug.scope("InliningDecisions", new Runnable() {
-                public void run() {
-                    Debug.log(msg, args);
-                }
-            });
-        }
-    }
-
-    private static InlineInfo logNotInlinedMethodAndReturnNull(final String msg, final Object... args) {
-        logInliningDecision(msg, args);
-        return null;
-    }
-
-    private static boolean logNotInlinedMethodAndReturnFalse(final String msg, final Object... args) {
-        logInliningDecision(msg, args);
-        return false;
-    }
-
-    public static String methodName(InlineInfo info) {
-        if (!Debug.isLogEnabled()) {
-            return null;
+    private static String methodName(InlineInfo info) {
+        if (info == null) {
+            return "null";
         } else if (info.invoke() != null && info.invoke().stateAfter() != null) {
             return methodName(info.invoke().stateAfter(), info.invoke().bci()) + ": " + info.toString();
         } else {
@@ -657,18 +694,18 @@
         ProfilingInfo profilingInfo = caller.getProfilingInfo();
         JavaTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci());
         if (typeProfile == null) {
-            return logNotInlinedMethodAndReturnNull("not inlining %s because no type profile exists", methodName(targetMethod, invoke));
+            return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "no type profile exists");
         }
 
         ProfiledType[] ptypes = typeProfile.getTypes();
         if (ptypes == null || ptypes.length <= 0) {
-            return logNotInlinedMethodAndReturnNull("not inlining %s because no types/probabilities were recorded", methodName(targetMethod, invoke));
+            return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "no types/probabilities were recorded");
         }
 
         double notRecordedTypeProbability = typeProfile.getNotRecordedProbability();
         if (ptypes.length == 1 && notRecordedTypeProbability == 0) {
             if (!optimisticOpts.inlineMonomorphicCalls()) {
-                return logNotInlinedMethodAndReturnNull("not inlining %s because inlining monomorphic calls is disabled", methodName(targetMethod, invoke));
+                return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining monomorphic calls is disabled");
             }
 
             ResolvedJavaType type = ptypes[0].getType();
@@ -682,10 +719,10 @@
             invoke.setMegamorphic(true);
 
             if (!optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0) {
-                return logNotInlinedMethodAndReturnNull("not inlining %s because inlining polymorphic calls is disabled", methodName(targetMethod, invoke));
+                return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining polymorphic calls is disabled");
             }
             if (!optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) {
-                return logNotInlinedMethodAndReturnNull("not inlining %s because inlining megamorphic calls is disabled", methodName(targetMethod, invoke));
+                return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining megamorphic calls is disabled");
             }
 
             // TODO (chaeubl) inlining of multiple methods should work differently
@@ -712,7 +749,7 @@
             double totalWeight = 0;
             for (ResolvedJavaMethod concrete: concreteMethods) {
                 if (!checkTargetConditions(invoke, concrete, optimisticOpts, runtime)) {
-                    return logNotInlinedMethodAndReturnNull("not inlining %s because it is a polymorphic method call and at least one invoked method cannot be inlined", methodName(targetMethod, invoke));
+                    return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "it is a polymorphic method call and at least one invoked method cannot be inlined");
                 }
                 totalWeight += inliningPolicy.inliningWeight(caller, concrete, invoke);
             }
@@ -720,6 +757,7 @@
         }
     }
 
+
     private static ResolvedJavaMethod getCaller(Invoke invoke) {
         return invoke.stateAfter().method();
     }
@@ -731,15 +769,15 @@
 
     private static boolean checkInvokeConditions(Invoke invoke) {
         if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because the invoke has already been lowered, or has been created as a low-level node", invoke.callTarget() == null ? "callTarget=null" : invoke.callTarget().targetName());
+            return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has already been lowered, or has been created as a low-level node");
         } else if (invoke.methodCallTarget().targetMethod() == null) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because target method is null", invoke.toString());
+            return logNotInlinedMethodAndReturnFalse(invoke, "target method is null");
         } else if (invoke.stateAfter() == null) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because the invoke has no after state", methodName(invoke.methodCallTarget().targetMethod(), invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has no after state");
         } else if (invoke.predecessor() == null || !invoke.node().isAlive()) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because the invoke is dead code", methodName(invoke.methodCallTarget().targetMethod(), invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code");
         } else if (!invoke.useForInlining()) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because invoke is marked to be not used for inlining", methodName(invoke.methodCallTarget().targetMethod(), invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is marked to be not used for inlining");
         } else {
             return true;
         }
@@ -747,21 +785,21 @@
 
     private static boolean checkTargetConditions(Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts, GraalCodeCacheProvider runtime) {
         if (method == null) {
-            return logNotInlinedMethodAndReturnFalse("not inlining because method is not resolved");
+            return logNotInlinedMethodAndReturnFalse(invoke, method, "the method is not resolved");
         } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(invoke, method, runtime))) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because it is a non-intrinsic native method", methodName(method, invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, method, "it is a non-intrinsic native method");
         } else if (Modifier.isAbstract(method.getModifiers())) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because it is an abstract method", methodName(method, invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, method, "it is an abstract method");
         } else if (!method.getDeclaringClass().isInitialized()) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because of non-initialized class", methodName(method, invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, method, "the method's class is not initialized");
         } else if (!method.canBeInlined()) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because it is marked non-inlinable", methodName(method, invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, method, "it is marked non-inlinable");
         } else if (computeInliningLevel(invoke) > GraalOptions.MaximumInlineLevel) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because it excees the maximum inlining depth", methodName(method, invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, method, "it exceeds the maximum inlining depth");
         } else if (computeRecursiveInliningLevel(invoke.stateAfter(), method) > GraalOptions.MaximumRecursiveInlining) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(method, invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, method, "it exceeds the maximum recursive inlining depth");
         } else if (new OptimisticOptimizations(method).lessOptimisticThan(optimisticOpts)) {
-            return logNotInlinedMethodAndReturnFalse("not inlining %s because callee uses less optimistic optimizations than caller", methodName(method, invoke));
+            return logNotInlinedMethodAndReturnFalse(invoke, method, "the callee uses less optimistic optimizations than caller");
         } else {
             return true;
         }