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