1 /*
   2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 package org.graalvm.compiler.core.test.tutorial;
  26 
  27 import static org.graalvm.compiler.core.common.CompilationRequestIdentifier.asCompilationRequest;
  28 import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions;
  29 
  30 import java.lang.reflect.Method;
  31 
  32 import org.graalvm.compiler.api.test.Graal;
  33 import org.graalvm.compiler.code.CompilationResult;
  34 import org.graalvm.compiler.core.GraalCompiler;
  35 import org.graalvm.compiler.core.common.CompilationIdentifier;
  36 import org.graalvm.compiler.core.target.Backend;
  37 import org.graalvm.compiler.debug.DebugHandlersFactory;
  38 import org.graalvm.compiler.debug.DebugContext;
  39 import org.graalvm.compiler.debug.DebugDumpScope;
  40 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
  41 import org.graalvm.compiler.lir.phases.LIRSuites;
  42 import org.graalvm.compiler.nodes.StructuredGraph;
  43 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  44 import org.graalvm.compiler.options.OptionValues;
  45 import org.graalvm.compiler.phases.OptimisticOptimizations;
  46 import org.graalvm.compiler.phases.PhaseSuite;
  47 import org.graalvm.compiler.phases.tiers.HighTierContext;
  48 import org.graalvm.compiler.phases.tiers.Suites;
  49 import org.graalvm.compiler.phases.util.Providers;
  50 import org.graalvm.compiler.runtime.RuntimeProvider;
  51 
  52 import jdk.vm.ci.code.CodeCacheProvider;
  53 import jdk.vm.ci.code.InstalledCode;
  54 import jdk.vm.ci.meta.MetaAccessProvider;
  55 import jdk.vm.ci.meta.ProfilingInfo;
  56 import jdk.vm.ci.meta.ResolvedJavaMethod;
  57 
  58 /**
  59  * Sample code that shows how to invoke Graal from an application.
  60  */
  61 public class InvokeGraal {
  62 
  63     protected final Backend backend;
  64     protected final Providers providers;
  65     protected final MetaAccessProvider metaAccess;
  66     protected final CodeCacheProvider codeCache;
  67 
  68     public InvokeGraal() {
  69         /* Ask the hosting Java VM for the entry point object to the Graal API. */
  70         RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
  71 
  72         /*
  73          * The default backend (architecture, VM configuration) that the hosting VM is running on.
  74          */
  75         backend = runtimeProvider.getHostBackend();
  76         /* Access to all of the Graal API providers, as implemented by the hosting VM. */
  77         providers = backend.getProviders();
  78         /* Some frequently used providers and configuration objects. */
  79         metaAccess = providers.getMetaAccess();
  80         codeCache = providers.getCodeCache();
  81     }
  82 
  83     /**
  84      * The simplest way to compile a method, using the default behavior for everything.
  85      */
  86     @SuppressWarnings("try")
  87     protected InstalledCode compileAndInstallMethod(ResolvedJavaMethod method) {
  88         /* Create a unique compilation identifier, visible in IGV. */
  89         CompilationIdentifier compilationId = backend.getCompilationIdentifier(method);
  90         OptionValues options = getInitialOptions();
  91         DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
  92         try (DebugContext.Scope s = debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId), true))) {
  93 
  94             /*
  95              * The graph that is compiled. We leave it empty (no nodes added yet). This means that
  96              * it will be filled according to the graphBuilderSuite defined below. We also specify
  97              * that we want the compilation to make optimistic assumptions about runtime state such
  98              * as the loaded class hierarchy.
  99              */
 100             StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(method).compilationId(compilationId).build();
 101 
 102             /*
 103              * The phases used to build the graph. Usually this is just the GraphBuilderPhase. If
 104              * the graph already contains nodes, it is ignored.
 105              */
 106             PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite();
 107 
 108             /*
 109              * The optimization phases that are applied to the graph. This is the main configuration
 110              * point for Graal. Add or remove phases to customize your compilation.
 111              */
 112             Suites suites = backend.getSuites().getDefaultSuites(options);
 113 
 114             /*
 115              * The low-level phases that are applied to the low-level representation.
 116              */
 117             LIRSuites lirSuites = backend.getSuites().getDefaultLIRSuites(options);
 118 
 119             /*
 120              * We want Graal to perform all speculative optimistic optimizations, using the
 121              * profiling information that comes with the method (collected by the interpreter) for
 122              * speculation.
 123              */
 124             OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL;
 125             ProfilingInfo profilingInfo = graph.getProfilingInfo(method);
 126 
 127             /* The default class and configuration for compilation results. */
 128             CompilationResult compilationResult = new CompilationResult(graph.compilationId());
 129             CompilationResultBuilderFactory factory = CompilationResultBuilderFactory.Default;
 130 
 131             /* Invoke the whole Graal compilation pipeline. */
 132             GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory, true);
 133 
 134             /*
 135              * Install the compilation result into the VM, i.e., copy the byte[] array that contains
 136              * the machine code into an actual executable memory location.
 137              */
 138             return backend.addInstalledCode(debug, method, asCompilationRequest(compilationId), compilationResult);
 139         } catch (Throwable ex) {
 140             throw debug.handle(ex);
 141         }
 142     }
 143 
 144     /**
 145      * Look up a method using Java reflection and convert it to the Graal API method object.
 146      */
 147     protected ResolvedJavaMethod findMethod(Class<?> declaringClass, String name) {
 148         Method reflectionMethod = null;
 149         for (Method m : declaringClass.getDeclaredMethods()) {
 150             if (m.getName().equals(name)) {
 151                 assert reflectionMethod == null : "More than one method with name " + name + " in class " + declaringClass.getName();
 152                 reflectionMethod = m;
 153             }
 154         }
 155         assert reflectionMethod != null : "No method with name " + name + " in class " + declaringClass.getName();
 156         return metaAccess.lookupJavaMethod(reflectionMethod);
 157     }
 158 }