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 jdk.vm.ci.hotspot; 24 25 import static jdk.vm.ci.inittimer.InitTimer.timer; 26 27 import java.io.IOException; 28 import java.io.OutputStream; 29 import java.io.PrintStream; 30 import java.lang.reflect.Array; 31 import java.lang.reflect.Field; 32 import java.lang.reflect.Method; 33 import java.lang.reflect.Modifier; 34 import java.util.Collections; 35 import java.util.HashMap; 36 import java.util.Map; 37 import java.util.Objects; 38 import java.util.TreeMap; 39 40 import jdk.vm.ci.code.Architecture; 41 import jdk.vm.ci.code.CompilationRequestResult; 42 import jdk.vm.ci.code.CompiledCode; 43 import jdk.vm.ci.code.InstalledCode; 44 import jdk.vm.ci.common.JVMCIError; 45 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory; 46 import jdk.vm.ci.hotspot.services.HotSpotVMEventListener; 47 import jdk.vm.ci.inittimer.InitTimer; 48 import jdk.vm.ci.inittimer.SuppressFBWarnings; 49 import jdk.vm.ci.meta.JVMCIMetaAccessContext; 50 import jdk.vm.ci.meta.JavaKind; 51 import jdk.vm.ci.meta.JavaType; 52 import jdk.vm.ci.meta.ResolvedJavaType; 53 import jdk.vm.ci.runtime.JVMCI; 54 import jdk.vm.ci.runtime.JVMCIBackend; 55 import jdk.vm.ci.runtime.JVMCICompiler; 56 import jdk.vm.ci.runtime.services.JVMCICompilerFactory; 57 import jdk.vm.ci.services.Services; 58 import jdk.internal.misc.VM; 59 60 //JaCoCo Exclude 61 62 /** 63 * HotSpot implementation of a JVMCI runtime. 64 * 65 * The initialization of this class is very fragile since it's initialized both through 66 * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and 67 * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class 68 * can't have a static initializer and any required initialization must be done as part of 69 * {@link #runtime()}. This allows the initialization to funnel back through 70 * {@link JVMCI#initialize()} without deadlocking. 71 */ 72 public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, HotSpotProxified { 73 74 @SuppressWarnings("try") 75 static class DelayedInit { 76 private static final HotSpotJVMCIRuntime instance; 77 78 static { 79 try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) { 80 instance = new HotSpotJVMCIRuntime(); 81 } 82 } 83 } 84 85 /** 86 * Gets the singleton {@link HotSpotJVMCIRuntime} object. 87 */ 88 public static HotSpotJVMCIRuntime runtime() { 89 JVMCI.initialize(); 90 return DelayedInit.instance; 91 } 92 190 } 191 192 throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture); 193 } 194 195 /** 196 * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend. 197 */ 198 public static JavaKind getHostWordKind() { 199 return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind; 200 } 201 202 protected final CompilerToVM compilerToVm; 203 204 protected final HotSpotVMConfig config; 205 private final JVMCIBackend hostBackend; 206 207 private final JVMCICompilerFactory compilerFactory; 208 private final HotSpotJVMCICompilerFactory hsCompilerFactory; 209 private volatile JVMCICompiler compiler; 210 protected final JVMCIMetaAccessContext metaAccessContext; 211 212 /** 213 * Stores the result of {@link HotSpotJVMCICompilerFactory#getCompilationLevelAdjustment} so 214 * that it can be read from the VM. 215 */ 216 @SuppressWarnings("unused") private final int compilationLevelAdjustment; 217 218 private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>(); 219 220 private final Iterable<HotSpotVMEventListener> vmEventListeners; 221 222 /** 223 * Stores the result of {@link HotSpotJVMCICompilerFactory#getTrivialPrefixes()} so that it can 224 * be read from the VM. 225 */ 226 @SuppressWarnings("unused") private final String[] trivialPrefixes; 227 228 @SuppressWarnings("try") 229 private HotSpotJVMCIRuntime() { 230 compilerToVm = new CompilerToVM(); 231 232 try (InitTimer t = timer("HotSpotVMConfig<init>")) { 233 config = new HotSpotVMConfig(compilerToVm); 234 } 235 236 String hostArchitecture = config.getHostArchitectureName(); 237 238 HotSpotJVMCIBackendFactory factory; 239 try (InitTimer t = timer("find factory:", hostArchitecture)) { 240 factory = findFactory(hostArchitecture); 241 } 242 243 try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) { 244 hostBackend = registerBackend(factory.createJVMCIBackend(this, null)); 245 } 246 247 vmEventListeners = Services.load(HotSpotVMEventListener.class); 248 249 JVMCIMetaAccessContext context = null; 250 for (HotSpotVMEventListener vmEventListener : vmEventListeners) { 251 context = vmEventListener.createMetaAccessContext(this); 252 if (context != null) { 253 break; 254 } 255 } 256 if (context == null) { 257 context = new HotSpotJVMCIMetaAccessContext(); 258 } 259 metaAccessContext = context; 260 261 boolean printFlags = Option.PrintFlags.getBoolean(); 262 boolean showFlags = Option.ShowFlags.getBoolean(); 263 if (printFlags || showFlags) { 264 Option.printFlags(System.out); 265 if (printFlags) { 266 System.exit(0); 267 } 268 } 269 270 if (Option.PrintConfig.getBoolean()) { 271 printConfig(config, compilerToVm); 272 } 273 274 compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory(); 275 if (compilerFactory instanceof HotSpotJVMCICompilerFactory) { 276 hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory; 277 trivialPrefixes = hsCompilerFactory.getTrivialPrefixes(); 278 compilationLevelAdjustment = hsCompilerFactory.getCompilationLevelAdjustment(config); 279 } else { 285 286 private JVMCIBackend registerBackend(JVMCIBackend backend) { 287 Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass(); 288 JVMCIBackend oldValue = backends.put(arch, backend); 289 assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName(); 290 return backend; 291 } 292 293 public ResolvedJavaType fromClass(Class<?> javaClass) { 294 return metaAccessContext.fromClass(javaClass); 295 } 296 297 public HotSpotVMConfig getConfig() { 298 return config; 299 } 300 301 public CompilerToVM getCompilerToVM() { 302 return compilerToVm; 303 } 304 305 public JVMCIMetaAccessContext getMetaAccessContext() { 306 return metaAccessContext; 307 } 308 309 public JVMCICompiler getCompiler() { 310 if (compiler == null) { 311 synchronized (this) { 312 if (compiler == null) { 313 compiler = compilerFactory.createCompiler(this); 314 } 315 } 316 } 317 return compiler; 318 } 319 320 public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) { 321 Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class"); 322 // If the name represents a primitive type we can short-circuit the lookup. 323 if (name.length() == 1) { 324 JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)); 325 return fromClass(kind.toJavaClass()); 326 } 327 328 // Resolve non-primitive types in the VM. 344 assert arch != Architecture.class; 345 return backends.get(arch); 346 } 347 348 public Map<Class<? extends Architecture>, JVMCIBackend> getJVMCIBackends() { 349 return Collections.unmodifiableMap(backends); 350 } 351 352 /** 353 * Called from the VM. 354 */ 355 @SuppressWarnings({"unused"}) 356 private int adjustCompilationLevel(Class<?> declaringClass, String name, String signature, boolean isOsr, int level) { 357 return hsCompilerFactory.adjustCompilationLevel(config, declaringClass, name, signature, isOsr, level); 358 } 359 360 /** 361 * Called from the VM. 362 */ 363 @SuppressWarnings({"unused"}) 364 private CompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) { 365 CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id)); 366 assert result != null : "compileMethod must always return something"; 367 return result; 368 } 369 370 /** 371 * Shuts down the runtime. 372 * 373 * Called from the VM. 374 */ 375 @SuppressWarnings({"unused"}) 376 private void shutdown() throws Exception { 377 for (HotSpotVMEventListener vmEventListener : vmEventListeners) { 378 vmEventListener.notifyShutdown(); 379 } 380 } 381 382 /** 383 * Notify on completion of a bootstrap. 384 * 385 * Called from the VM. 386 */ 387 @SuppressWarnings({"unused"}) | 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 jdk.vm.ci.hotspot; 24 25 import static jdk.vm.ci.common.InitTimer.timer; 26 27 import java.io.IOException; 28 import java.io.OutputStream; 29 import java.io.PrintStream; 30 import java.lang.reflect.Array; 31 import java.lang.reflect.Field; 32 import java.lang.reflect.Method; 33 import java.lang.reflect.Modifier; 34 import java.util.Collections; 35 import java.util.HashMap; 36 import java.util.Map; 37 import java.util.Objects; 38 import java.util.TreeMap; 39 40 import jdk.internal.misc.VM; 41 import jdk.vm.ci.code.Architecture; 42 import jdk.vm.ci.code.CompilationRequestResult; 43 import jdk.vm.ci.code.CompiledCode; 44 import jdk.vm.ci.code.InstalledCode; 45 import jdk.vm.ci.common.InitTimer; 46 import jdk.vm.ci.common.JVMCIError; 47 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory; 48 import jdk.vm.ci.hotspot.services.HotSpotVMEventListener; 49 import jdk.vm.ci.meta.JavaKind; 50 import jdk.vm.ci.meta.JavaType; 51 import jdk.vm.ci.meta.ResolvedJavaType; 52 import jdk.vm.ci.runtime.JVMCI; 53 import jdk.vm.ci.runtime.JVMCIBackend; 54 import jdk.vm.ci.runtime.JVMCICompiler; 55 import jdk.vm.ci.runtime.services.JVMCICompilerFactory; 56 import jdk.vm.ci.services.Services; 57 58 /** 59 * HotSpot implementation of a JVMCI runtime. 60 * 61 * The initialization of this class is very fragile since it's initialized both through 62 * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and 63 * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class 64 * can't have a static initializer and any required initialization must be done as part of 65 * {@link #runtime()}. This allows the initialization to funnel back through 66 * {@link JVMCI#initialize()} without deadlocking. 67 */ 68 public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider { 69 70 @SuppressWarnings("try") 71 static class DelayedInit { 72 private static final HotSpotJVMCIRuntime instance; 73 74 static { 75 try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) { 76 instance = new HotSpotJVMCIRuntime(); 77 } 78 } 79 } 80 81 /** 82 * Gets the singleton {@link HotSpotJVMCIRuntime} object. 83 */ 84 public static HotSpotJVMCIRuntime runtime() { 85 JVMCI.initialize(); 86 return DelayedInit.instance; 87 } 88 186 } 187 188 throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture); 189 } 190 191 /** 192 * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend. 193 */ 194 public static JavaKind getHostWordKind() { 195 return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind; 196 } 197 198 protected final CompilerToVM compilerToVm; 199 200 protected final HotSpotVMConfig config; 201 private final JVMCIBackend hostBackend; 202 203 private final JVMCICompilerFactory compilerFactory; 204 private final HotSpotJVMCICompilerFactory hsCompilerFactory; 205 private volatile JVMCICompiler compiler; 206 protected final HotSpotJVMCIMetaAccessContext metaAccessContext; 207 208 /** 209 * Stores the result of {@link HotSpotJVMCICompilerFactory#getCompilationLevelAdjustment} so 210 * that it can be read from the VM. 211 */ 212 @SuppressWarnings("unused") private final int compilationLevelAdjustment; 213 214 private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>(); 215 216 private final Iterable<HotSpotVMEventListener> vmEventListeners; 217 218 /** 219 * Stores the result of {@link HotSpotJVMCICompilerFactory#getTrivialPrefixes()} so that it can 220 * be read from the VM. 221 */ 222 @SuppressWarnings("unused") private final String[] trivialPrefixes; 223 224 @SuppressWarnings("try") 225 private HotSpotJVMCIRuntime() { 226 compilerToVm = new CompilerToVM(); 227 228 try (InitTimer t = timer("HotSpotVMConfig<init>")) { 229 config = new HotSpotVMConfig(compilerToVm); 230 } 231 232 String hostArchitecture = config.getHostArchitectureName(); 233 234 HotSpotJVMCIBackendFactory factory; 235 try (InitTimer t = timer("find factory:", hostArchitecture)) { 236 factory = findFactory(hostArchitecture); 237 } 238 239 try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) { 240 hostBackend = registerBackend(factory.createJVMCIBackend(this, null)); 241 } 242 243 vmEventListeners = Services.load(HotSpotVMEventListener.class); 244 245 metaAccessContext = new HotSpotJVMCIMetaAccessContext(); 246 247 boolean printFlags = Option.PrintFlags.getBoolean(); 248 boolean showFlags = Option.ShowFlags.getBoolean(); 249 if (printFlags || showFlags) { 250 Option.printFlags(System.out); 251 if (printFlags) { 252 System.exit(0); 253 } 254 } 255 256 if (Option.PrintConfig.getBoolean()) { 257 printConfig(config, compilerToVm); 258 } 259 260 compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory(); 261 if (compilerFactory instanceof HotSpotJVMCICompilerFactory) { 262 hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory; 263 trivialPrefixes = hsCompilerFactory.getTrivialPrefixes(); 264 compilationLevelAdjustment = hsCompilerFactory.getCompilationLevelAdjustment(config); 265 } else { 271 272 private JVMCIBackend registerBackend(JVMCIBackend backend) { 273 Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass(); 274 JVMCIBackend oldValue = backends.put(arch, backend); 275 assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName(); 276 return backend; 277 } 278 279 public ResolvedJavaType fromClass(Class<?> javaClass) { 280 return metaAccessContext.fromClass(javaClass); 281 } 282 283 public HotSpotVMConfig getConfig() { 284 return config; 285 } 286 287 public CompilerToVM getCompilerToVM() { 288 return compilerToVm; 289 } 290 291 public JVMCICompiler getCompiler() { 292 if (compiler == null) { 293 synchronized (this) { 294 if (compiler == null) { 295 compiler = compilerFactory.createCompiler(this); 296 } 297 } 298 } 299 return compiler; 300 } 301 302 public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) { 303 Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class"); 304 // If the name represents a primitive type we can short-circuit the lookup. 305 if (name.length() == 1) { 306 JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)); 307 return fromClass(kind.toJavaClass()); 308 } 309 310 // Resolve non-primitive types in the VM. 326 assert arch != Architecture.class; 327 return backends.get(arch); 328 } 329 330 public Map<Class<? extends Architecture>, JVMCIBackend> getJVMCIBackends() { 331 return Collections.unmodifiableMap(backends); 332 } 333 334 /** 335 * Called from the VM. 336 */ 337 @SuppressWarnings({"unused"}) 338 private int adjustCompilationLevel(Class<?> declaringClass, String name, String signature, boolean isOsr, int level) { 339 return hsCompilerFactory.adjustCompilationLevel(config, declaringClass, name, signature, isOsr, level); 340 } 341 342 /** 343 * Called from the VM. 344 */ 345 @SuppressWarnings({"unused"}) 346 private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) { 347 CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id)); 348 assert result != null : "compileMethod must always return something"; 349 HotSpotCompilationRequestResult hsResult; 350 if (result instanceof HotSpotCompilationRequestResult) { 351 hsResult = (HotSpotCompilationRequestResult) result; 352 } else { 353 Object failure = result.getFailure(); 354 if (failure != null) { 355 boolean retry = false; // Be conservative with unknown compiler 356 hsResult = HotSpotCompilationRequestResult.failure(failure.toString(), retry); 357 } else { 358 int inlinedBytecodes = -1; 359 hsResult = HotSpotCompilationRequestResult.success(inlinedBytecodes); 360 } 361 } 362 363 return hsResult; 364 } 365 366 /** 367 * Shuts down the runtime. 368 * 369 * Called from the VM. 370 */ 371 @SuppressWarnings({"unused"}) 372 private void shutdown() throws Exception { 373 for (HotSpotVMEventListener vmEventListener : vmEventListeners) { 374 vmEventListener.notifyShutdown(); 375 } 376 } 377 378 /** 379 * Notify on completion of a bootstrap. 380 * 381 * Called from the VM. 382 */ 383 @SuppressWarnings({"unused"}) |