changeset 9054:c7f289614722

Merge.
author Roland Schatz <roland.schatz@oracle.com>
date Fri, 12 Apr 2013 18:15:44 +0200
parents 1a99a8df6dad (current diff) 1946c86f8842 (diff)
children b28c80b6ee58
files
diffstat 20 files changed, 205 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Apr 12 18:15:44 2013 +0200
@@ -405,6 +405,7 @@
                 }
                 long start = System.currentTimeMillis();
                 PhasePlan phasePlan = new PhasePlan();
+                StructuredGraph graphCopy = graph.copy();
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                 phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
@@ -414,7 +415,7 @@
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
-                return addMethod(method, compResult);
+                return addMethod(method, compResult, graphCopy);
             }
         });
 
@@ -424,12 +425,12 @@
         return installedCode;
     }
 
-    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) {
+    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) {
         return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() {
 
             @Override
             public InstalledCode call() throws Exception {
-                InstalledCode installedCode = runtime.addMethod(method, compResult);
+                InstalledCode installedCode = runtime.addMethod(method, compResult, graph);
                 if (Debug.isDumpEnabled()) {
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Fri Apr 12 18:15:44 2013 +0200
@@ -22,65 +22,77 @@
  */
 package com.oracle.graal.hotspot.test;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+import static java.lang.reflect.Modifier.*;
+
 import java.lang.reflect.*;
 
+import org.junit.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.*;
 
 public class InstalledCodeExecuteHelperTest extends GraalCompilerTest {
 
-    private static final int ITERATIONS = 100000000;
+    private static final int ITERATIONS = 100000;
+    private final MetaAccessProvider metaAccessProvider;
+    Object[] argsToBind;
 
-    // TODO this is not a test, move it somewhere else
-    // CheckStyle: stop system..print check
-    public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
-
-        final Method benchrMethod = InstalledCodeExecuteHelperTest.class.getMethod("bench", long.class, long.class);
-        final ResolvedJavaMethod benchJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(benchrMethod);
-        HotSpotInstalledCode benchCode = (HotSpotInstalledCode) getCode(benchJavaMethod, parse(benchrMethod));
+    public InstalledCodeExecuteHelperTest() {
+        this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class);
+    }
 
-        final Method wrapperMethod = InstalledCodeExecuteHelperTest.class.getMethod("executeWrapper", long.class, long.class, Object.class, Object.class, Object.class);
-        final ResolvedJavaMethod wrapperJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(wrapperMethod);
-        HotSpotInstalledCode wrapperCode = (HotSpotInstalledCode) getCode(wrapperJavaMethod, parse(wrapperMethod));
+    @Test
+    public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
 
-        final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class);
-        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(fooMethod);
-        HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        argsToBind = new Object[]{fooCode};
 
-        System.out.println(wrapperCode.executeVarargs(fooCode.getnmethod(), fooJavaMethod.getMetaspaceMethod(), null, null, null));
+        final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class);
+        final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod);
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod));
 
-        long nmethod = fooCode.getnmethod();
-        long metaspacemethod = fooJavaMethod.getMetaspaceMethod();
+        Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode));
 
-        System.out.println("Without replaced InstalledCode.execute:" + bench(nmethod, metaspacemethod));
-
-        System.out.println("WITH replaced InstalledCode.execute:" + benchCode.executeVarargs(nmethod, metaspacemethod));
+        Assert.assertEquals(Integer.valueOf(42), installedBenchmarkCode.executeVarargs(argsToBind[0]));
 
     }
 
-    // CheckStyle: resume system..print check
-
-    public static Long bench(long nmethod, long metaspacemethod) throws InvalidInstalledCodeException {
-        long start = System.currentTimeMillis();
-
-        for (int i = 0; i < ITERATIONS; i++) {
-            HotSpotInstalledCode.executeHelper(nmethod, metaspacemethod, null, null, null);
+    public static Integer benchmark(HotSpotInstalledCode code) throws InvalidInstalledCodeException {
+        int val = 0;
+        for (int j = 0; j < 100; j++) {
+            for (int i = 0; i < ITERATIONS; i++) {
+                val = (Integer) code.execute(null, null, null);
+            }
         }
-
-        long end = System.currentTimeMillis();
-        return (end - start);
+        return val;
     }
 
-    public static Object foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) {
+    public static Integer foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) {
         return 42;
     }
 
-    public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException {
-        return HotSpotInstalledCode.executeHelper(nmethod, metaspaceMethod, arg1, arg2, arg3);
+    @Override
+    protected StructuredGraph parse(Method m) {
+        StructuredGraph graph = super.parse(m);
+        if (argsToBind != null) {
+            Object receiver = isStatic(m.getModifiers()) ? null : this;
+            Object[] args = argsWithReceiver(receiver, argsToBind);
+            JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m));
+            assert parameterTypes.length == args.length;
+            for (int i = 0; i < argsToBind.length; i++) {
+                LocalNode local = graph.getLocal(i);
+                Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]);
+                ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph);
+                local.replaceAtUsages(replacement);
+            }
+        }
+        return graph;
     }
-
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri Apr 12 18:15:44 2013 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -167,7 +168,7 @@
                 }
             }
 
-            installMethod(result);
+            installMethod(result, null);
         } catch (BailoutException bailout) {
             Debug.metric("Bailouts").increment();
             if (GraalOptions.ExitVMOnBailout) {
@@ -197,12 +198,12 @@
                         MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize()));
     }
 
-    private void installMethod(final CompilationResult compResult) {
+    private void installMethod(final CompilationResult compResult, final Graph graph) {
         Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() {
 
             @Override
             public void run() {
-                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult);
+                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, graph, entryBCI, compResult);
                 if (Debug.isDumpEnabled()) {
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 12 18:15:44 2013 +0200
@@ -170,5 +170,12 @@
         return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod);
     }
 
+    /**
+     * Direct call to the given nativeMethod with three object arguments and an object return value.
+     * This method does not have an implementation on the C++ side, but its entry points (from
+     * interpreter and from compiled code) are directly pointing to a manually generated assembly
+     * stub that does the necessary argument shuffling and a tail call via an indirect jump to the
+     * verified entry point of the given native method.
+     */
     private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Fri Apr 12 18:15:44 2013 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -39,12 +40,13 @@
 
     private final HotSpotResolvedJavaMethod method;
     private final boolean isDefault;
-    private final long nmethod; // This field is set by the runtime upon code installation.
+    private final Graph graph;
+    long nmethod;
     long start;
 
-    public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) {
-        this.nmethod = 0;
+    public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) {
         this.method = method;
+        this.graph = graph;
         this.isDefault = isDefault;
     }
 
@@ -52,10 +54,14 @@
         return isDefault;
     }
 
-    public long getnmethod() {
+    public long getMethodAddress() {
         return nmethod;
     }
 
+    public Graph getGraph() {
+        return graph;
+    }
+
     @Override
     public ResolvedJavaMethod getMethod() {
         return method;
@@ -114,9 +120,4 @@
     public byte[] getCode() {
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod);
     }
-
-    @SuppressWarnings("unused")
-    public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException {
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod);
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Apr 12 18:15:44 2013 +0200
@@ -766,16 +766,21 @@
         return graalRuntime.getCompilerToVM().getJavaField(reflectionField);
     }
 
-    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) {
-        HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, true);
+    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, Graph graph, int entryBCI, CompilationResult compResult) {
+        HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, graph, true);
         graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), installedCode, method.getSpeculationLog());
         return installedCode;
     }
 
     @Override
     public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+        return addMethod(method, compResult, null);
+    }
+
+    @Override
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, false);
+        HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, graph, false);
         CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, null);
         if (result != CodeInstallResult.OK) {
             return null;
@@ -894,7 +899,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long nmethod = ((HotSpotInstalledCode) code).getnmethod();
+            long nmethod = ((HotSpotInstalledCode) code).getMethodAddress();
             return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod);
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Fri Apr 12 18:15:44 2013 +0200
@@ -24,22 +24,24 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.word.*;
+import com.oracle.graal.phases.common.*;
 
 public class HotSpotInstalledCodeExecuteNode extends AbstractCallNode implements Lowerable {
 
-    @Input private final ValueNode targetAddress;
-    @Input private final ValueNode metaspaceObject;
+    @Input private final ValueNode code;
     private final Class[] signature;
 
-    public HotSpotInstalledCodeExecuteNode(Kind kind, ValueNode targetAddress, ValueNode metaspaceObject, Class[] signature, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
+    public HotSpotInstalledCodeExecuteNode(Kind kind, Class[] signature, ValueNode code, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
         super(StampFactory.forKind(kind), new ValueNode[]{arg1, arg2, arg3});
-        this.targetAddress = targetAddress;
-        this.metaspaceObject = metaspaceObject;
+        this.code = code;
         this.signature = signature;
     }
 
@@ -50,30 +52,57 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        replaceWithInvoke(tool);
+        if (code.isConstant() && code.asConstant().asObject() instanceof HotSpotInstalledCode) {
+            HotSpotInstalledCode hsCode = (HotSpotInstalledCode) code.asConstant().asObject();
+            InvokeNode invoke = replaceWithInvoke(tool.getRuntime());
+            StructuredGraph graph = (StructuredGraph) hsCode.getGraph();
+            if (graph != null) {
+                InliningUtil.inline(invoke, (StructuredGraph) hsCode.getGraph(), false);
+            }
+        } else {
+            replaceWithInvoke(tool.getRuntime());
+        }
     }
 
-    private InvokeNode replaceWithInvoke(LoweringTool tool) {
-        InvokeNode invoke = createInvoke(tool);
-        ((StructuredGraph) graph()).replaceFixedWithFixed(this, invoke);
-        return invoke;
-    }
-
-    protected InvokeNode createInvoke(LoweringTool tool) {
+    protected InvokeNode replaceWithInvoke(MetaAccessProvider tool) {
         ResolvedJavaMethod method = null;
+        ResolvedJavaField methodField = null;
+        ResolvedJavaField metaspaceMethodField = null;
+        ResolvedJavaField nmethodField = null;
         try {
-            method = tool.getRuntime().lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class));
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw new IllegalStateException();
+            method = tool.lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class));
+            methodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("method"));
+            nmethodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("nmethod"));
+            metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod"));
+        } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) {
+            throw new IllegalStateException(e);
         }
         ResolvedJavaType[] signatureTypes = new ResolvedJavaType[signature.length];
         for (int i = 0; i < signature.length; i++) {
-            signatureTypes[i] = tool.getRuntime().lookupJavaType(signature[i]);
+            signatureTypes[i] = tool.lookupJavaType(signature[i]);
         }
-        HotSpotIndirectCallTargetNode callTarget = graph().add(
-                        new HotSpotIndirectCallTargetNode(metaspaceObject, targetAddress, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall));
-        InvokeNode invoke = graph().add(new InvokeNode(callTarget, 0));
+        final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset();
+
+        StructuredGraph g = (StructuredGraph) graph();
+
+        LoadFieldNode loadnmethod = g.add(new LoadFieldNode(code, nmethodField));
+        UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadnmethod, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), HotSpotGraalRuntime.getInstance().getTarget().wordKind));
+
+        LoadFieldNode loadMethod = g.add(new LoadFieldNode(code, methodField));
+        LoadFieldNode loadmetaspaceMethod = g.add(new LoadFieldNode(loadMethod, metaspaceMethodField));
+
+        HotSpotIndirectCallTargetNode callTarget = g.add(new HotSpotIndirectCallTargetNode(loadmetaspaceMethod, load, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall));
+
+        InvokeNode invoke = g.add(new InvokeNode(callTarget, 0));
+
         invoke.setStateAfter(stateAfter());
+        g.replaceFixedWithFixed(this, invoke);
+
+        g.addBeforeFixed(invoke, loadmetaspaceMethod);
+        g.addBeforeFixed(loadmetaspaceMethod, loadMethod);
+        g.addBeforeFixed(invoke, load);
+        g.addBeforeFixed(load, loadnmethod);
+
         return invoke;
     }
 
@@ -82,6 +111,6 @@
     }
 
     @NodeIntrinsic
-    public static native <T> T call(@ConstantNodeParameter Kind kind, Word targetAddress, long metaspaceObject, @ConstantNodeParameter Class[] signature, Object arg1, Object arg2, Object arg3);
+    public static native <T> T call(@ConstantNodeParameter Kind kind, @ConstantNodeParameter Class[] signature, Object code, Object arg1, Object arg2, Object arg3);
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java	Fri Apr 12 18:15:44 2013 +0200
@@ -27,20 +27,18 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.replacements.Snippet.Fold;
-import com.oracle.graal.word.*;
 
 @ClassSubstitution(HotSpotInstalledCode.class)
 public class HotSpotInstalledCodeSubstitutions {
 
-    @MethodSubstitution
-    public static Object executeHelper(long nmethod, long metaspaceMethod, final Object arg1, final Object arg2, final Object arg3) {
-        final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset();
-        final Word callTarget = Word.unsigned(nmethod).readWord(verifiedEntryPointOffset);
-        return HotSpotInstalledCodeExecuteNode.call(Kind.Object, callTarget, metaspaceMethod, getSignature(), arg1, arg2, arg3);
+    @MethodSubstitution(isStatic = false)
+    public static Object execute(HotSpotInstalledCode code, final Object arg1, final Object arg2, final Object arg3) {
+        return HotSpotInstalledCodeExecuteNode.call(Kind.Object, getSignature(), code, arg1, arg2, arg3);
     }
 
     @Fold
     private static Class[] getSignature() {
         return new Class[]{Object.class, Object.class, Object.class};
     }
+
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Fri Apr 12 17:55:22 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Fri Apr 12 18:15:44 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.spi;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 
 /**
@@ -30,5 +31,17 @@
  */
 public interface GraalCodeCacheProvider extends CodeCacheProvider {
 
+    /**
+     * Adds the given compilation result as an implementation of the given method without making it
+     * the default implementation. The graph might be inlined later on.
+     * 
+     * @param method a method to which the executable code is begin added
+     * @param compResult the compilation result to be added
+     * @param graph the graph that represents the method
+     * @return a reference to the compiled and ready-to-run code or null if the code installation
+     *         failed
+     */
+    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph);
+
     void lower(Node n, LoweringTool tool);
 }
--- a/src/cpu/sparc/vm/interpreter_sparc.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/cpu/sparc/vm/interpreter_sparc.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -381,7 +381,9 @@
     case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
     case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false);  break;
     case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);   break;
+#ifdef GRAAL
     case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry();   break;
+#endif
     case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();        break;
     case Interpreter::accessor               : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry();     break;
     case Interpreter::abstract               : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry();     break;
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -1917,7 +1917,6 @@
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
                                                 BasicType ret_type) {
-  assert (method->intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "not yet ported");
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
     intptr_t start = (intptr_t)__ pc();
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Fri Apr 12 18:15:44 2013 +0200
@@ -36,7 +36,9 @@
 
   address generate_normal_entry(bool synchronized);
   address generate_native_entry(bool synchronized);
+#ifdef GRAAL
   address generate_execute_compiled_method_entry();
+#endif
   address generate_abstract_entry(void);
   address generate_math_entry(AbstractInterpreter::MethodKind kind);
   address generate_empty_entry(void);
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -1670,10 +1670,16 @@
   verify_oop_args(masm, method, sig_bt, regs);
   vmIntrinsics::ID iid = method->intrinsic_id();
 
+#ifdef GRAAL
   if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // We are called from compiled code here. The three object arguments
+    // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The
+    // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail
+    // call to its verified entry point.
     __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
     return;
   }
+#endif
 
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -873,6 +873,8 @@
   return generate_accessor_entry();
 }
 
+#ifdef GRAAL
+
 // Interpreter stub for calling a compiled method with 3 object arguments
 address InterpreterGenerator::generate_execute_compiled_method_entry() {
   address entry_point = __ pc();
@@ -891,14 +893,27 @@
   // as far as the placement of the call instruction
   __ push(rax);
 
+  // Move first object argument from interpreter calling convention to compiled
+  // code calling convention.
   __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5));
+
+  // Move second object argument.
   __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4));
+
+  // Move third object argument.
   __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3));
+
+  // Load the raw pointer to the nmethod.
   __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize));
+
+  // Perform a tail call to the verified entry point of the nmethod.
   __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+
   return entry_point;
 }
 
+#endif
+
 // Interpreter stub for calling a native method. (asm interpreter)
 // This sets up a somewhat different looking stack for calling the
 // native method than the typical interpreter frame setup.
@@ -1586,7 +1601,9 @@
   switch (kind) {
   case Interpreter::zerolocals             :                                                                             break;
   case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
+#ifdef GRAAL
   case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break;
+#endif
   case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break;
   case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);  break;
   case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();       break;
--- a/src/share/vm/code/nmethod.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/share/vm/code/nmethod.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -1307,9 +1307,12 @@
   }
 
 #ifdef GRAAL
-    if (_graal_installed_code != NULL) {
-      _graal_installed_code = NULL;
-    }
+  // The method can only be unloaded after the pointer to the installed code
+  // Java wrapper is no longer alive. Here we need to clear out this weak
+  // reference to the dead object.
+  if (_graal_installed_code != NULL) {
+    _graal_installed_code = NULL;
+  }
 #endif
 
   // Make the class unloaded - i.e., change state and notify sweeper
@@ -1396,14 +1399,14 @@
     // The caller can be calling the method statically or through an inline
     // cache call.
     if (!is_osr_method() && !is_not_entrant()) {
+      address stub = SharedRuntime::get_handle_wrong_method_stub();
+#ifdef GRAAL
       if (_graal_installed_code != NULL && !HotSpotInstalledCode::isDefault(_graal_installed_code)) {
         // This was manually installed machine code. Patch entry with stub that throws an exception.
-        NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
-                    SharedRuntime::get_deoptimized_installed_code_stub());
-      } else {
-        NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
-                    SharedRuntime::get_handle_wrong_method_stub());
+        stub = SharedRuntime::get_deoptimized_installed_code_stub();
       }
+#endif
+      NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub);
     }
 
     if (is_in_use()) {
--- a/src/share/vm/interpreter/abstractInterpreter.hpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp	Fri Apr 12 18:15:44 2013 +0200
@@ -85,7 +85,9 @@
     zerolocals_synchronized,                                    // method needs locals initialization & is synchronized
     native,                                                     // native method
     native_synchronized,                                        // native method & is synchronized
+#ifdef GRAAL
     execute_compiled_method,                                    // direct call to compiled method address
+#endif
     empty,                                                      // empty method (code: _return)
     accessor,                                                   // accessor method (code: _aload_0, _getfield, _(a|i)return)
     abstract,                                                   // abstract method (throws an AbstractMethodException)
--- a/src/share/vm/interpreter/interpreter.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/share/vm/interpreter/interpreter.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -188,9 +188,13 @@
   // Method handle primitive?
   if (m->is_method_handle_intrinsic()) {
     vmIntrinsics::ID id = m->intrinsic_id();
+#ifdef GRAAL
     if (id == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+      // Special method kind for directly executing the verified entry point
+      // of a given nmethod.
       return AbstractInterpreter::execute_compiled_method;
     }
+#endif
     assert(MethodHandles::is_signature_polymorphic(id), "must match an intrinsic");
     MethodKind kind = (MethodKind)( method_handle_invoke_FIRST +
                                     ((int)id - vmIntrinsics::FIRST_MH_SIG_POLY) );
@@ -290,7 +294,9 @@
     case zerolocals_synchronized: tty->print("zerolocals_synchronized"); break;
     case native                 : tty->print("native"                 ); break;
     case native_synchronized    : tty->print("native_synchronized"    ); break;
+#ifdef GRAAL
     case execute_compiled_method: tty->print("execute_compiled_method"); break;
+#endif
     case empty                  : tty->print("empty"                  ); break;
     case accessor               : tty->print("accessor"               ); break;
     case abstract               : tty->print("abstract"               ); break;
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -360,7 +360,9 @@
   method_entry(zerolocals)
   method_entry(zerolocals_synchronized)
   method_entry(empty)
+#ifdef GRAAL
   method_entry(execute_compiled_method)
+#endif
   method_entry(accessor)
   method_entry(abstract)
   method_entry(java_lang_math_sin  )
--- a/src/share/vm/oops/method.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/share/vm/oops/method.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -850,10 +850,15 @@
   (void) make_adapters(h_method, CHECK);
 
   // ONLY USE the h_method now as make_adapter may have blocked
+
+#ifdef GRAAL
+  // Check for special intrinsic that executes a compiled method.
   if (h_method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // Actively install the stub for calling the intrinsic from compiled code.
     CompileBroker::compile_method(h_method, InvocationEntryBci, CompLevel_highest_tier,
                                   methodHandle(), CompileThreshold, "executeCompiledMethod", CHECK);
   }
+#endif
 }
 
 address Method::make_adapters(methodHandle mh, TRAPS) {
--- a/src/share/vm/prims/unsafe.cpp	Fri Apr 12 17:55:22 2013 +0200
+++ b/src/share/vm/prims/unsafe.cpp	Fri Apr 12 18:15:44 2013 +0200
@@ -116,7 +116,9 @@
 inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
   jlong byte_offset = field_offset_to_byte_offset(field_offset);
   // Don't allow unsafe to be used to read or write the header word of oops
-  assert(p == NULL || field_offset >= oopDesc::header_size(), "offset must be outside of header");
+  // unless running GRAAL which wants to read the misc word for example when
+  // interpreting computeHashCode().
+  assert(p == NULL || field_offset >= oopDesc::header_size() || GRAAL, "offset must be outside of header");
 #ifdef ASSERT
   if (p != NULL) {
     assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");