001/*
002 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.hotspot;
024
025import static com.oracle.graal.compiler.common.GraalOptions.*;
026import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.*;
027import static jdk.internal.jvmci.code.CallingConvention.Type.*;
028import static jdk.internal.jvmci.code.CodeUtil.*;
029import jdk.internal.jvmci.code.*;
030import jdk.internal.jvmci.code.CallingConvention.Type;
031import jdk.internal.jvmci.compiler.Compiler;
032import jdk.internal.jvmci.meta.*;
033import jdk.internal.jvmci.service.*;
034
035import com.oracle.graal.compiler.*;
036import com.oracle.graal.graphbuilderconf.*;
037import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
038import com.oracle.graal.hotspot.meta.*;
039import com.oracle.graal.hotspot.phases.*;
040import com.oracle.graal.java.*;
041import com.oracle.graal.lir.asm.*;
042import com.oracle.graal.lir.phases.*;
043import com.oracle.graal.nodes.*;
044import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
045import com.oracle.graal.nodes.spi.*;
046import com.oracle.graal.phases.*;
047import com.oracle.graal.phases.OptimisticOptimizations.Optimization;
048import com.oracle.graal.phases.tiers.*;
049
050@ServiceProvider(Compiler.class)
051public class HotSpotGraalCompiler implements Compiler {
052
053    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean mustRecordMethodInlining) {
054        HotSpotBackend backend = HotSpotGraalRuntime.runtime().getHostBackend();
055        HotSpotProviders providers = HotSpotGraalRuntime.runtime().getHostProviders();
056        final boolean isOSR = entryBCI != INVOCATION_ENTRY_BCI;
057
058        StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers);
059        if (graph == null) {
060            SpeculationLog speculationLog = method.getSpeculationLog();
061            if (speculationLog != null) {
062                speculationLog.collectFailedSpeculations();
063            }
064            graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue()), speculationLog);
065            if (!mustRecordMethodInlining) {
066                graph.disableInlinedMethodRecording();
067            }
068        }
069
070        CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
071        if (isOSR) {
072            // for OSR, only a pointer is passed to the method.
073            JavaType[] parameterTypes = new JavaType[]{providers.getMetaAccess().lookupJavaType(long.class)};
074            CallingConvention tmp = providers.getCodeCache().getRegisterConfig().getCallingConvention(JavaCallee, providers.getMetaAccess().lookupJavaType(void.class), parameterTypes,
075                            backend.getTarget(), false);
076            cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0));
077        }
078        Suites suites = getSuites(providers);
079        LIRSuites lirSuites = getLIRSuites(providers);
080        ProfilingInfo profilingInfo = method.getProfilingInfo(!isOSR, isOSR);
081        OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo);
082        if (isOSR) {
083            // In OSR compiles, we cannot rely on never executed code profiles, because
084            // all code after the OSR loop is never executed.
085            optimisticOpts.remove(Optimization.RemoveNeverExecutedCode);
086        }
087        CompilationResult result = GraalCompiler.compileGraph(graph, cc, method, providers, backend, backend.getTarget(), getGraphBuilderSuite(providers, isOSR), optimisticOpts, profilingInfo,
088                        suites, lirSuites, new CompilationResult(), CompilationResultBuilderFactory.Default);
089
090        result.setEntryBCI(entryBCI);
091
092        if (!isOSR) {
093            ProfilingInfo profile = method.getProfilingInfo();
094            profile.setCompilerIRSize(StructuredGraph.class, graph.getNodeCount());
095        }
096
097        return result;
098    }
099
100    /**
101     * Gets a graph produced from the intrinsic for a given method that can be compiled and
102     * installed for the method.
103     *
104     * @param method
105     * @return an intrinsic graph that can be compiled and installed for {@code method} or null
106     */
107    protected StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers) {
108        Replacements replacements = providers.getReplacements();
109        ResolvedJavaMethod substMethod = replacements.getSubstitutionMethod(method);
110        if (substMethod != null) {
111            assert !substMethod.equals(method);
112            StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES);
113            Plugins plugins = new Plugins(providers.getGraphBuilderPlugins());
114            GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
115            IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, ROOT_COMPILATION);
116            new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph);
117            assert !graph.isFrozen();
118            return graph;
119        }
120        return null;
121    }
122
123    protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo) {
124        return new OptimisticOptimizations(profilingInfo);
125    }
126
127    protected Suites getSuites(HotSpotProviders providers) {
128        return providers.getSuites().getDefaultSuites();
129    }
130
131    protected LIRSuites getLIRSuites(HotSpotProviders providers) {
132        return providers.getSuites().getDefaultLIRSuites();
133    }
134
135    protected PhaseSuite<HighTierContext> getGraphBuilderSuite(HotSpotProviders providers, boolean isOSR) {
136        PhaseSuite<HighTierContext> suite = HotSpotSuitesProvider.withSimpleDebugInfoIfRequested(providers.getSuites().getDefaultGraphBuilderSuite());
137        if (isOSR) {
138            suite = suite.copy();
139            suite.appendPhase(new OnStackReplacementPhase());
140        }
141        return suite;
142    }
143}