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