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.ArrayList;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.ServiceLoader;
41 import java.util.TreeMap;
42
43 import jdk.internal.misc.VM;
44 import jdk.vm.ci.code.Architecture;
45 import jdk.vm.ci.code.CompilationRequestResult;
46 import jdk.vm.ci.code.CompiledCode;
47 import jdk.vm.ci.code.InstalledCode;
48 import jdk.vm.ci.common.InitTimer;
49 import jdk.vm.ci.common.JVMCIError;
50 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory;
51 import jdk.vm.ci.hotspot.services.HotSpotVMEventListener;
52 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory.CompilationLevel;
53 import jdk.vm.ci.meta.JavaKind;
54 import jdk.vm.ci.meta.JavaType;
55 import jdk.vm.ci.meta.ResolvedJavaType;
56 import jdk.vm.ci.runtime.JVMCI;
57 import jdk.vm.ci.runtime.JVMCIBackend;
58 import jdk.vm.ci.runtime.JVMCICompiler;
59 import jdk.vm.ci.runtime.services.JVMCICompilerFactory;
60 import jdk.vm.ci.services.Services;
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 {
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
93 /**
94 * A list of all supported JVMCI options.
95 */
96 public enum Option {
97 Compiler(String.class, null, "Selects the system compiler."),
98 // Note: The following one is not used (see InitTimer.ENABLED).
99 InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."),
100 PrintConfig(boolean.class, false, "Prints all HotSpotVMConfig fields."),
101 PrintFlags(boolean.class, false, "Prints all JVMCI flags and exits."),
102 ShowFlags(boolean.class, false, "Prints all JVMCI flags and continues."),
103 TraceMethodDataFilter(String.class, null, "");
104
105 /**
106 * The prefix for system properties that are JVMCI options.
107 */
108 private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
109
110 /**
111 * Marker for uninitialized flags.
112 */
113 private static final String UNINITIALIZED = "UNINITIALIZED";
114
115 private final Class<?> type;
116 private Object value;
117 private final Object defaultValue;
118 private boolean isDefault;
119 private final String help;
120
225 synchronized (this) {
226 if (vmEventListeners == null) {
227 List<HotSpotVMEventListener> listeners = new ArrayList<>();
228 for (HotSpotVMEventListener vmEventListener : ServiceLoader.load(HotSpotVMEventListener.class)) {
229 listeners.add(vmEventListener);
230 }
231 vmEventListeners = listeners;
232 }
233 }
234 }
235 return vmEventListeners;
236 }
237
238 /**
239 * Stores the result of {@link HotSpotJVMCICompilerFactory#getTrivialPrefixes()} so that it can
240 * be read from the VM.
241 */
242 @SuppressWarnings("unused") private final String[] trivialPrefixes;
243
244 @SuppressWarnings("try")
245 private HotSpotJVMCIRuntime() {
246 compilerToVm = new CompilerToVM();
247
248 try (InitTimer t = timer("HotSpotVMConfig<init>")) {
249 configStore = new HotSpotVMConfigStore(compilerToVm);
250 config = new HotSpotVMConfig(configStore);
251 }
252
253 String hostArchitecture = config.getHostArchitectureName();
254
255 HotSpotJVMCIBackendFactory factory;
256 try (InitTimer t = timer("find factory:", hostArchitecture)) {
257 factory = findFactory(hostArchitecture);
258 }
259
260 try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
261 hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
262 }
263
264 metaAccessContext = new HotSpotJVMCIMetaAccessContext();
265
266 boolean printFlags = Option.PrintFlags.getBoolean();
267 boolean showFlags = Option.ShowFlags.getBoolean();
268 if (printFlags || showFlags) {
269 Option.printFlags(System.out);
270 if (printFlags) {
271 System.exit(0);
272 }
273 }
274
275 if (Option.PrintConfig.getBoolean()) {
276 printConfig(config, compilerToVm);
277 }
278
279 compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
280 if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
281 hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
282 trivialPrefixes = hsCompilerFactory.getTrivialPrefixes();
283 switch (hsCompilerFactory.getCompilationLevelAdjustment()) {
284 case None:
285 compilationLevelAdjustment = config.compLevelAdjustmentNone;
286 break;
287 case ByHolder:
288 compilationLevelAdjustment = config.compLevelAdjustmentByHolder;
289 break;
290 case ByFullSignature:
291 compilationLevelAdjustment = config.compLevelAdjustmentByFullSignature;
292 break;
293 default:
294 compilationLevelAdjustment = config.compLevelAdjustmentNone;
295 break;
296 }
447 @SuppressWarnings({"unused"})
448 private void bootstrapFinished() throws Exception {
449 for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
450 vmEventListener.notifyBootstrapFinished();
451 }
452 }
453
454 /**
455 * Notify on successful install into the CodeCache.
456 *
457 * @param hotSpotCodeCacheProvider
458 * @param installedCode
459 * @param compiledCode
460 */
461 void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
462 for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
463 vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compiledCode);
464 }
465 }
466
467 private static void printConfig(HotSpotVMConfig config, CompilerToVM vm) {
468 Field[] fields = config.getClass().getDeclaredFields();
469 Map<String, Field> sortedFields = new TreeMap<>();
470 for (Field f : fields) {
471 if (!f.isSynthetic() && !Modifier.isStatic(f.getModifiers())) {
472 f.setAccessible(true);
473 sortedFields.put(f.getName(), f);
474 }
475 }
476 for (Field f : sortedFields.values()) {
477 try {
478 String line = String.format("%9s %-40s = %s%n", f.getType().getSimpleName(), f.getName(), pretty(f.get(config)));
479 byte[] lineBytes = line.getBytes();
480 vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
481 vm.flushDebugOutput();
482 } catch (Exception e) {
483 }
484 }
485 }
486
487 private static String pretty(Object value) {
488 if (value == null) {
489 return "null";
490 }
491
492 Class<?> klass = value.getClass();
493 if (value instanceof String) {
494 return "\"" + value + "\"";
495 } else if (value instanceof Method) {
496 return "method \"" + ((Method) value).getName() + "\"";
497 } else if (value instanceof Class<?>) {
498 return "class \"" + ((Class<?>) value).getSimpleName() + "\"";
499 } else if (value instanceof Integer) {
500 if ((Integer) value < 10) {
501 return value.toString();
502 }
503 return value + " (0x" + Integer.toHexString((Integer) value) + ")";
504 } else if (value instanceof Long) {
505 if ((Long) value < 10 && (Long) value > -10) {
506 return value + "l";
507 }
508 return value + "l (0x" + Long.toHexString((Long) value) + "l)";
509 } else if (klass.isArray()) {
510 StringBuilder str = new StringBuilder();
511 int dimensions = 0;
512 while (klass.isArray()) {
513 dimensions++;
514 klass = klass.getComponentType();
515 }
516 int length = Array.getLength(value);
517 str.append(klass.getSimpleName()).append('[').append(length).append(']');
518 for (int i = 1; i < dimensions; i++) {
519 str.append("[]");
520 }
521 str.append(" {");
522 for (int i = 0; i < length; i++) {
523 str.append(pretty(Array.get(value, i)));
524 if (i < length - 1) {
525 str.append(", ");
526 }
527 }
528 str.append('}');
529 return str.toString();
530 }
531 return value.toString();
532 }
533
534 public OutputStream getLogStream() {
535 return new OutputStream() {
536
537 @Override
538 public void write(byte[] b, int off, int len) throws IOException {
539 if (b == null) {
540 throw new NullPointerException();
541 } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length || (off + len) < 0) {
542 throw new IndexOutOfBoundsException();
543 } else if (len == 0) {
544 return;
545 }
546 compilerToVm.writeDebugOutput(b, off, len);
547 }
548
549 @Override
550 public void write(int b) throws IOException {
551 write(new byte[]{(byte) b}, 0, 1);
|
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.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.ServiceLoader;
37 import java.util.TreeMap;
38
39 import jdk.internal.misc.VM;
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.InitTimer;
45 import jdk.vm.ci.common.JVMCIError;
46 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory;
47 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory.CompilationLevel;
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 {
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
89 /**
90 * A list of all supported JVMCI options.
91 */
92 public enum Option {
93 Compiler(String.class, null, "Selects the system compiler."),
94 // Note: The following one is not used (see InitTimer.ENABLED). It is added here
95 // so that -Djvmci.PrintFlags=true shows the option.
96 InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."),
97 PrintConfig(boolean.class, false, "Prints VM configuration available via JVMCI and exits."),
98 PrintFlags(boolean.class, false, "Prints all JVMCI flags and exits."),
99 ShowFlags(boolean.class, false, "Prints all JVMCI flags and continues."),
100 TraceMethodDataFilter(String.class, null, "");
101
102 /**
103 * The prefix for system properties that are JVMCI options.
104 */
105 private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
106
107 /**
108 * Marker for uninitialized flags.
109 */
110 private static final String UNINITIALIZED = "UNINITIALIZED";
111
112 private final Class<?> type;
113 private Object value;
114 private final Object defaultValue;
115 private boolean isDefault;
116 private final String help;
117
222 synchronized (this) {
223 if (vmEventListeners == null) {
224 List<HotSpotVMEventListener> listeners = new ArrayList<>();
225 for (HotSpotVMEventListener vmEventListener : ServiceLoader.load(HotSpotVMEventListener.class)) {
226 listeners.add(vmEventListener);
227 }
228 vmEventListeners = listeners;
229 }
230 }
231 }
232 return vmEventListeners;
233 }
234
235 /**
236 * Stores the result of {@link HotSpotJVMCICompilerFactory#getTrivialPrefixes()} so that it can
237 * be read from the VM.
238 */
239 @SuppressWarnings("unused") private final String[] trivialPrefixes;
240
241 @SuppressWarnings("try")
242 @SuppressFBWarnings(value = "DM_EXIT", justification = "PrintFlags is meant to exit the VM")
243 private HotSpotJVMCIRuntime() {
244 compilerToVm = new CompilerToVM();
245
246 try (InitTimer t = timer("HotSpotVMConfig<init>")) {
247 configStore = new HotSpotVMConfigStore(compilerToVm);
248 config = new HotSpotVMConfig(configStore);
249 }
250
251 String hostArchitecture = config.getHostArchitectureName();
252
253 HotSpotJVMCIBackendFactory factory;
254 try (InitTimer t = timer("find factory:", hostArchitecture)) {
255 factory = findFactory(hostArchitecture);
256 }
257
258 try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
259 hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
260 }
261
262 metaAccessContext = new HotSpotJVMCIMetaAccessContext();
263
264 boolean printFlags = Option.PrintFlags.getBoolean();
265 boolean showFlags = Option.ShowFlags.getBoolean();
266 if (printFlags || showFlags) {
267 Option.printFlags(System.out);
268 if (printFlags) {
269 System.exit(0);
270 }
271 }
272
273 if (Option.PrintConfig.getBoolean()) {
274 printConfig(configStore, compilerToVm);
275 System.exit(0);
276 }
277
278 compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
279 if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
280 hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
281 trivialPrefixes = hsCompilerFactory.getTrivialPrefixes();
282 switch (hsCompilerFactory.getCompilationLevelAdjustment()) {
283 case None:
284 compilationLevelAdjustment = config.compLevelAdjustmentNone;
285 break;
286 case ByHolder:
287 compilationLevelAdjustment = config.compLevelAdjustmentByHolder;
288 break;
289 case ByFullSignature:
290 compilationLevelAdjustment = config.compLevelAdjustmentByFullSignature;
291 break;
292 default:
293 compilationLevelAdjustment = config.compLevelAdjustmentNone;
294 break;
295 }
446 @SuppressWarnings({"unused"})
447 private void bootstrapFinished() throws Exception {
448 for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
449 vmEventListener.notifyBootstrapFinished();
450 }
451 }
452
453 /**
454 * Notify on successful install into the CodeCache.
455 *
456 * @param hotSpotCodeCacheProvider
457 * @param installedCode
458 * @param compiledCode
459 */
460 void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
461 for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
462 vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compiledCode);
463 }
464 }
465
466 @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
467 private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
468 String line = String.format(format, args);
469 byte[] lineBytes = line.getBytes();
470 vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
471 vm.flushDebugOutput();
472 }
473
474 private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
475 TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
476 for (VMField field : fields.values()) {
477 if (!field.isStatic()) {
478 printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
479 } else {
480 String value = field.value == null ? "null" : String.format("%d[0x%x]", field.value, field.value);
481 printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
482 }
483 }
484 TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
485 for (VMFlag flag : flags.values()) {
486 printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
487 }
488 TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
489 for (Map.Entry<String, Long> e : addresses.entrySet()) {
490 printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
491 }
492 TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
493 for (Map.Entry<String, Long> e : constants.entrySet()) {
494 printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
495 }
496 TreeMap<String, Long> typeSizes = new TreeMap<>(store.getTypeSizes());
497 for (Map.Entry<String, Long> e : typeSizes.entrySet()) {
498 printConfigLine(vm, "[vmconfig:type size] %s = %d%n", e.getKey(), e.getValue());
499 }
500 }
501
502 public OutputStream getLogStream() {
503 return new OutputStream() {
504
505 @Override
506 public void write(byte[] b, int off, int len) throws IOException {
507 if (b == null) {
508 throw new NullPointerException();
509 } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length || (off + len) < 0) {
510 throw new IndexOutOfBoundsException();
511 } else if (len == 0) {
512 return;
513 }
514 compilerToVm.writeDebugOutput(b, off, len);
515 }
516
517 @Override
518 public void write(int b) throws IOException {
519 write(new byte[]{(byte) b}, 0, 1);
|