001/*
002 * Copyright (c) 2015, 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.compiler.test.tutorial;
024
025import java.lang.reflect.*;
026import java.util.concurrent.atomic.*;
027
028import jdk.internal.jvmci.code.*;
029import jdk.internal.jvmci.code.CallingConvention.Type;
030import com.oracle.graal.debug.*;
031import com.oracle.graal.debug.Debug.Scope;
032import jdk.internal.jvmci.meta.*;
033
034import com.oracle.graal.api.runtime.*;
035import com.oracle.graal.compiler.*;
036import com.oracle.graal.compiler.target.*;
037import com.oracle.graal.lir.asm.*;
038import com.oracle.graal.lir.phases.*;
039import com.oracle.graal.nodes.*;
040import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
041import com.oracle.graal.phases.*;
042import com.oracle.graal.phases.tiers.*;
043import com.oracle.graal.phases.util.*;
044import com.oracle.graal.runtime.*;
045
046/**
047 * Sample code that shows how to invoke Graal from an application.
048 */
049public class InvokeGraal {
050
051    protected final Backend backend;
052    protected final Providers providers;
053    protected final MetaAccessProvider metaAccess;
054    protected final CodeCacheProvider codeCache;
055    protected final TargetDescription target;
056
057    public InvokeGraal() {
058        /* Ask the hosting Java VM for the entry point object to the Graal API. */
059        RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
060
061        /*
062         * The default backend (architecture, VM configuration) that the hosting VM is running on.
063         */
064        backend = runtimeProvider.getHostBackend();
065        /* Access to all of the Graal API providers, as implemented by the hosting VM. */
066        providers = backend.getProviders();
067        /* Some frequently used providers and configuration objects. */
068        metaAccess = providers.getMetaAccess();
069        codeCache = providers.getCodeCache();
070        target = codeCache.getTarget();
071    }
072
073    private static AtomicInteger compilationId = new AtomicInteger();
074
075    /**
076     * The simplest way to compile a method, using the default behavior for everything.
077     */
078    protected InstalledCode compileAndInstallMethod(ResolvedJavaMethod method) {
079        /* Ensure every compilation gets a unique number, visible in IGV. */
080        try (Scope s = Debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId.incrementAndGet()), true))) {
081
082            /*
083             * The graph that is compiled. We leave it empty (no nodes added yet). This means that
084             * it will be filled according to the graphBuilderSuite defined below. We also specify
085             * that we want the compilation to make optimistic assumptions about runtime state such
086             * as the loaded class hierarchy.
087             */
088            StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.YES);
089
090            /*
091             * The phases used to build the graph. Usually this is just the GraphBuilderPhase. If
092             * the graph already contains nodes, it is ignored.
093             */
094            PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite();
095
096            /*
097             * The optimization phases that are applied to the graph. This is the main configuration
098             * point for Graal. Add or remove phases to customize your compilation.
099             */
100            Suites suites = backend.getSuites().createSuites();
101
102            /*
103             * The low-level phases that are applied to the low-level representation.
104             */
105            LIRSuites lirSuites = backend.getSuites().createLIRSuites();
106
107            /*
108             * The calling convention for the machine code. You should have a very good reason
109             * before you switch to a different calling convention than the one that the VM provides
110             * by default.
111             */
112            CallingConvention callingConvention = CodeUtil.getCallingConvention(codeCache, Type.JavaCallee, method, false);
113
114            /*
115             * We want Graal to perform all speculative optimisitic optimizations, using the
116             * profiling information that comes with the method (collected by the interpreter) for
117             * speculation.
118             */
119            OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL;
120            ProfilingInfo profilingInfo = method.getProfilingInfo();
121
122            /* The default class and configuration for compilation results. */
123            CompilationResult compilationResult = new CompilationResult();
124            CompilationResultBuilderFactory factory = CompilationResultBuilderFactory.Default;
125
126            /* Invoke the whole Graal compilation pipeline. */
127            GraalCompiler.compileGraph(graph, callingConvention, method, providers, backend, target, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory);
128
129            /*
130             * Install the compilation result into the VM, i.e., copy the byte[] array that contains
131             * the machine code into an actual executable memory location.
132             */
133            InstalledCode installedCode = codeCache.addMethod(method, compilationResult, null, null);
134
135            return installedCode;
136        } catch (Throwable ex) {
137            throw Debug.handle(ex);
138        }
139    }
140
141    /**
142     * Look up a method using Java reflection and convert it to the Graal API method object.
143     */
144    protected ResolvedJavaMethod findMethod(Class<?> declaringClass, String name) {
145        Method reflectionMethod = null;
146        for (Method m : declaringClass.getDeclaredMethods()) {
147            if (m.getName().equals(name)) {
148                assert reflectionMethod == null : "More than one method with name " + name + " in class " + declaringClass.getName();
149                reflectionMethod = m;
150            }
151        }
152        assert reflectionMethod != null : "No method with name " + name + " in class " + declaringClass.getName();
153        return metaAccess.lookupJavaMethod(reflectionMethod);
154    }
155}