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 }