# HG changeset patch # User Lukas Stadler # Date 1330600279 -3600 # Node ID b5dc2403c1e798806286c6517401e03db0a9e536 # Parent 71bcf0a9e875c3ea76a9cef4eccad5b5449c79a6 add option to inline VTable stubs diff -r 71bcf0a9e875 -r b5dc2403c1e7 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:10:41 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Thu Mar 01 12:11:19 2012 +0100 @@ -35,6 +35,8 @@ // Checkstyle: resume + + public static int Threads = 4; public static boolean Lower = true; @@ -151,6 +153,7 @@ public static boolean GenSafepoints = true; public static boolean GenLoopSafepoints = true; public static boolean UseTypeCheckHints = true; + public static boolean InlineVTableStubs = ____; public static boolean GenAssertionCode = ____; public static boolean AlignCallsForPatching = true; diff -r 71bcf0a9e875 -r b5dc2403c1e7 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java Thu Mar 01 12:10:41 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java Thu Mar 01 12:11:19 2012 +0100 @@ -72,6 +72,7 @@ public int klassOopOffset; public int graalMirrorKlassOffset; public int nmethodEntryOffset; + public int methodCompiledEntryOffset; // methodData information public int methodDataOopDataOffset; diff -r 71bcf0a9e875 -r b5dc2403c1e7 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java Thu Mar 01 12:10:41 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java Thu Mar 01 12:11:19 2012 +0100 @@ -37,7 +37,7 @@ private static final long serialVersionUID = 156632908220561612L; private final RiResolvedMethod method; - private long nmethod; + public long nmethod; public HotSpotCompiledMethod(Compiler compiler, RiResolvedMethod method) { super(compiler); diff -r 71bcf0a9e875 -r b5dc2403c1e7 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolved.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolved.java Thu Mar 01 12:10:41 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolved.java Thu Mar 01 12:11:19 2012 +0100 @@ -29,4 +29,5 @@ RiResolvedMethod uniqueConcreteMethod(); void dumpProfile(); + int vtableEntryOffset(); } diff -r 71bcf0a9e875 -r b5dc2403c1e7 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:10:41 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Thu Mar 01 12:11:19 2012 +0100 @@ -61,6 +61,7 @@ private boolean canBeInlined; private CiGenericCallback callback; private int compilationComplexity; + private int vtableEntryOffset; private HotSpotMethodResolvedImpl() { super(null); @@ -353,4 +354,9 @@ public void setCallback(CiGenericCallback callback) { this.callback = callback; } + + @Override + public int vtableEntryOffset() { + return vtableEntryOffset; + } } diff -r 71bcf0a9e875 -r b5dc2403c1e7 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:10:41 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Thu Mar 01 12:11:19 2012 +0100 @@ -249,24 +249,45 @@ } }; - private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates invokeVirtualTemplates = new IndexTemplates(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); + 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); - if (is(NULL_CHECK, flags)) { + // 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, receiver, true); + asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true); + asm.mark(MARK_INVOKEVIRTUAL); + + 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); + + 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"); } - asm.mark(MARK_INVOKEVIRTUAL); - asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); - - return asm.finishTemplate(addr, "invokevirtual"); } }; @@ -1230,7 +1251,12 @@ @Override public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) { - return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0)); + HotSpotMethodResolved hsMethod = (HotSpotMethodResolved) method; + if (GraalOptions.InlineVTableStubs) { + return new XirSnippet(invokeVirtualTemplates.get(site, hsMethod.vtableEntryOffset()), receiver); + } else { + return new XirSnippet(invokeVirtualTemplates.get(site, hsMethod.vtableEntryOffset()), receiver, wordArg(0)); + } } @Override diff -r 71bcf0a9e875 -r b5dc2403c1e7 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:10:41 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeNode.java Thu Mar 01 12:11:19 2012 +0100 @@ -37,7 +37,7 @@ public final class InvokeNode extends AbstractStateSplit implements Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint { @Input private final MethodCallTargetNode callTarget; - private final int bci; + @Data private final int bci; private boolean useForInlining; /** diff -r 71bcf0a9e875 -r b5dc2403c1e7 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:10:41 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java Thu Mar 01 12:11:19 2012 +0100 @@ -26,6 +26,7 @@ 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.*; @@ -37,7 +38,7 @@ @Input private final MethodCallTargetNode callTarget; @Input private FrameState stateAfter; - private final int bci; + @Data private final int bci; private boolean useForInlining; /** diff -r 71bcf0a9e875 -r b5dc2403c1e7 src/cpu/x86/vm/nativeInst_x86.hpp --- a/src/cpu/x86/vm/nativeInst_x86.hpp Thu Mar 01 12:10:41 2012 +0100 +++ b/src/cpu/x86/vm/nativeInst_x86.hpp Thu Mar 01 12:11:19 2012 +0100 @@ -61,6 +61,7 @@ bool is_nop() { return ubyte_at(0) == nop_instruction_code; } bool is_dtrace_trap(); inline bool is_call(); + inline bool is_call_reg(); inline bool is_illegal(); inline bool is_return(); inline bool is_jump(); @@ -181,6 +182,28 @@ return call; } +class NativeCallReg: public NativeInstruction { + public: + enum Intel_specific_constants { + instruction_code = 0xFF, + instruction_size = 2, + instruction_offset = 0, + return_address_offset = 2 + }; + + address instruction_address() const { return addr_at(instruction_offset); } + address next_instruction_address() const { return addr_at(return_address_offset); } + + + static bool is_call_reg_at(address instr) { + return ((*instr) & 0xFF) == NativeCallReg::instruction_code; + } + + static bool is_call_reg_before(address return_address) { + return is_call_reg_at(return_address - NativeCallReg::return_address_offset); + } +}; + // An interface for accessing/manipulating native mov reg, imm32 instructions. // (used to manipulate inlined 32bit data dll calls, etc.) class NativeMovConstReg: public NativeInstruction { @@ -532,6 +555,7 @@ inline bool NativeInstruction::is_illegal() { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; } inline bool NativeInstruction::is_call() { return ubyte_at(0) == NativeCall::instruction_code; } +inline bool NativeInstruction::is_call_reg() { return ubyte_at(0) == NativeCallReg::instruction_code; } inline bool NativeInstruction::is_return() { return ubyte_at(0) == NativeReturn::instruction_code || ubyte_at(0) == NativeReturnX::instruction_code; } inline bool NativeInstruction::is_jump() { return ubyte_at(0) == NativeJump::instruction_code || diff -r 71bcf0a9e875 -r b5dc2403c1e7 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Thu Mar 01 12:10:41 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu Mar 01 12:11:19 2012 +0100 @@ -605,6 +605,7 @@ NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); jint next_pc_offset = 0x0; + bool is_call_reg = false; if (inst->is_call() || inst->is_jump()) { assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size"); next_pc_offset = pc_offset + NativeCall::instruction_size; @@ -614,6 +615,11 @@ u_char* call = (u_char*) (_instructions->start() + next_pc_offset); assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte"); next_pc_offset += 3; /* prefix byte + opcode byte + modrm byte */ + } else if (inst->is_call_reg()) { + // the inlined vtable stub contains a "call register" instruction, which isn't recognized here + assert(hotspot_method != NULL, "only valid for virtual calls"); + is_call_reg = true; + next_pc_offset = pc_offset + NativeCallReg::instruction_size; } else { runtime_call->print(); fatal("unsupported type of instruction for call site"); @@ -665,7 +671,6 @@ _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); TRACE_graal_3("relocating (stub) at %016x", inst); } else { // method != NULL - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); assert(hotspot_method != NULL, "unexpected RiMethod"); assert(debug_info != NULL, "debug info expected"); @@ -680,9 +685,13 @@ TRACE_graal_3("method call"); switch (_next_call_type) { case MARK_INVOKEVIRTUAL: + if (is_call_reg) { + break; + } case MARK_INVOKEINTERFACE: { assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand); break; @@ -690,6 +699,7 @@ case MARK_INVOKESTATIC: { assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand); break; @@ -697,6 +707,7 @@ case MARK_INVOKESPECIAL: { assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand); break; diff -r 71bcf0a9e875 -r b5dc2403c1e7 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Thu Mar 01 12:10:41 2012 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Thu Mar 01 12:11:19 2012 +0100 @@ -274,6 +274,17 @@ 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 71bcf0a9e875 -r b5dc2403c1e7 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Thu Mar 01 12:10:41 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Thu Mar 01 12:11:19 2012 +0100 @@ -808,6 +808,7 @@ set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); set_int(env, config, "graalMirrorKlassOffset", in_bytes(Klass::graal_mirror_offset())); set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes()); + set_int(env, config, "methodCompiledEntryOffset", in_bytes(methodOopDesc::from_compiled_offset())); set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far()); diff -r 71bcf0a9e875 -r b5dc2403c1e7 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Thu Mar 01 12:10:41 2012 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu Mar 01 12:11:19 2012 +0100 @@ -69,6 +69,7 @@ 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;") \