# HG changeset patch # User Thomas Wuerthinger # Date 1362498206 -3600 # Node ID fe64b5da82291675dc9afd3e350f0cedd08a30a6 # Parent 9ac11c77d12858f742e00455f1f680be538d3c8b Create direct call for Static and Special to avoid out-of-line patching stub. diff -r 9ac11c77d128 -r fe64b5da8229 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Tue Mar 05 11:49:29 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Tue Mar 05 16:43:26 2013 +0100 @@ -25,7 +25,6 @@ import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*; import com.oracle.graal.amd64.*; -import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.bridge.*; @@ -42,82 +41,27 @@ * This instruction (which moves 0L in RAX) is patched by the C++ Graal code to replace the 0L * constant with Universe::non_oop_word(), a special sentinel used for the initial value of the * Klass in an inline cache. - *

- * For non-inline cache calls (i.e., INVOKESTATIC and INVOKESPECIAL), a static call stub is emitted. - * Initially, these calls go to the global static call resolution stub (i.e., - * SharedRuntime::get_resolve_static_call_stub()). Resolution will link the call to a compiled - * version of the callee if available otherwise to the interpreter. The interpreter expects to find - * the Method* for the callee in RBX. To achieve this, the static call is linked to a static call - * stub which initializes RBX and jumps to the interpreter. This pattern is shown below: - * - *

- *       call L1
- *       nop
- * 
- *       ...
- * 
- *   L1: mov rbx [Method*]
- *       jmp [interpreter entry point]
- * 
*/ @Opcode("CALL_DIRECT") final class AMD64DirectCallOp extends DirectCallOp { - /** - * The mark emitted at the position of the direct call instruction. This is only recorded for - * calls that have an associated static call stub (i.e., - * {@code invokeKind == Static || invokeKind == Special}). - */ - Mark callsiteMark; - private final InvokeKind invokeKind; - AMD64DirectCallOp(InvokeTarget target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, LIR lir) { + AMD64DirectCallOp(InvokeTarget target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) { super(target, result, parameters, temps, state); this.invokeKind = invokeKind; - - if (invokeKind == Static || invokeKind == Special) { - lir.stubs.add(new AMD64Code() { - - public String description() { - return "static call stub for Invoke" + AMD64DirectCallOp.this.invokeKind; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - assert callsiteMark != null : "static call site has not yet been emitted"; - tasm.recordMark(Marks.MARK_STATIC_CALL_STUB, callsiteMark); - masm.movq(AMD64.rbx, 0L); - int pos = masm.codeBuffer.position(); - // Create a jump-to-self as expected by CompiledStaticCall::set_to_interpreted() - // in compiledIC.cpp - masm.jmp(pos, true); - } - }); - } - + assert invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - if (invokeKind == Static || invokeKind == Special) { - tasm.recordMark(invokeKind == Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL); - } else { - assert invokeKind == Virtual || invokeKind == Interface; - // The mark for an invocation that uses an inline cache must be placed at the - // instruction - // that loads the Klass from the inline cache so that the C++ code can find it - // and replace the inline 0L value with Universe::non_oop_word() - tasm.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE); - AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Long), Constant.LONG_0); - } - + // The mark for an invocation that uses an inline cache must be placed at the + // instruction + // that loads the Klass from the inline cache so that the C++ code can find it + // and replace the inline 0L value with Universe::non_oop_word() + tasm.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE); + AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Long), Constant.LONG_0); emitAlignmentForDirectCall(tasm, masm); - - if (invokeKind == Static || invokeKind == Special) { - callsiteMark = tasm.recordMark(null); - } - AMD64Call.directCall(tasm, masm, callTarget, state); } } diff -r 9ac11c77d128 -r fe64b5da8229 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Mar 05 11:49:29 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Mar 05 16:43:26 2013 +0100 @@ -155,7 +155,7 @@ @Override protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - append(new AMD64DirectCallOp(callTarget.target(), result, parameters, temps, callState, ((HotSpotDirectCallTargetNode) callTarget).invokeKind(), lir)); + append(new AMD64DirectCallOp(callTarget.target(), result, parameters, temps, callState, ((HotSpotDirectCallTargetNode) callTarget).invokeKind())); } @Override diff -r 9ac11c77d128 -r fe64b5da8229 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Mar 05 11:49:29 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Mar 05 16:43:26 2013 +0100 @@ -72,6 +72,13 @@ return holder; } + /** + * Gets the address of the C++ Method object for this method. + */ + public Constant getMetaspaceMethodConstant() { + return Constant.forIntegerKind(HotSpotGraalRuntime.getInstance().getTarget().wordKind, metaspaceMethod, this); + } + @Override public int getModifiers() { HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); diff -r 9ac11c77d128 -r fe64b5da8229 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Mar 05 11:49:29 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Mar 05 16:43:26 2013 +0100 @@ -574,6 +574,14 @@ graph.addAfterFixed(metaspaceMethod, compiledEntry); } } + } else if (callTarget.invokeKind() == InvokeKind.Special || callTarget.invokeKind() == InvokeKind.Static) { + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); + ConstantNode metaspaceMethod = ConstantNode.forConstant(hsMethod.getMetaspaceMethodConstant(), this, graph); + ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), + StampFactory.forKind(wordKind()))); + loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), + CallingConvention.Type.JavaCall)); + graph.addBeforeFixed(invoke.node(), compiledEntry); } if (loweredCallTarget == null) { @@ -900,7 +908,7 @@ } public boolean needsDataPatch(Constant constant) { - return constant.getPrimitiveAnnotation() instanceof HotSpotResolvedObjectType; + return constant.getPrimitiveAnnotation() != null; } /** diff -r 9ac11c77d128 -r fe64b5da8229 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Tue Mar 05 11:49:29 2013 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Tue Mar 05 16:43:26 2013 +0100 @@ -126,6 +126,10 @@ assert((Klass*) prim == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim)); int index = oop_recorder->find_index(klass); TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string()); + } else if (obj->is_a(HotSpotResolvedJavaMethod::klass())) { + Method* method = (Method*) (address) HotSpotResolvedJavaMethod::metaspaceMethod(obj); + int index = oop_recorder->find_index(method); + TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string()); } else { assert(java_lang_String::is_instance(obj), err_msg("unexpected annotation type (%s) for constant %ld (%p) of kind %c", obj->klass()->name()->as_C_string(), prim, prim, kind));