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 org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled;
  26 import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary;
  27 import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump;
  28 import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log;
  29 import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter;
  30 import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify;
  31 import static jdk.vm.ci.common.InitTimer.timer;
  32 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
  33 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
  34 
  35 import java.util.Collections;
  36 import java.util.HashMap;
  37 import java.util.Map;
  38 
  39 import org.graalvm.compiler.api.collections.CollectionsProvider;
  40 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
  41 import org.graalvm.compiler.api.runtime.GraalRuntime;
  42 import org.graalvm.compiler.core.common.GraalOptions;
  43 import org.graalvm.compiler.core.target.Backend;
  44 import org.graalvm.compiler.debug.Debug;
  45 import org.graalvm.compiler.debug.DebugEnvironment;
  46 import org.graalvm.compiler.debug.GraalError;
  47 import org.graalvm.compiler.debug.TTY;
  48 import org.graalvm.compiler.debug.internal.DebugValuesPrinter;
  49 import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter;
  50 import org.graalvm.compiler.graph.DefaultNodeCollectionsProvider;
  51 import org.graalvm.compiler.graph.NodeCollectionsProvider;
  52 import org.graalvm.compiler.hotspot.CompilerConfigurationFactory.BackendMap;
  53 import org.graalvm.compiler.hotspot.debug.BenchmarkCounters;
  54 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
  55 import org.graalvm.compiler.nodes.spi.StampProvider;
  56 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
  57 import org.graalvm.compiler.replacements.SnippetCounter;
  58 import org.graalvm.compiler.runtime.RuntimeProvider;
  59 
  60 import jdk.vm.ci.code.Architecture;
  61 import jdk.vm.ci.code.stack.StackIntrospection;
  62 import jdk.vm.ci.common.InitTimer;
  63 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
  64 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
  65 import jdk.vm.ci.meta.JavaKind;
  66 import jdk.vm.ci.runtime.JVMCIBackend;
  67 
  68 //JaCoCo Exclude
  69 
  70 /**
  71  * Singleton class holding the instance of the {@link GraalRuntime}.
  72  */
  73 public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
  74 
  75     private static boolean checkArrayIndexScaleInvariants() {
  76         assert getArrayIndexScale(JavaKind.Byte) == 1;
  77         assert getArrayIndexScale(JavaKind.Boolean) == 1;
  78         assert getArrayIndexScale(JavaKind.Char) == 2;
  79         assert getArrayIndexScale(JavaKind.Short) == 2;
  80         assert getArrayIndexScale(JavaKind.Int) == 4;
  81         assert getArrayIndexScale(JavaKind.Long) == 8;
  82         assert getArrayIndexScale(JavaKind.Float) == 4;
  83         assert getArrayIndexScale(JavaKind.Double) == 8;
  84         return true;
  85     }
  86 
  87     private final HotSpotBackend hostBackend;
  88     private DebugValuesPrinter debugValuesPrinter;
  89 
  90     private final Map<Class<? extends Architecture>, HotSpotBackend> backends = new HashMap<>();
  91 
  92     private final GraalHotSpotVMConfig config;
  93 
  94     /**
  95      * @param compilerConfigurationFactory factory for the compiler configuration
  96      *            {@link CompilerConfigurationFactory#selectFactory(String)}
  97      */
  98     @SuppressWarnings("try")
  99     HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory) {
 100 
 101         HotSpotVMConfigStore store = jvmciRuntime.getConfigStore();
 102         config = new GraalHotSpotVMConfig(store);
 103         CompileTheWorldOptions.overrideWithNativeOptions(config);
 104 
 105         // Only set HotSpotPrintInlining if it still has its default value (false).
 106         if (GraalOptions.HotSpotPrintInlining.getValue() == false) {
 107             GraalOptions.HotSpotPrintInlining.setValue(config.printInlining);
 108         }
 109 
 110         CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
 111         BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
 112 
 113         JVMCIBackend hostJvmciBackend = jvmciRuntime.getHostJVMCIBackend();
 114         Architecture hostArchitecture = hostJvmciBackend.getTarget().arch;
 115         try (InitTimer t = timer("create backend:", hostArchitecture)) {
 116             HotSpotBackendFactory factory = backendMap.getBackendFactory(hostArchitecture);
 117             if (factory == null) {
 118                 throw new GraalError("No backend available for host architecture \"%s\"", hostArchitecture);
 119             }
 120             hostBackend = registerBackend(factory.createBackend(this, compilerConfiguration, jvmciRuntime, null));
 121         }
 122 
 123         for (JVMCIBackend jvmciBackend : jvmciRuntime.getJVMCIBackends().values()) {
 124             if (jvmciBackend == hostJvmciBackend) {
 125                 continue;
 126             }
 127 
 128             Architecture gpuArchitecture = jvmciBackend.getTarget().arch;
 129             HotSpotBackendFactory factory = backendMap.getBackendFactory(gpuArchitecture);
 130             if (factory == null) {
 131                 throw new GraalError("No backend available for specified GPU architecture \"%s\"", gpuArchitecture);
 132             }
 133             try (InitTimer t = timer("create backend:", gpuArchitecture)) {
 134                 registerBackend(factory.createBackend(this, compilerConfiguration, null, hostBackend));
 135             }
 136         }
 137 
 138         if (Log.getValue() == null && !areScopedGlobalMetricsEnabled() && Dump.getValue() == null && Verify.getValue() == null) {
 139             if (MethodFilter.getValue() != null && !Debug.isEnabled()) {
 140                 TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, TrackMemUse, Dump and Verify options are all null");
 141             }
 142         }
 143 
 144         if (Debug.isEnabled()) {
 145             DebugEnvironment.initialize(TTY.out, hostBackend.getProviders().getSnippetReflection());
 146 
 147             String summary = DebugValueSummary.getValue();
 148             if (summary != null) {
 149                 switch (summary) {
 150                     case "Name":
 151                     case "Partial":
 152                     case "Complete":
 153                     case "Thread":
 154                         break;
 155                     default:
 156                         throw new GraalError("Unsupported value for DebugSummaryValue: %s", summary);
 157                 }
 158             }
 159         }
 160 
 161         if (Debug.areUnconditionalCountersEnabled() || Debug.areUnconditionalTimersEnabled() || Debug.areUnconditionalMethodMetricsEnabled() ||
 162                         (Debug.isEnabled() && areScopedGlobalMetricsEnabled()) || (Debug.isEnabled() && Debug.isMethodFilteringEnabled())) {
 163             // This must be created here to avoid loading the DebugValuesPrinter class
 164             // during shutdown() which in turn can cause a deadlock
 165             int mmPrinterType = 0;
 166             mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue() ? 1 : 0;
 167             mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterFile.getValue() != null ? 2 : 0;
 168             switch (mmPrinterType) {
 169                 case 0:
 170                     debugValuesPrinter = new DebugValuesPrinter();
 171                     break;
 172                 case 1:
 173                     debugValuesPrinter = new DebugValuesPrinter(new MethodMetricsPrinter.MethodMetricsASCIIPrinter(TTY.out));
 174                     break;
 175                 case 2:
 176                     debugValuesPrinter = new DebugValuesPrinter(new MethodMetricsPrinter.MethodMetricsCSVFilePrinter());
 177                     break;
 178                 case 3:
 179                     debugValuesPrinter = new DebugValuesPrinter(
 180                                     new MethodMetricsPrinter.MethodMetricsCompositePrinter(new MethodMetricsPrinter.MethodMetricsCSVFilePrinter(),
 181                                                     new MethodMetricsPrinter.MethodMetricsASCIIPrinter(TTY.out)));
 182                     break;
 183                 default:
 184                     break;
 185             }
 186         }
 187 
 188         // Complete initialization of backends
 189         try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) {
 190             hostBackend.completeInitialization(jvmciRuntime);
 191         }
 192         for (HotSpotBackend backend : backends.values()) {
 193             if (backend != hostBackend) {
 194                 try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) {
 195                     backend.completeInitialization(jvmciRuntime);
 196                 }
 197             }
 198         }
 199 
 200         BenchmarkCounters.initialize(jvmciRuntime);
 201 
 202         assert checkArrayIndexScaleInvariants();
 203 
 204         runtimeStartTime = System.nanoTime();
 205         bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
 206     }
 207 
 208     private HotSpotBackend registerBackend(HotSpotBackend backend) {
 209         Class<? extends Architecture> arch = backend.getTarget().arch.getClass();
 210         HotSpotBackend oldValue = backends.put(arch, backend);
 211         assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName();
 212         return backend;
 213     }
 214 
 215     @Override
 216     public HotSpotProviders getHostProviders() {
 217         return getHostBackend().getProviders();
 218     }
 219 
 220     @Override
 221     public GraalHotSpotVMConfig getVMConfig() {
 222         return config;
 223     }
 224 
 225     @Override
 226     public String getName() {
 227         return getClass().getSimpleName();
 228     }
 229 
 230     private final NodeCollectionsProvider nodeCollectionsProvider = new DefaultNodeCollectionsProvider();
 231 
 232     @SuppressWarnings("unchecked")
 233     @Override
 234     public <T> T getCapability(Class<T> clazz) {
 235         if (clazz == RuntimeProvider.class) {
 236             return (T) this;
 237         } else if (clazz == CollectionsProvider.class || clazz == NodeCollectionsProvider.class) {
 238             return (T) nodeCollectionsProvider;
 239         } else if (clazz == StackIntrospection.class) {
 240             return (T) this;
 241         } else if (clazz == SnippetReflectionProvider.class) {
 242             return (T) getHostProviders().getSnippetReflection();
 243         } else if (clazz == StampProvider.class) {
 244             return (T) getHostProviders().getStampProvider();
 245         }
 246         return null;
 247     }
 248 
 249     @Override
 250     public HotSpotBackend getHostBackend() {
 251         return hostBackend;
 252     }
 253 
 254     @Override
 255     public <T extends Architecture> Backend getBackend(Class<T> arch) {
 256         assert arch != Architecture.class;
 257         return backends.get(arch);
 258     }
 259 
 260     public Map<Class<? extends Architecture>, HotSpotBackend> getBackends() {
 261         return Collections.unmodifiableMap(backends);
 262     }
 263 
 264     private long runtimeStartTime;
 265 
 266     /**
 267      * Take action related to entering a new execution phase.
 268      *
 269      * @param phase the execution phase being entered
 270      */
 271     static void phaseTransition(String phase) {
 272         CompilationStatistics.clear(phase);
 273     }
 274 
 275     void shutdown() {
 276         if (debugValuesPrinter != null) {
 277             debugValuesPrinter.printDebugValues();
 278         }
 279         phaseTransition("final");
 280 
 281         SnippetCounter.printGroups(TTY.out().out());
 282         BenchmarkCounters.shutdown(runtime(), runtimeStartTime);
 283     }
 284 
 285     void clearMeters() {
 286         if (debugValuesPrinter != null) {
 287             debugValuesPrinter.clearDebugValues();
 288         }
 289     }
 290 
 291     private final boolean bootstrapJVMCI;
 292     private boolean bootstrapFinished;
 293 
 294     public void notifyBootstrapFinished() {
 295         bootstrapFinished = true;
 296     }
 297 
 298     @Override
 299     public boolean isBootstrapping() {
 300         return bootstrapJVMCI && !bootstrapFinished;
 301     }
 302 }