changeset 3465:8cd198d7cbc1

When a method that has been compiled before is considered for inlining, use its compiled (native) code size for size checks. This avoids inlining compiled methods that already contain many other inlined methods, reducing generated code size and usually execution time as well. Also, add GraalMetrics bookkeeping for inlining.
author Peter Hofer <peter.hofer@jku.at>
date Mon, 01 Aug 2011 13:45:25 +0200
parents be4ca325525a
children b9f76db5ac53
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.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.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java src/share/vm/graal/graalVMEntries.cpp
diffstat 8 files changed, 75 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java	Wed Jul 27 17:32:44 2011 -0700
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java	Mon Aug 01 13:45:25 2011 +0200
@@ -41,6 +41,10 @@
     public static int InlinedFinalizerChecks;
     public static int InlineForcedMethods;
     public static int InlineForbiddenMethods;
+    public static int InlineConsidered;
+    public static int InlinePerformed;
+    public static int InlineUncompiledConsidered;
+    public static int InlineUncompiledPerformed;
     public static int BlocksDeleted;
     public static int BytecodesCompiled;
     public static int CodeBytesEmitted;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Wed Jul 27 17:32:44 2011 -0700
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Mon Aug 01 13:45:25 2011 +0200
@@ -46,9 +46,12 @@
     public static int     MaximumInstructionCount            = 3000;
     public static float   MaximumInlineRatio                 = 0.90f;
     public static int     MaximumInlineSize                  = 35;
+    public static int     MaximumInlineCompSize              = 350;
     public static int     MaximumFreqInlineSize              = 200;
+    public static int     MaximumFreqInlineCompSize          = 1500;
     public static int     FreqInlineRatio                    = 20;
     public static int     MaximumTrivialSize                 = 6;
+    public static int     MaximumTrivialCompSize             = 120;
     public static int     MaximumInlineLevel                 = 9;
     public static int     MaximumRecursiveInlineLevel        = 2;
     public static int     MaximumDesiredSize                 = 8000;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Jul 27 17:32:44 2011 -0700
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Mon Aug 01 13:45:25 2011 +0200
@@ -83,6 +83,13 @@
             newInvokes = new ArrayDeque<Invoke>();
             for (Invoke invoke : queue) {
                 if (!invoke.isDeleted()) {
+                    if (GraalOptions.Meter) {
+                        GraalMetrics.InlineConsidered++;
+                        if (!invoke.target.hasCompiledCode()) {
+                            GraalMetrics.InlineUncompiledConsidered++;
+                        }
+                    }
+
                     RiMethod code = inlineInvoke(invoke, iterations, ratio);
                     if (code != null) {
                         if (graph.getNodeCount() > GraalOptions.MaximumInstructionCount) {
@@ -97,6 +104,12 @@
                                 methodCount.put(code, methodCount.get(code) + 1);
                             }
                         }
+                        if (GraalOptions.Meter) {
+                            GraalMetrics.InlinePerformed++;
+                            if (!invoke.target.hasCompiledCode()) {
+                                GraalMetrics.InlineUncompiledPerformed++;
+                            }
+                        }
                     }
                 }
             }
@@ -303,6 +316,7 @@
 
     private boolean checkSizeConditions(RiMethod caller, int iterations, RiMethod method, Invoke invoke, RiTypeProfile profile, float adjustedRatio) {
         int maximumSize = GraalOptions.MaximumTrivialSize;
+        int maximumCompiledSize = GraalOptions.MaximumTrivialCompSize;
         double ratio = 0;
         if (profile != null && profile.count > 0) {
             RiMethod parent = invoke.stateAfter().method();
@@ -313,16 +327,27 @@
             }
             if (ratio >= GraalOptions.FreqInlineRatio) {
                 maximumSize = GraalOptions.MaximumFreqInlineSize;
+                maximumCompiledSize = GraalOptions.MaximumFreqInlineCompSize;
             } else if (ratio >= 1 * (1 - adjustedRatio)) {
                 maximumSize = GraalOptions.MaximumInlineSize;
+                maximumCompiledSize = GraalOptions.MaximumInlineCompSize;
             }
         }
         if (hints != null && hints.contains(invoke)) {
             maximumSize = GraalOptions.MaximumFreqInlineSize;
+            maximumCompiledSize = GraalOptions.MaximumFreqInlineCompSize;
         }
-        if (method.codeSize() > maximumSize || iterations >= GraalOptions.MaximumInlineLevel || (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel)) {
+        boolean oversize;
+        int compiledSize = method.compiledCodeSize();
+        if (compiledSize < 0) {
+            oversize = (method.codeSize() > maximumSize);
+        } else {
+            oversize = (compiledSize > maximumCompiledSize);
+        }
+        if (oversize || iterations >= GraalOptions.MaximumInlineLevel || (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel)) {
             if (GraalOptions.TraceInlining) {
-                TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f, %s) or inling level", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile);
+                TTY.println("not inlining %s because of size (bytecode: %d, bytecode max: %d, compiled: %d, compiled max: %d, ratio %5.3f, %s) or inlining level",
+                                methodName(method, invoke), method.codeSize(), maximumSize, compiledSize, maximumCompiledSize, ratio, profile);
             }
             if (GraalOptions.Extend) {
                 boolean newResult = overrideInliningDecision(iterations, caller, invoke.bci, method, false);
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Wed Jul 27 17:32:44 2011 -0700
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Mon Aug 01 13:45:25 2011 +0200
@@ -170,9 +170,7 @@
     }
 
     public boolean hasCompiledCode() {
-        // TODO: needs a VMEntries to go cache the result of that method.
-        // This isn't used by GRAAL for now, so this is enough.throwoutCount
-        return false;
+        return compiler.getVMEntries().RiMethod_hasCompiledCode(this);
     }
 
     @Override
@@ -210,6 +208,11 @@
         return compiler.getVMEntries().RiMethod_switchProbability(this, bci);
     }
 
+    @Override
+    public int compiledCodeSize() {
+        return compiler.getVMEntries().RiMethod_compiledCodeSize(this);
+    }
+
     public void dumpProfile() {
         TTY.println("profile info for %s", this);
         TTY.println("canBeStaticallyBound: " + canBeStaticallyBound());
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java	Wed Jul 27 17:32:44 2011 -0700
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java	Mon Aug 01 13:45:25 2011 +0200
@@ -181,4 +181,9 @@
     public double[] switchProbability(int bci) {
         return null;
     }
+
+    @Override
+    public int compiledCodeSize() {
+        return -1;
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java	Wed Jul 27 17:32:44 2011 -0700
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java	Mon Aug 01 13:45:25 2011 +0200
@@ -101,5 +101,9 @@
 
     RiField[] RiType_fields(HotSpotTypeResolved klass);
 
+    boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method);
+
+    int RiMethod_compiledCodeSize(HotSpotMethodResolved method);
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java	Wed Jul 27 17:32:44 2011 -0700
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java	Mon Aug 01 13:45:25 2011 +0200
@@ -147,5 +147,11 @@
     @Override
     public native RiField[] RiType_fields(HotSpotTypeResolved klass);
 
+    @Override
+    public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method);
+
+    @Override
+    public native int RiMethod_compiledCodeSize(HotSpotMethodResolved method);
+
     // Checkstyle: resume
 }
--- a/src/share/vm/graal/graalVMEntries.cpp	Wed Jul 27 17:32:44 2011 -0700
+++ b/src/share/vm/graal/graalVMEntries.cpp	Mon Aug 01 13:45:25 2011 +0200
@@ -183,7 +183,7 @@
   return method->invocation_count();
 }
 
-// public native int RiMethod_throwoutCount(long vmId);
+// public native int RiMethod_exceptionProbability(long vmId, int bci);
 JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_2exceptionProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) {
   TRACE_graal_3("VMEntries::RiMethod_exceptionProbability");
   ciMethod* cimethod;
@@ -337,6 +337,23 @@
   }
 }
 
+// public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method);
+JNIEXPORT jboolean JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasCompiledCode(JNIEnv *, jobject, jobject hotspot_method) {
+  TRACE_graal_3("VMEntries::RiMethod_hasCompiledCode");
+  methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+  return method->has_compiled_code();
+}
+
+// public native boolean RiMethod_compiledCodeSize(HotSpotMethodResolved method);
+JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1compiledCodeSize(JNIEnv *, jobject, jobject hotspot_method) {
+  TRACE_graal_3("VMEntries::RiMethod_compiledCodeSize");
+  nmethod* code = getMethodFromHotSpotMethod(hotspot_method)->code();
+  if (code != NULL) {
+    return code->insts_end() - code->verified_entry_point();
+  }
+  return -1;
+}
+
 // public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
 JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) {
   TRACE_graal_3("VMEntries::RiSignature_lookupType");
@@ -901,6 +918,8 @@
   {CC"RiMethod_switchProbability",      CC"("RESOLVED_METHOD"I)[D",                 FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2switchProbability)},
   {CC"RiMethod_invocationCount",        CC"("RESOLVED_METHOD")I",                   FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1invocationCount)},
   {CC"RiMethod_exceptionProbability",   CC"("RESOLVED_METHOD"I)I",                  FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2exceptionProbability)},
+  {CC"RiMethod_hasCompiledCode",        CC"("RESOLVED_METHOD")Z",                   FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasCompiledCode)},
+  {CC"RiMethod_compiledCodeSize",       CC"("RESOLVED_METHOD")I",                   FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1compiledCodeSize)},
   {CC"RiSignature_lookupType",          CC"("STRING RESOLVED_TYPE")"TYPE,           FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType)},
   {CC"RiConstantPool_lookupConstant",   CC"("PROXY"I)"OBJECT,                       FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant)},
   {CC"RiConstantPool_lookupMethod",     CC"("PROXY"IB)"METHOD,                      FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod)},