# HG changeset patch # User Lukas Stadler # Date 1330612595 -3600 # Node ID 5e6f1026a63ec2afe67ce0451ab64fed503d5998 # Parent 6072d5da5c20b5b2381290b6e520587948d49353 fixes to vtable stub inlining: compute offset on demand, look out for interface methods diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java --- 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); diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java --- 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 diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- 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; diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- 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; diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java --- 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 diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java --- 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 } diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java --- 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 } diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java --- 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); } } diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java --- 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)); } } diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/Invoke.java --- 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); } diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeNode.java --- 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; } diff -r 6072d5da5c20 -r 5e6f1026a63e graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java --- 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; } diff -r 6072d5da5c20 -r 5e6f1026a63e src/share/vm/graal/graalCompiler.cpp --- 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; diff -r 6072d5da5c20 -r 5e6f1026a63e src/share/vm/graal/graalCompilerToVM.cpp --- 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() { diff -r 6072d5da5c20 -r 5e6f1026a63e src/share/vm/graal/graalJavaAccess.hpp --- 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;") \