changeset 12536:16e507054ebb

Merge
author Matthias Grimmer <grimmer@ssw.jku.at>
date Wed, 23 Oct 2013 13:41:10 +0200
parents cee7f686c470 (diff) 2583afcd26ee (current diff)
children c95e11c431b0
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java
diffstat 13 files changed, 204 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Oct 23 13:41:10 2013 +0200
@@ -42,6 +42,16 @@
     InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult);
 
     /**
+     * Sets the given compilation result as the default implementation of the given method.
+     * 
+     * @param method a method to which the executable code is begin added
+     * @param compResult the compilation result to be added
+     * @return a reference to the compiled and ready-to-run code or null if the code installation
+     *         failed
+     */
+    InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult);
+
+    /**
      * Returns a disassembly of some compiled code.
      * 
      * @param compResult some compiled code
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Wed Oct 23 13:41:10 2013 +0200
@@ -210,7 +210,7 @@
         }
     }
 
-    private static void decodePointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) {
+    public static void decodePointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) {
         // If the base is zero, the compressed address has to be shifted left
         // in order to be uncompressed.
         if (base == 0) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Oct 23 13:41:10 2013 +0200
@@ -218,6 +218,8 @@
 
     long readUnsafeKlassPointer(Object o);
 
+    void doNotInlineOrCompile(long metaspaceMethod);
+
     /**
      * Invalidates the profiling information and restarts profiling upon the next invocation.
      * 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Oct 23 13:41:10 2013 +0200
@@ -178,6 +178,9 @@
     public native long readUnsafeKlassPointer(Object o);
 
     @Override
+    public native void doNotInlineOrCompile(long metaspaceMethod);
+
+    @Override
     public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
         return executeCompiledMethodIntrinsic(arg1, arg2, arg3, hotspotInstalledCode);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Wed Oct 23 13:41:10 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
 import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.printer.*;
 
 /**
@@ -173,6 +174,11 @@
         return code;
     }
 
+    public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+        HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
+        return installMethod(hotspotMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult);
+    }
+
     public InstalledCode addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
 
         HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Oct 23 13:41:10 2013 +0200
@@ -190,6 +190,14 @@
     }
 
     /**
+     * Manually adds a DontInline annotation to this method.
+     */
+    public void setDontInline() {
+        dontInline = true;
+        runtime().getCompilerToVM().doNotInlineOrCompile(metaspaceMethod);
+    }
+
+    /**
      * Returns true if this method is one of the special methods that is ignored by security stack
      * walks.
      * 
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java	Wed Oct 23 13:41:10 2013 +0200
@@ -22,16 +22,20 @@
  */
 package com.oracle.graal.truffle.hotspot.amd64;
 
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.amd64.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.hotspot.amd64.util.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 
@@ -42,7 +46,7 @@
  */
 class AMD64HotSpotTruffleBackend extends AMD64HotSpotBackend {
 
-    private ResolvedJavaMethod optimizedCallTargetCall;
+    private HotSpotResolvedJavaMethod optimizedCallTargetCall;
 
     public AMD64HotSpotTruffleBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
         super(runtime, providers);
@@ -51,7 +55,9 @@
     private ResolvedJavaMethod getInstrumentedMethod() throws GraalInternalError {
         if (optimizedCallTargetCall == null) {
             try {
-                optimizedCallTargetCall = getProviders().getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("call", PackedFrame.class, Arguments.class));
+                optimizedCallTargetCall = (HotSpotResolvedJavaMethod) getProviders().getMetaAccess().lookupJavaMethod(
+                                OptimizedCallTarget.class.getDeclaredMethod("call", PackedFrame.class, Arguments.class));
+                optimizedCallTargetCall.setDontInline();
             } catch (NoSuchMethodException | SecurityException e) {
                 throw new GraalInternalError(e);
             }
@@ -63,7 +69,31 @@
     protected void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, TargetMethodAssembler tasm, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedStub) {
         super.emitCodePrefix(installedCodeOwner, tasm, asm, regConfig, config, verifiedStub);
         if (getInstrumentedMethod().equals(installedCodeOwner)) {
-            // TODO emit tailcall code
+            HotSpotProviders providers = getRuntime().getHostProviders();
+            Register thisRegister = providers.getCodeCache().getRegisterConfig().getCallingConventionRegisters(Type.JavaCall, Kind.Object)[0];
+            Register spillRegister = AMD64.r10; // TODO(mg): fix me
+            AMD64Address nMethodAddress = new AMD64Address(thisRegister, OptimizedCallTargetFieldInfo.getCompiledMethodFieldOffset());
+            if (config.useCompressedOops) {
+                asm.movl(spillRegister, nMethodAddress);
+                AMD64HotSpotMove.decodePointer(asm, spillRegister, providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase, config.narrowOopShift, config.logMinObjAlignment);
+            } else {
+                asm.movq(spillRegister, nMethodAddress);
+            }
+            Label doProlog = new Label();
+
+            asm.cmpq(spillRegister, 0);
+            asm.jcc(ConditionFlag.Equal, doProlog);
+
+            AMD64Address codeBlobAddress = new AMD64Address(spillRegister, OptimizedCallTargetFieldInfo.getCodeBlobFieldOffset());
+            asm.movq(spillRegister, codeBlobAddress);
+            asm.cmpq(spillRegister, 0);
+            asm.jcc(ConditionFlag.Equal, doProlog);
+
+            AMD64Address verifiedEntryPointAddress = new AMD64Address(spillRegister, config.nmethodEntryOffset);
+            asm.movq(spillRegister, verifiedEntryPointAddress);
+            asm.jmp(spillRegister);
+
+            asm.bind(doProlog);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/util/OptimizedCallTargetFieldInfo.java	Wed Oct 23 13:41:10 2013 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.hotspot.amd64.util;
+
+import java.lang.reflect.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.truffle.*;
+
+public class OptimizedCallTargetFieldInfo {
+
+    private static final Unsafe unsafe = UnsafeAccess.unsafe;
+    private static int compiledMethodFieldOffset = -1;
+    private static int codeBlobFieldOffset = -1;
+
+    public static int getCodeBlobFieldOffset() {
+        if (codeBlobFieldOffset == -1) {
+            codeBlobFieldOffset = getFieldOffset("codeBlob", HotSpotInstalledCode.class);
+        }
+        return codeBlobFieldOffset;
+    }
+
+    public static int getCompiledMethodFieldOffset() {
+        if (compiledMethodFieldOffset == -1) {
+            compiledMethodFieldOffset = getFieldOffset("compiledMethod", OptimizedCallTarget.class);
+        }
+        return compiledMethodFieldOffset;
+
+    }
+
+    private static int getFieldOffset(String name, Class container) {
+        try {
+            container.getDeclaredField(name).setAccessible(true);
+            Field field = container.getDeclaredField(name);
+            return (int) unsafe.objectFieldOffset(field);
+        } catch (NoSuchFieldException | SecurityException e) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Wed Oct 23 13:41:10 2013 +0200
@@ -22,11 +22,28 @@
  */
 package com.oracle.graal.truffle;
 
+import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
+import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.runtime.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
@@ -47,6 +64,7 @@
     private ArrayList<String> excludes;
 
     private GraalTruffleRuntime() {
+        installOptimizedCallTargetCallMethod();
     }
 
     public String getName() {
@@ -138,4 +156,43 @@
             }
         }
     }
+
+    public static void installOptimizedCallTargetCallMethod() {
+        Providers providers = getGraalProviders();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        ResolvedJavaMethod resolvedCallMethod = metaAccess.lookupJavaMethod(getCallMethod());
+        providers.getCodeCache().setDefaultMethod(resolvedCallMethod, compileMethod(resolvedCallMethod));
+    }
+
+    private static Method getCallMethod() {
+        Method method;
+        try {
+            method = OptimizedCallTarget.class.getDeclaredMethod("call", new Class[]{PackedFrame.class, Arguments.class});
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+        return method;
+    }
+
+    private static CompilationResult compileMethod(ResolvedJavaMethod javaMethod) {
+        Providers providers = getGraalProviders();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        Suites suites = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites();
+        suites.getHighTier().findPhase(InliningPhase.class).remove();
+        StructuredGraph graph = new StructuredGraph(javaMethod);
+        ForeignCallsProvider foreignCalls = providers.getForeignCalls();
+        new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+        PhasePlan phasePlan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
+        Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
+        return GraalCompiler.compileGraph(graph, cc, javaMethod, providers, backend, providers.getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog(), suites,
+                        new CompilationResult());
+    }
+
+    private static Providers getGraalProviders() {
+        RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
+        return runtimeProvider.getHostBackend().getProviders();
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Oct 23 13:41:10 2013 +0200
@@ -75,6 +75,14 @@
     }
 
     private Object callHelper(PackedFrame caller, Arguments args) {
+        if (compiledMethod != null && compiledMethod.isValid()) {
+            TruffleRuntime runtime = Truffle.getRuntime();
+            if (runtime instanceof GraalTruffleRuntime) {
+                OUT.printf("[truffle] reinstall OptimizedCallTarget.call code with frame prolog shortcut.");
+                OUT.println();
+                GraalTruffleRuntime.installOptimizedCallTargetCallMethod();
+            }
+        }
         if (TruffleCallTargetProfiling.getValue()) {
             callCount++;
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Wed Oct 23 13:41:10 2013 +0200
@@ -34,6 +34,9 @@
 public class OptimizedCallTargetSubstitutions {
 
     @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
+    public static native Object call(OptimizedCallTarget target, PackedFrame caller, Arguments args);
+
+    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
     public static native Object callHelper(OptimizedCallTarget target, PackedFrame caller, Arguments args);
 
     @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java	Wed Oct 23 10:29:53 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java	Wed Oct 23 13:41:10 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.truffle.sl.nodes;
 
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
 
 public class BlockNode extends StatementNode {
 
@@ -33,6 +34,7 @@
     }
 
     @Override
+    @ExplodeLoop
     public void executeVoid(VirtualFrame frame) {
         for (StatementNode statement : statements) {
             statement.executeVoid(frame);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Oct 23 10:29:53 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Oct 23 13:41:10 2013 +0200
@@ -642,6 +642,13 @@
   return id;
 }
 
+C2V_VMENTRY(void, doNotInlineOrCompile,(JNIEnv *, jobject,  jlong metaspace_method))
+  methodHandle method = asMethod(metaspace_method);
+  method->set_not_c1_compilable();
+  method->set_not_c2_compilable();
+  method->set_dont_inline(true);
+C2V_END
+
 C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config))
 
 #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0)
@@ -1196,6 +1203,7 @@
   {CC"getUniqueImplementor",          CC"("HS_RESOLVED_TYPE")"RESOLVED_TYPE,                            FN_PTR(getUniqueImplementor)},
   {CC"getStackTraceElement",          CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT,                     FN_PTR(getStackTraceElement)},
   {CC"initializeMethod",              CC"("METASPACE_METHOD HS_RESOLVED_METHOD")V",                     FN_PTR(initializeMethod)},
+  {CC"doNotInlineOrCompile",          CC"("METASPACE_METHOD")V",                                        FN_PTR(doNotInlineOrCompile)},
   {CC"initializeMethodData",          CC"("METASPACE_METHOD_DATA METHOD_DATA")V",                       FN_PTR(initializeMethodData)},
   {CC"isMethodCompilable",            CC"("METASPACE_METHOD")Z",                                        FN_PTR(isMethodCompilable)},
   {CC"getCompiledCodeSize",           CC"("METASPACE_METHOD")I",                                        FN_PTR(getCompiledCodeSize)},