changeset 7930:fe64b5da8229

Create direct call for Static and Special to avoid out-of-line patching stub.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 05 Mar 2013 16:43:26 +0100
parents 9ac11c77d128
children 57726bff1d9f
files graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java src/share/vm/graal/graalCodeInstaller.cpp
diffstat 5 files changed, 29 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- 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.
- * <p>
- * 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:
- * 
- * <pre>
- *       call L1
- *       nop
- * 
- *       ...
- * 
- *   L1: mov rbx [Method*]
- *       jmp [interpreter entry point]
- * </pre>
  */
 @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);
     }
 }
--- 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
--- 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();
--- 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;
     }
 
     /**
--- 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));