comparison graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/jvmci/HotSpotJVMCIRuntime.java @ 21527:07b088d61d5d

added HotSpotJVMCIRuntime* classes, replaced references to HotSpotGraalRuntime in VM with HotSpotJVMCIRuntime (JBS:GRAAL-53)
author Doug Simon <doug.simon@oracle.com>
date Fri, 22 May 2015 23:26:20 +0200
parents
children de0cf192779c
comparison
equal deleted inserted replaced
21526:1da7aef31a08 21527:07b088d61d5d
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 com.oracle.graal.hotspot.jvmci;
24
25 import static com.oracle.graal.compiler.common.UnsafeAccess.*;
26 import static com.oracle.graal.hotspot.jvmci.InitTimer.*;
27
28 import java.lang.reflect.*;
29 import java.util.*;
30
31 import com.oracle.graal.api.code.*;
32 import com.oracle.graal.api.meta.*;
33 import com.oracle.graal.api.runtime.*;
34 import com.oracle.graal.debug.*;
35 import com.oracle.graal.hotspot.*;
36 import com.oracle.graal.hotspot.jvmci.logging.*;
37 import com.oracle.graal.options.*;
38 import com.oracle.jvmci.runtime.*;
39
40 //JaCoCo Exclude
41
42 public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, HotSpotProxified {
43
44 private static final HotSpotJVMCIRuntime instance;
45
46 static {
47 try (InitTimer t0 = timer("HotSpotJVMCIRuntime.<clinit>")) {
48 try (InitTimer t = timer("initialize HotSpotOptions")) {
49 HotSpotOptions.initialize();
50 }
51
52 try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
53 instance = new HotSpotJVMCIRuntime();
54 }
55
56 try (InitTimer t = timer("HotSpotJVMCIRuntime.completeInitialization")) {
57 // Why deferred initialization? See comment in completeInitialization().
58 instance.completeInitialization();
59 }
60 }
61 }
62
63 /**
64 * Gets the singleton {@link HotSpotJVMCIRuntime} object.
65 */
66 public static HotSpotJVMCIRuntime runtime() {
67 assert instance != null;
68 return instance;
69 }
70
71 /**
72 * Do deferred initialization.
73 */
74 public void completeInitialization() {
75 TTY.initialize(Options.LogFile.getStream(compilerToVm));
76
77 // Proxies for the VM/Compiler interfaces cannot be initialized
78 // in the constructor as proxy creation causes static
79 // initializers to be executed for all the types involved in the
80 // proxied methods. Some of these static initializers (e.g. in
81 // HotSpotMethodData) rely on the static 'instance' field being set
82 // to retrieve configuration details.
83 CompilerToVM toVM = this.compilerToVm;
84
85 if (CountingProxy.ENABLED) {
86 toVM = CountingProxy.getProxy(CompilerToVM.class, toVM);
87 }
88 if (Logger.ENABLED) {
89 toVM = LoggingProxy.getProxy(CompilerToVM.class, toVM);
90 }
91
92 this.compilerToVm = toVM;
93 }
94
95 public static class Options {
96
97 // @formatter:off
98 @Option(help = "The JVMCI runtime configuration to use", type = OptionType.Expert)
99 public static final OptionValue<String> JVMCIRuntime = new OptionValue<>("");
100
101 @Option(help = "File to which logging is sent. A %p in the name will be replaced with a string identifying the process, usually the process id.", type = OptionType.Expert)
102 public static final PrintStreamOption LogFile = new PrintStreamOption();
103 // @formatter:on
104 }
105
106 public static HotSpotJVMCIBackendFactory findFactory(String architecture) {
107 HotSpotJVMCIBackendFactory basic = null;
108 HotSpotJVMCIBackendFactory selected = null;
109 HotSpotJVMCIBackendFactory nonBasic = null;
110 int nonBasicCount = 0;
111
112 for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) {
113 if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
114 if (factory.getJVMCIRuntimeName().equals(Options.JVMCIRuntime.getValue())) {
115 assert selected == null || checkFactoryOverriding(selected, factory);
116 selected = factory;
117 }
118 if (factory.getJVMCIRuntimeName().equals("basic")) {
119 assert basic == null || checkFactoryOverriding(basic, factory);
120 basic = factory;
121 } else {
122 nonBasic = factory;
123 nonBasicCount++;
124 }
125 }
126 }
127
128 if (selected != null) {
129 return selected;
130 } else {
131 if (!Options.JVMCIRuntime.getValue().equals("")) {
132 // Fail fast if a non-default value for JVMCIRuntime was specified
133 // and the corresponding factory is not available
134 throw new InternalError(String.format("Specified runtime \"%s\" not available for the %s architecture", Options.JVMCIRuntime.getValue(), architecture));
135 } else if (nonBasicCount == 1) {
136 // If there is exactly one non-basic runtime, select this one.
137 return nonBasic;
138 } else {
139 return basic;
140 }
141 }
142 }
143
144 /**
145 * Checks that a factory overriding is valid. A factory B can only override/replace a factory A
146 * if the B.getClass() is a subclass of A.getClass(). This models the assumption that B is
147 * extends the behavior of A and has therefore understood the behavior expected of A.
148 *
149 * @param baseFactory
150 * @param overridingFactory
151 */
152 private static boolean checkFactoryOverriding(HotSpotJVMCIBackendFactory baseFactory, HotSpotJVMCIBackendFactory overridingFactory) {
153 return baseFactory.getClass().isAssignableFrom(overridingFactory.getClass());
154 }
155
156 /**
157 * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend.
158 */
159 public static Kind getHostWordKind() {
160 return instance.getHostJVMCIBackend().getCodeCache().getTarget().wordKind;
161 }
162
163 /**
164 * Reads a klass pointer from a constant object.
165 */
166 public static long unsafeReadKlassPointer(Object object) {
167 return instance.getCompilerToVM().readUnsafeKlassPointer(object);
168 }
169
170 /**
171 * Reads a word value from a given object.
172 */
173 public static long unsafeReadWord(Object object, long offset) {
174 if (getHostWordKind() == Kind.Long) {
175 return unsafe.getLong(object, offset);
176 }
177 return unsafe.getInt(object, offset) & 0xFFFFFFFFL;
178 }
179
180 protected/* final */CompilerToVM compilerToVm;
181
182 protected final HotSpotVMConfig config;
183 private final JVMCIBackend hostBackend;
184
185 /**
186 * Graal mirrors are stored as a {@link ClassValue} associated with the {@link Class} of the
187 * type. This data structure stores both {@link HotSpotResolvedObjectType} and
188 * {@link HotSpotResolvedPrimitiveType} types.
189 */
190 private final ClassValue<ResolvedJavaType> graalMirrors = new ClassValue<ResolvedJavaType>() {
191 @Override
192 protected ResolvedJavaType computeValue(Class<?> javaClass) {
193 if (javaClass.isPrimitive()) {
194 Kind kind = Kind.fromJavaClass(javaClass);
195 return new HotSpotResolvedPrimitiveType(kind);
196 } else {
197 return new HotSpotResolvedObjectTypeImpl(javaClass);
198 }
199 }
200 };
201
202 private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
203
204 private HotSpotJVMCIRuntime() {
205 CompilerToVM toVM = new CompilerToVMImpl();
206 compilerToVm = toVM;
207 try (InitTimer t = timer("HotSpotVMConfig<init>")) {
208 config = new HotSpotVMConfig(compilerToVm);
209 }
210
211 if (Boolean.valueOf(System.getProperty("graal.printconfig"))) {
212 printConfig(config);
213 }
214
215 String hostArchitecture = config.getHostArchitectureName();
216
217 HotSpotJVMCIBackendFactory factory;
218 try (InitTimer t = timer("find factory:", hostArchitecture)) {
219 factory = findFactory(hostArchitecture);
220 }
221 try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
222 hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
223 }
224 }
225
226 private JVMCIBackend registerBackend(JVMCIBackend backend) {
227 Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass();
228 JVMCIBackend oldValue = backends.put(arch, backend);
229 assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName();
230 return backend;
231 }
232
233 public ResolvedJavaType fromClass(Class<?> javaClass) {
234 return graalMirrors.get(javaClass);
235 }
236
237 private static void printConfig(HotSpotVMConfig config) {
238 Field[] fields = config.getClass().getDeclaredFields();
239 Map<String, Field> sortedFields = new TreeMap<>();
240 for (Field f : fields) {
241 f.setAccessible(true);
242 sortedFields.put(f.getName(), f);
243 }
244 for (Field f : sortedFields.values()) {
245 try {
246 Logger.info(String.format("%9s %-40s = %s", f.getType().getSimpleName(), f.getName(), Logger.pretty(f.get(config))));
247 } catch (Exception e) {
248 }
249 }
250 }
251
252 public HotSpotVMConfig getConfig() {
253 return config;
254 }
255
256 public CompilerToVM getCompilerToVM() {
257 return compilerToVm;
258 }
259
260 public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
261 Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
262 // If the name represents a primitive type we can short-circuit the lookup.
263 if (name.length() == 1) {
264 Kind kind = Kind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
265 return fromClass(kind.toJavaClass());
266 }
267
268 // Resolve non-primitive types in the VM.
269 HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType;
270 final long metaspaceKlass = compilerToVm.lookupType(name, hsAccessingType.mirror(), resolve);
271
272 if (metaspaceKlass == 0L) {
273 assert resolve == false;
274 return HotSpotUnresolvedJavaType.create(this, name);
275 }
276 return HotSpotResolvedObjectTypeImpl.fromMetaspaceKlass(metaspaceKlass);
277 }
278
279 public JVMCIBackend getHostJVMCIBackend() {
280 return hostBackend;
281 }
282
283 public <T extends Architecture> JVMCIBackend getJVMCIBackend(Class<T> arch) {
284 assert arch != Architecture.class;
285 return backends.get(arch);
286 }
287
288 public Map<Class<? extends Architecture>, JVMCIBackend> getBackends() {
289 return Collections.unmodifiableMap(backends);
290 }
291
292 private HotSpotVMEventListener vmEventListener;
293
294 public void registerVMEventListener(HotSpotVMEventListener l) {
295 assert vmEventListener == null : "cannot register multiple HotSpotVMEventListeners";
296 vmEventListener = l;
297 }
298
299 /**
300 * Called from the VM.
301 */
302 @SuppressWarnings("unused")
303 private void compileTheWorld() throws Throwable {
304 if (vmEventListener != null) {
305 vmEventListener.notifyCompileTheWorld();
306 }
307 }
308
309 /**
310 * Shuts down the runtime.
311 *
312 * Called from the VM.
313 */
314 @SuppressWarnings("unused")
315 private void shutdown() throws Exception {
316 if (vmEventListener != null) {
317 vmEventListener.notifyShutdown();
318 }
319 }
320 }