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 }