changeset 5003:5e6f1026a63e

fixes to vtable stub inlining: compute offset on demand, look out for interface methods
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 01 Mar 2012 15:36:35 +0100
parents 6072d5da5c20
children 2792bcd9a0ce
files graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.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/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/Invoke.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 15 files changed, 108 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Thu Mar 01 15:36:35 2012 +0100
@@ -51,7 +51,7 @@
 
     XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method);
 
-    XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method);
+    XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method, boolean megamorph);
 
     XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, RiMethod method);
 
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java	Thu Mar 01 15:36:35 2012 +0100
@@ -23,7 +23,6 @@
 package com.oracle.max.cri.xir;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 
 /**
  * Encapsulates the notion of a site where XIR can be supplied. It is supplied to the {@link RiXirGenerator} by the
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Thu Mar 01 15:36:35 2012 +0100
@@ -153,7 +153,8 @@
     public static boolean GenSafepoints                      = true;
     public static boolean GenLoopSafepoints                  = true;
     public static boolean UseTypeCheckHints                  = true;
-    public static boolean InlineVTableStubs                  = ____;
+    public static boolean InlineVTableStubs                  = true;
+    public static boolean AlwaysInlineVTableStubs            = true;
 
     public static boolean GenAssertionCode                   = ____;
     public static boolean AlignCallsForPatching              = true;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Mar 01 15:36:35 2012 +0100
@@ -931,7 +931,7 @@
             case Virtual:
                 assert callTarget.receiver().kind() == CiKind.Object : callTarget + ": " + callTarget.targetMethod().toString();
                 receiver = toXirArgument(callTarget.receiver());
-                snippet = xir.genInvokeVirtual(site(x.node(), callTarget.receiver()), receiver, targetMethod);
+                snippet = xir.genInvokeVirtual(site(x.node(), callTarget.receiver()), receiver, targetMethod, x.megamorph());
                 break;
             case Interface:
                 assert callTarget.receiver().kind() == CiKind.Object : callTarget;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Thu Mar 01 15:36:35 2012 +0100
@@ -605,10 +605,11 @@
                         Debug.log("not inlining %s because method can't be inlined", methodName(targetMethod, invoke));
                         return null;
                     } else {
-                        Debug.log("not inlining %s because GraalOptions.InlinePolymorphicCalls == false", methodName(targetMethod, invoke));
+                        Debug.log("not inlining %s because GraalOptions.InlineMonomorphicCalls == false", methodName(targetMethod, invoke));
                         return null;
                     }
                 } else {
+                    invoke.setMegamorph(true);
                     if (GraalOptions.InlinePolymorphicCalls && notRecordedTypeProbability == 0 || GraalOptions.InlineMegamorphicCalls && notRecordedTypeProbability > 0) {
                         // TODO (ch) inlining of multiple methods should work differently
                         // 1. check which methods can be inlined
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Thu Mar 01 15:36:35 2012 +0100
@@ -111,5 +111,7 @@
 
     Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
 
+    int RiMethod_vtableEntryOffset(HotSpotMethodResolved method);
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Mar 01 15:36:35 2012 +0100
@@ -159,5 +159,8 @@
     @Override
     public native Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
 
+    @Override
+    public native int RiMethod_vtableEntryOffset(HotSpotMethodResolved method);
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu Mar 01 15:36:35 2012 +0100
@@ -37,9 +37,6 @@
  */
 public final class HotSpotMethodResolvedImpl extends HotSpotMethod implements HotSpotMethodResolved {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = -5486975070147586588L;
 
     /** DO NOT USE IN JAVA CODE! */
@@ -61,7 +58,6 @@
     private boolean canBeInlined;
     private CiGenericCallback callback;
     private int compilationComplexity;
-    private int vtableEntryOffset;
 
     private HotSpotMethodResolvedImpl() {
         super(null);
@@ -357,6 +353,6 @@
 
     @Override
     public int vtableEntryOffset() {
-        return vtableEntryOffset;
+        return compiler.getVMEntries().RiMethod_vtableEntryOffset(this);
     }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Thu Mar 01 15:36:35 2012 +0100
@@ -249,45 +249,49 @@
         }
     };
 
-    private IndexTemplates invokeVirtualTemplates = new IndexTemplates(NULL_CHECK) {
+    private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(CiXirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
+            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
+            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
+            XirOperand tempO = asm.createRegister("tempO", CiKind.Object, AMD64.rax);
+
+            if (is(NULL_CHECK, flags)) {
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(target.wordKind, temp, receiver, true);
+            }
+            asm.mark(MARK_INVOKEVIRTUAL);
+            asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
+
+            return asm.finishTemplate(addr, "invokevirtual");
+        }
+    };
+
+    private IndexTemplates inlinedInvokeVirtualTemplates = new IndexTemplates(NULL_CHECK) {
 
         @Override
         protected XirTemplate create(CiXirAssembler asm, long flags, int vtableEntryOffset) {
-            if (GraalOptions.InlineVTableStubs) {
-                asm.restart();
-                XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
-                XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
-                XirOperand method = asm.createRegisterTemp("method", CiKind.Object, AMD64.rbx);
-
-                // load class from receiver
-                if (is(NULL_CHECK, flags)) {
-                    asm.mark(MARK_IMPLICIT_NULL);
-                }
-                asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), true);
-                // load vtable entry
-                asm.pload(target.wordKind, method, temp, asm.i(vtableEntryOffset), false);
-                // load entry point from methodOop
-                asm.mark(MARK_IMPLICIT_NULL);
-                asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true);
-                asm.mark(MARK_INVOKEVIRTUAL);
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
+            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
+            XirOperand method = asm.createRegisterTemp("method", CiKind.Object, AMD64.rbx);
 
-                return asm.finishTemplate(temp, "invokevirtual");
-            } else {
-                asm.restart();
-                XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object);
-                XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
-                XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
-                XirOperand tempO = asm.createRegister("tempO", CiKind.Object, AMD64.rax);
+            // load class from receiver
+            if (is(NULL_CHECK, flags)) {
+                asm.mark(MARK_IMPLICIT_NULL);
+            }
+            asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), true);
+            // load vtable entry
+            asm.pload(target.wordKind, method, temp, asm.i(vtableEntryOffset), false);
+            // load entry point from methodOop
+            asm.mark(MARK_IMPLICIT_NULL);
+            asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true);
+            asm.mark(MARK_INVOKEVIRTUAL);
 
-                if (is(NULL_CHECK, flags)) {
-                    asm.mark(MARK_IMPLICIT_NULL);
-                    asm.pload(target.wordKind, temp, receiver, true);
-                }
-                asm.mark(MARK_INVOKEVIRTUAL);
-                asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
-
-                return asm.finishTemplate(addr, "invokevirtual");
-            }
+            return asm.finishTemplate(temp, "invokevirtual");
         }
     };
 
@@ -1250,12 +1254,19 @@
     }
 
     @Override
-    public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) {
-        HotSpotMethodResolved hsMethod = (HotSpotMethodResolved) method;
-        if (GraalOptions.InlineVTableStubs) {
-            return new XirSnippet(invokeVirtualTemplates.get(site, hsMethod.vtableEntryOffset()), receiver);
+    public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method, boolean megamorph) {
+        int vtableEntryOffset = 0;
+
+        if (GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || megamorph)) {
+            HotSpotMethodResolved hsMethod = (HotSpotMethodResolved) method;
+            if (!hsMethod.holder().isInterface()) {
+                vtableEntryOffset = hsMethod.vtableEntryOffset();
+            }
+        }
+        if (vtableEntryOffset > 0) {
+            return new XirSnippet(inlinedInvokeVirtualTemplates.get(site, vtableEntryOffset), receiver);
         } else {
-            return new XirSnippet(invokeVirtualTemplates.get(site, hsMethod.vtableEntryOffset()), receiver, wordArg(0));
+            return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0));
         }
     }
 
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/Invoke.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/Invoke.java	Thu Mar 01 15:36:35 2012 +0100
@@ -52,4 +52,8 @@
     boolean useForInlining();
 
     void setUseForInlining(boolean value);
+
+    boolean megamorph();
+
+    void setMegamorph(boolean megamorph);
 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeNode.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeNode.java	Thu Mar 01 15:36:35 2012 +0100
@@ -38,6 +38,8 @@
 
     @Input private final MethodCallTargetNode callTarget;
     @Data private final int bci;
+    // megamorph should only be true when the compiler is sure that the call site is megamorph, and false when in doubt
+    @Data private boolean megamorph;
     private boolean useForInlining;
 
     /**
@@ -52,6 +54,7 @@
         super(callTarget.returnStamp());
         this.callTarget = callTarget;
         this.bci = bci;
+        this.megamorph = false;
         this.useForInlining = true;
     }
 
@@ -59,6 +62,16 @@
         return callTarget;
     }
 
+    @Override
+    public boolean megamorph() {
+        return megamorph;
+    }
+
+    @Override
+    public void setMegamorph(boolean megamorph) {
+        this.megamorph = megamorph;
+    }
+
     public boolean useForInlining() {
         return useForInlining;
     }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java	Thu Mar 01 12:26:32 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java	Thu Mar 01 15:36:35 2012 +0100
@@ -26,7 +26,6 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.graph.Node.*;
 import com.oracle.max.graal.nodes.extended.*;
 import com.oracle.max.graal.nodes.java.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -39,6 +38,8 @@
     @Input private final MethodCallTargetNode callTarget;
     @Input private FrameState stateAfter;
     @Data private final int bci;
+    // megamorph should only be true when the compiler is sure that the call site is megamorph, and false when in doubt
+    @Data private boolean megamorph;
     private boolean useForInlining;
 
     /**
@@ -50,6 +51,7 @@
         super(callTarget.returnStamp(), new BeginNode[]{null, exceptionEdge}, new double[]{1.0, 0.0});
         this.bci = bci;
         this.callTarget = callTarget;
+        this.megamorph = true;
         this.useForInlining = true;
     }
 
@@ -74,6 +76,16 @@
     }
 
     @Override
+    public boolean megamorph() {
+        return megamorph;
+    }
+
+    @Override
+    public void setMegamorph(boolean megamorph) {
+        this.megamorph = megamorph;
+    }
+
+    @Override
     public boolean useForInlining() {
         return useForInlining;
     }
--- a/src/share/vm/graal/graalCompiler.cpp	Thu Mar 01 12:26:32 2012 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Mar 01 15:36:35 2012 +0100
@@ -274,17 +274,6 @@
   HotSpotMethodResolved::set_maxLocals(obj, method->max_locals());
   HotSpotMethodResolved::set_maxStackSize(obj, method->max_stack());
   HotSpotMethodResolved::set_canBeInlined(obj, !CompilerOracle::should_not_inline(method));
-
-  int vtable_entry_offset;
-  if (instanceKlass::cast(method->method_holder())->is_interface()) {
-    vtable_entry_offset = -1;
-  } else {
-    // get entry offset in words
-    vtable_entry_offset = instanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size();
-    // convert to bytes
-    vtable_entry_offset = vtable_entry_offset * wordSize + vtableEntry::method_offset_in_bytes();
-  }
-  HotSpotMethodResolved::set_vtableEntryOffset(obj, vtable_entry_offset);
   
   method->set_graal_mirror(obj());
   return obj;
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Mar 01 12:26:32 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Mar 01 15:36:35 2012 +0100
@@ -951,6 +951,21 @@
   return JNIHandles::make_local((oop) result.get_jobject());
 }
 
+// public native int RiMethod_vtableEntryOffset(HotSpotMethodResolved method);
+JNIEXPORT jint JNICALL Java_com_oracle_max_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_vtableEntryOffset(JNIEnv *, jobject, jobject hotspot_method) {
+  TRACE_graal_3("CompilerToVM::RiMethod_vtableEntryOffset");
+
+  methodOop method = getMethodFromHotSpotMethod(hotspot_method);
+  assert(!instanceKlass::cast(method->method_holder())->is_interface(), "vtableEntryOffset cannot be called for interface methods");
+
+  // get entry offset in words
+  int vtable_entry_offset = instanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size();
+  // convert to bytes
+  vtable_entry_offset = vtable_entry_offset * wordSize + vtableEntry::method_offset_in_bytes();
+
+  return vtable_entry_offset;
+}
+
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_max_graal_hotspot_bridge_CompilerToVMImpl_##f))
@@ -1013,6 +1028,7 @@
   {CC"disassembleNative",                 CC"([BJ)"STRING,                                      FN_PTR(disassembleNative)},
   {CC"disassembleJava",                   CC"("RESOLVED_METHOD")"STRING,                        FN_PTR(disassembleJava)},
   {CC"executeCompiledMethod",             CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT,    FN_PTR(executeCompiledMethod)},
+  {CC"RiMethod_vtableEntryOffset",        CC"("RESOLVED_METHOD")I",                             FN_PTR(RiMethod_vtableEntryOffset)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu Mar 01 12:26:32 2012 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Mar 01 15:36:35 2012 +0100
@@ -69,7 +69,6 @@
     int_field(HotSpotMethodResolved, maxStackSize)                                      \
     boolean_field(HotSpotMethodResolved, canBeInlined)                                  \
     oop_field(HotSpotMethodResolved, callback, "Lcom/oracle/max/cri/ci/CiGenericCallback;") \
-    int_field(HotSpotMethodResolved, vtableEntryOffset)                                 \
   end_class                                                                             \
   start_class(HotSpotMethodData)                                                        \
     oop_field(HotSpotMethodData, compiler, "Lcom/oracle/max/graal/hotspot/Compiler;")   \