# HG changeset patch # User Matthias Grimmer # Date 1382441137 -7200 # Node ID 23dc5dfdb9c7c4285f219abf01128abf659ca651 # Parent 9fe4cd9d7e12f3456de7e4ac58ba94d425f7178b Add OptimizedCallTarget.call(PackedFrame, Arguments) frame prologue injection diff -r 9fe4cd9d7e12 -r 23dc5dfdb9c7 graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java --- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java Tue Oct 22 13:24:43 2013 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64HotSpotTruffleBackend.java Tue Oct 22 13:25:37 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.*; @@ -63,7 +67,32 @@ 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); } } } diff -r 9fe4cd9d7e12 -r 23dc5dfdb9c7 graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/util/OptimizedCallTargetFieldInfo.java --- /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 Tue Oct 22 13:25:37 2013 +0200 @@ -0,0 +1,69 @@ +/* + * 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) { + try { + HotSpotInstalledCode.class.getDeclaredField("codeBlob").setAccessible(true); + Field codeBlobField = HotSpotInstalledCode.class.getDeclaredField("codeBlob"); + codeBlobFieldOffset = (int) unsafe.objectFieldOffset(codeBlobField); + } catch (NoSuchFieldException | SecurityException e) { + throw GraalInternalError.shouldNotReachHere(); + } + return codeBlobFieldOffset; + } else { + return codeBlobFieldOffset; + } + } + + public static int getCompiledMethodFieldOffset() { + if (compiledMethodFieldOffset == -1) { + try { + OptimizedCallTarget.class.getDeclaredField("compiledMethod").setAccessible(true); + Field compiledMethodField = OptimizedCallTarget.class.getDeclaredField("compiledMethod"); + compiledMethodFieldOffset = (int) unsafe.objectFieldOffset(compiledMethodField); + } catch (NoSuchFieldException | SecurityException e) { + throw GraalInternalError.shouldNotReachHere(); + } + return compiledMethodFieldOffset; + } else { + return compiledMethodFieldOffset; + } + } + +} diff -r 9fe4cd9d7e12 -r 23dc5dfdb9c7 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Tue Oct 22 13:24:43 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Tue Oct 22 13:25:37 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.*; @@ -45,8 +62,17 @@ private Replacements truffleReplacements; private ArrayList includes; private ArrayList excludes; + private final CodeCacheProvider codeCacheProvider; + private final ResolvedJavaMethod callMethod; + private final CompilationResult callCompilationResult; private GraalTruffleRuntime() { + Providers providers = getGraalProviders(); + MetaAccessProvider metaAccess = providers.getMetaAccess(); + codeCacheProvider = providers.getCodeCache(); + callMethod = metaAccess.lookupJavaMethod(getCallMethod()); + callCompilationResult = compileMethod(callMethod, providers); + installOptimizedCallTargetCallMethod(); } public String getName() { @@ -138,4 +164,39 @@ } } } + + public void installOptimizedCallTargetCallMethod() { + codeCacheProvider.addDefaultMethod(callMethod, callCompilationResult); + } + + 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) { + 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(); + } } diff -r 9fe4cd9d7e12 -r 23dc5dfdb9c7 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Tue Oct 22 13:24:43 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Tue Oct 22 13:25:37 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) runtime).installOptimizedCallTargetCallMethod(); + } + } if (TruffleCallTargetProfiling.getValue()) { callCount++; }