1 /* 2 * Copyright (c) 2015, 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 jdk.internal.jvmci.hotspot; 24 25 import static jdk.internal.jvmci.inittimer.InitTimer.*; 26 27 import java.util.*; 28 29 import jdk.internal.jvmci.code.*; 30 import jdk.internal.jvmci.common.*; 31 import jdk.internal.jvmci.compiler.*; 32 import jdk.internal.jvmci.compiler.Compiler; 33 import jdk.internal.jvmci.inittimer.*; 34 import jdk.internal.jvmci.meta.*; 35 import jdk.internal.jvmci.runtime.*; 36 import jdk.internal.jvmci.service.*; 37 38 //JaCoCo Exclude 39 40 public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, HotSpotProxified { 41 42 /** 43 * The proper initialization of this class is complex because it's tangled up with the 44 * initialization of the JVMCI and really should only ever be triggered through 45 * {@link JVMCI#getRuntime}. However since {@link #runtime} can also be called directly it 46 * should also trigger proper initialization. To ensure proper ordering, the static initializer 47 * of this class initializes {@link JVMCI} and then access to {@link DelayedInit#instance} 48 * triggers the final initialization of the {@link HotSpotJVMCIRuntime}. 49 */ 50 static { 51 JVMCI.initialize(); 52 } 53 54 @SuppressWarnings("try") 55 static class DelayedInit { 56 private static final HotSpotJVMCIRuntime instance; 57 58 static { 59 try (InitTimer t0 = timer("HotSpotJVMCIRuntime.<clinit>")) { 60 try (InitTimer t = timer("StartupEventListener.beforeJVMCIStartup")) { 61 for (StartupEventListener l : Services.load(StartupEventListener.class)) { 62 l.beforeJVMCIStartup(); 63 } 64 } 65 66 try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) { 67 instance = new HotSpotJVMCIRuntime(); 68 } 69 70 try (InitTimer t = timer("HotSpotJVMCIRuntime.completeInitialization")) { 71 instance.completeInitialization(); 72 } 73 } 74 } 75 } 76 77 /** 78 * Gets the singleton {@link HotSpotJVMCIRuntime} object. 79 */ 80 public static HotSpotJVMCIRuntime runtime() { 81 assert DelayedInit.instance != null; 82 return DelayedInit.instance; 83 } 84 85 /** 86 * Do deferred initialization. 87 */ 88 public void completeInitialization() { 89 compiler = HotSpotJVMCICompilerConfig.getCompilerFactory().createCompiler(this); 90 for (HotSpotVMEventListener vmEventListener : vmEventListeners) { 91 vmEventListener.completeInitialization(this); 92 } 93 } 94 95 public static HotSpotJVMCIBackendFactory findFactory(String architecture) { 96 for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) { 97 if (factory.getArchitecture().equalsIgnoreCase(architecture)) { 98 return factory; 99 } 100 } 101 102 throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture); 103 } 104 105 /** 106 * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend. 107 */ 108 public static JavaKind getHostWordKind() { 109 return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordKind; 110 } 111 112 protected final CompilerToVM compilerToVm; 113 114 protected final HotSpotVMConfig config; 115 private final JVMCIBackend hostBackend; 116 117 private Compiler compiler; 118 protected final JVMCIMetaAccessContext metaAccessContext; 119 120 private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>(); 121 122 private final Iterable<HotSpotVMEventListener> vmEventListeners; 123 124 @SuppressWarnings("try") 125 private HotSpotJVMCIRuntime() { 126 compilerToVm = new CompilerToVM(); 127 try (InitTimer t = timer("HotSpotVMConfig<init>")) { 128 config = new HotSpotVMConfig(compilerToVm); 129 } 130 131 String hostArchitecture = config.getHostArchitectureName(); 132 133 HotSpotJVMCIBackendFactory factory; 134 try (InitTimer t = timer("find factory:", hostArchitecture)) { 135 factory = findFactory(hostArchitecture); 136 } 137 138 CompilerFactory compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory(); 139 140 try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) { 141 hostBackend = registerBackend(factory.createJVMCIBackend(this, compilerFactory, null)); 142 } 143 144 vmEventListeners = Services.load(HotSpotVMEventListener.class); 145 146 JVMCIMetaAccessContext context = null; 147 for (HotSpotVMEventListener vmEventListener : vmEventListeners) { 148 context = vmEventListener.createMetaAccessContext(this); 149 if (context != null) { 150 break; 151 } 152 } 153 if (context == null) { 154 context = new HotSpotJVMCIMetaAccessContext(); 155 } 156 metaAccessContext = context; 157 } 158 159 private JVMCIBackend registerBackend(JVMCIBackend backend) { 160 Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass(); 161 JVMCIBackend oldValue = backends.put(arch, backend); 162 assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName(); 163 return backend; 164 } 165 166 public ResolvedJavaType fromClass(Class<?> javaClass) { 167 return metaAccessContext.fromClass(javaClass); 168 } 169 170 public HotSpotVMConfig getConfig() { 171 return config; 172 } 173 174 public CompilerToVM getCompilerToVM() { 175 return compilerToVm; 176 } 177 178 public JVMCIMetaAccessContext getMetaAccessContext() { 179 return metaAccessContext; 180 } 181 182 public Compiler getCompiler() { 183 return compiler; 184 } 185 186 public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) { 187 Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class"); 188 // If the name represents a primitive type we can short-circuit the lookup. 189 if (name.length() == 1) { 190 JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)); 191 return fromClass(kind.toJavaClass()); 192 } 193 194 // Resolve non-primitive types in the VM. 195 HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType; 196 final HotSpotResolvedObjectTypeImpl klass = compilerToVm.lookupType(name, hsAccessingType.mirror(), resolve); 197 198 if (klass == null) { 199 assert resolve == false; 200 return HotSpotUnresolvedJavaType.create(this, name); 201 } 202 return klass; 203 } 204 205 public JVMCIBackend getHostJVMCIBackend() { 206 return hostBackend; 207 } 208 209 public <T extends Architecture> JVMCIBackend getJVMCIBackend(Class<T> arch) { 210 assert arch != Architecture.class; 211 return backends.get(arch); 212 } 213 214 public Map<Class<? extends Architecture>, JVMCIBackend> getBackends() { 215 return Collections.unmodifiableMap(backends); 216 } 217 218 /** 219 * Called from the VM. 220 */ 221 @SuppressWarnings({"unused"}) 222 private void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) { 223 compiler.compileMethod(method, entryBCI, jvmciEnv, id); 224 } 225 226 /** 227 * Shuts down the runtime. 228 * 229 * Called from the VM. 230 */ 231 @SuppressWarnings({"unused"}) 232 private void shutdown() throws Exception { 233 for (HotSpotVMEventListener vmEventListener : vmEventListeners) { 234 vmEventListener.notifyShutdown(); 235 } 236 } 237 238 /** 239 * Shuts down the runtime. 240 * 241 * Called from the VM. 242 * 243 * @param hotSpotCodeCacheProvider 244 */ 245 void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompilationResult compResult) { 246 for (HotSpotVMEventListener vmEventListener : vmEventListeners) { 247 vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compResult); 248 } 249 } 250 }