1 /*
   2  * Copyright (c) 2011, 2016, 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 package org.graalvm.compiler.hotspot;
  24 
  25 import static jdk.vm.ci.common.InitTimer.timer;
  26 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
  27 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
  28 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
  29 import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining;
  30 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
  31 
  32 import java.util.ArrayList;
  33 import java.util.EnumMap;
  34 import java.util.List;
  35 import java.util.Map;
  36 
  37 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
  38 import org.graalvm.compiler.api.runtime.GraalRuntime;
  39 import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
  40 import org.graalvm.compiler.core.common.CompilationIdentifier;
  41 import org.graalvm.compiler.core.common.GraalOptions;
  42 import org.graalvm.compiler.core.target.Backend;
  43 import org.graalvm.compiler.debug.DebugContext;
  44 import org.graalvm.compiler.debug.DebugContext.Description;
  45 import org.graalvm.compiler.debug.DebugHandlersFactory;
  46 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
  47 import org.graalvm.compiler.debug.GlobalMetrics;
  48 import org.graalvm.compiler.debug.GraalError;
  49 import org.graalvm.compiler.debug.TTY;
  50 import org.graalvm.compiler.hotspot.CompilationStatistics.Options;
  51 import org.graalvm.compiler.hotspot.CompilerConfigurationFactory.BackendMap;
  52 import org.graalvm.compiler.hotspot.debug.BenchmarkCounters;
  53 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
  54 import org.graalvm.compiler.nodes.spi.StampProvider;
  55 import org.graalvm.compiler.options.OptionValues;
  56 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
  57 import org.graalvm.compiler.replacements.SnippetCounter;
  58 import org.graalvm.compiler.replacements.SnippetCounter.Group;
  59 import org.graalvm.compiler.runtime.RuntimeProvider;
  60 import org.graalvm.util.EconomicMap;
  61 import org.graalvm.util.Equivalence;
  62 
  63 import jdk.vm.ci.code.Architecture;
  64 import jdk.vm.ci.code.stack.StackIntrospection;
  65 import jdk.vm.ci.common.InitTimer;
  66 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
  67 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
  68 import jdk.vm.ci.meta.JavaKind;
  69 import jdk.vm.ci.meta.ResolvedJavaMethod;
  70 import jdk.vm.ci.runtime.JVMCIBackend;
  71 
  72 //JaCoCo Exclude
  73 
  74 /**
  75  * Singleton class holding the instance of the {@link GraalRuntime}.
  76  */
  77 public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
  78 
  79     private static boolean checkArrayIndexScaleInvariants() {
  80         assert getArrayIndexScale(JavaKind.Byte) == 1;
  81         assert getArrayIndexScale(JavaKind.Boolean) == 1;
  82         assert getArrayIndexScale(JavaKind.Char) == 2;
  83         assert getArrayIndexScale(JavaKind.Short) == 2;
  84         assert getArrayIndexScale(JavaKind.Int) == 4;
  85         assert getArrayIndexScale(JavaKind.Long) == 8;
  86         assert getArrayIndexScale(JavaKind.Float) == 4;
  87         assert getArrayIndexScale(JavaKind.Double) == 8;
  88         return true;
  89     }
  90 
  91     private final HotSpotBackend hostBackend;
  92     private final GlobalMetrics metricValues = new GlobalMetrics();
  93     private final List<SnippetCounter.Group> snippetCounterGroups;
  94 
  95     private final EconomicMap<Class<? extends Architecture>, HotSpotBackend> backends = EconomicMap.create(Equivalence.IDENTITY);
  96 
  97     private final GraalHotSpotVMConfig config;
  98 
  99     private final OptionValues options;
 100     private final DiagnosticsOutputDirectory outputDirectory;
 101     private final Map<ExceptionAction, Integer> compilationProblemsPerAction;
 102     private final HotSpotGraalMBean mBean;
 103 
 104     /**
 105      * @param compilerConfigurationFactory factory for the compiler configuration
 106      *            {@link CompilerConfigurationFactory#selectFactory(String, OptionValues)}
 107      */
 108     @SuppressWarnings("try")
 109     HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) {
 110         HotSpotVMConfigStore store = jvmciRuntime.getConfigStore();
 111         config = GeneratePIC.getValue(initialOptions) ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store);
 112 
 113         // Only set HotSpotPrintInlining if it still has its default value (false).
 114         if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) {
 115             options = new OptionValues(initialOptions, HotSpotPrintInlining, true);
 116         } else {
 117             options = initialOptions;
 118         }
 119 
 120         outputDirectory = new DiagnosticsOutputDirectory(options);
 121         compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class);
 122         snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null;
 123         CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
 124 
 125         HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions);
 126         this.mBean = createHotSpotGraalMBean(compiler);
 127 
 128         BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
 129 
 130         JVMCIBackend hostJvmciBackend = jvmciRuntime.getHostJVMCIBackend();
 131         Architecture hostArchitecture = hostJvmciBackend.getTarget().arch;
 132         try (InitTimer t = timer("create backend:", hostArchitecture)) {
 133             HotSpotBackendFactory factory = backendMap.getBackendFactory(hostArchitecture);
 134             if (factory == null) {
 135                 throw new GraalError("No backend available for host architecture \"%s\"", hostArchitecture);
 136             }
 137             hostBackend = registerBackend(factory.createBackend(this, compilerConfiguration, jvmciRuntime, null));
 138         }
 139 
 140         for (JVMCIBackend jvmciBackend : jvmciRuntime.getJVMCIBackends().values()) {
 141             if (jvmciBackend == hostJvmciBackend) {
 142                 continue;
 143             }
 144 
 145             Architecture gpuArchitecture = jvmciBackend.getTarget().arch;
 146             HotSpotBackendFactory factory = backendMap.getBackendFactory(gpuArchitecture);
 147             if (factory == null) {
 148                 throw new GraalError("No backend available for specified GPU architecture \"%s\"", gpuArchitecture);
 149             }
 150             try (InitTimer t = timer("create backend:", gpuArchitecture)) {
 151                 registerBackend(factory.createBackend(this, compilerConfiguration, null, hostBackend));
 152             }
 153         }
 154 
 155         // Complete initialization of backends
 156         try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) {
 157             hostBackend.completeInitialization(jvmciRuntime, options);
 158         }
 159         for (HotSpotBackend backend : backends.getValues()) {
 160             if (backend != hostBackend) {
 161                 try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) {
 162                     backend.completeInitialization(jvmciRuntime, options);
 163                 }
 164             }
 165         }
 166 
 167         BenchmarkCounters.initialize(jvmciRuntime, options);
 168 
 169         assert checkArrayIndexScaleInvariants();
 170 
 171         runtimeStartTime = System.nanoTime();
 172         bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
 173     }
 174 
 175     private static HotSpotGraalMBean createHotSpotGraalMBean(HotSpotGraalCompiler compiler) {
 176         try {
 177             return HotSpotGraalMBean.create(compiler);
 178         } catch (LinkageError ex) {
 179             return null;
 180         }
 181     }
 182 
 183     private HotSpotBackend registerBackend(HotSpotBackend backend) {
 184         Class<? extends Architecture> arch = backend.getTarget().arch.getClass();
 185         HotSpotBackend oldValue = backends.put(arch, backend);
 186         assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName();
 187         return backend;
 188     }
 189 
 190     @Override
 191     public HotSpotProviders getHostProviders() {
 192         return getHostBackend().getProviders();
 193     }
 194 
 195     @Override
 196     public GraalHotSpotVMConfig getVMConfig() {
 197         return config;
 198     }
 199 
 200     @Override
 201     public DebugContext openDebugContext(OptionValues compilationOptions, CompilationIdentifier compilationId, Object compilable, Iterable<DebugHandlersFactory> factories) {
 202         Description description = new Description(compilable, compilationId.toString(CompilationIdentifier.Verbosity.ID));
 203         return DebugContext.create(compilationOptions, description, metricValues, DEFAULT_LOG_STREAM, factories);
 204     }
 205 
 206     @Override
 207     public OptionValues getOptions() {
 208         return mBean == null ? options : mBean.optionsFor(options, null);
 209     }
 210 
 211     @Override
 212     public OptionValues getOptions(ResolvedJavaMethod forMethod) {
 213         return mBean == null ? options : mBean.optionsFor(options, forMethod);
 214     }
 215 
 216     @Override
 217     public Group createSnippetCounterGroup(String name) {
 218         if (snippetCounterGroups != null) {
 219             Group group = new Group(name);
 220             snippetCounterGroups.add(group);
 221             return group;
 222         }
 223         return null;
 224     }
 225 
 226     @Override
 227     public String getName() {
 228         return getClass().getSimpleName();
 229     }
 230 
 231     @SuppressWarnings("unchecked")
 232     @Override
 233     public <T> T getCapability(Class<T> clazz) {
 234         if (clazz == RuntimeProvider.class) {
 235             return (T) this;
 236         } else if (clazz == OptionValues.class) {
 237             return (T) options;
 238         } else if (clazz == StackIntrospection.class) {
 239             return (T) this;
 240         } else if (clazz == SnippetReflectionProvider.class) {
 241             return (T) getHostProviders().getSnippetReflection();
 242         } else if (clazz == StampProvider.class) {
 243             return (T) getHostProviders().getStampProvider();
 244         }
 245         return null;
 246     }
 247 
 248     @Override
 249     public HotSpotBackend getHostBackend() {
 250         return hostBackend;
 251     }
 252 
 253     @Override
 254     public <T extends Architecture> Backend getBackend(Class<T> arch) {
 255         assert arch != Architecture.class;
 256         return backends.get(arch);
 257     }
 258 
 259     private long runtimeStartTime;
 260     private boolean shutdown;
 261 
 262     /**
 263      * Take action related to entering a new execution phase.
 264      *
 265      * @param phase the execution phase being entered
 266      */
 267     void phaseTransition(String phase) {
 268         if (Options.UseCompilationStatistics.getValue(options)) {
 269             CompilationStatistics.clear(phase);
 270         }
 271     }
 272 
 273     void shutdown() {
 274         shutdown = true;
 275         metricValues.print(options);
 276 
 277         phaseTransition("final");
 278 
 279         if (snippetCounterGroups != null) {
 280             for (Group group : snippetCounterGroups) {
 281                 TTY.out().out().println(group);
 282             }
 283         }
 284         BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime);
 285 
 286         outputDirectory.close();
 287     }
 288 
 289     void clearMetrics() {
 290         metricValues.clear();
 291     }
 292 
 293     private final boolean bootstrapJVMCI;
 294     private boolean bootstrapFinished;
 295 
 296     public void notifyBootstrapFinished() {
 297         bootstrapFinished = true;
 298     }
 299 
 300     @Override
 301     public boolean isBootstrapping() {
 302         return bootstrapJVMCI && !bootstrapFinished;
 303     }
 304 
 305     @Override
 306     public boolean isShutdown() {
 307         return shutdown;
 308     }
 309 
 310     @Override
 311     public DiagnosticsOutputDirectory getOutputDirectory() {
 312         return outputDirectory;
 313     }
 314 
 315     @Override
 316     public Map<ExceptionAction, Integer> getCompilationProblemsPerAction() {
 317         return compilationProblemsPerAction;
 318     }
 319 
 320     final Object mbean() {
 321         return mBean;
 322     }
 323 }