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 }