< prev index next >
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
--- 1,7 ----
/*
! * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*** 35,44 ****
--- 35,45 ----
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
+ import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.ServiceLoader;
*** 209,218 ****
--- 210,228 ----
static String callToString(Object o) {
return o.toString();
}
/**
+ * Set of recognized {@code "jvmci.*"} system properties. Entries not associated with an
+ * {@link Option} have this object as their value.
+ */
+ static final Map<String, Object> options = new HashMap<>();
+ static {
+ options.put("jvmci.class.path.append", options);
+ }
+
+ /**
* A list of all supported JVMCI options.
*/
public enum Option {
// @formatter:off
Compiler(String.class, null, "Selects the system compiler. This must match the getCompilerName() value returned " +
*** 243,266 ****
private static final String NULL_VALUE = "NULL";
private final Class<?> type;
@NativeImageReinitialize private Object value;
private final Object defaultValue;
! private boolean isDefault;
private final String[] helpLines;
Option(Class<?> type, Object defaultValue, String... helpLines) {
assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
this.type = type;
this.defaultValue = defaultValue;
this.helpLines = helpLines;
}
@SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
! private Object getValue() {
! if (value == null) {
! String propertyValue = Services.getSavedProperty(getPropertyName());
if (propertyValue == null) {
this.value = defaultValue == null ? NULL_VALUE : defaultValue;
this.isDefault = true;
} else {
if (type == Boolean.class) {
--- 253,277 ----
private static final String NULL_VALUE = "NULL";
private final Class<?> type;
@NativeImageReinitialize private Object value;
private final Object defaultValue;
! private boolean isDefault = true;
private final String[] helpLines;
Option(Class<?> type, Object defaultValue, String... helpLines) {
assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
this.type = type;
this.defaultValue = defaultValue;
this.helpLines = helpLines;
+ Object existing = options.put(getPropertyName(), this);
+ assert existing == null : getPropertyName();
}
@SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
! private void init(String propertyValue) {
! assert value == null : "cannot re-initialize " + name();
if (propertyValue == null) {
this.value = defaultValue == null ? NULL_VALUE : defaultValue;
this.isDefault = true;
} else {
if (type == Boolean.class) {
*** 271,281 ****
throw new JVMCIError("Unexpected option type " + type);
}
this.isDefault = false;
}
}
! return value == NULL_VALUE ? null : value;
}
/**
* Gets the name of system property from which this option gets its value.
*/
--- 282,301 ----
throw new JVMCIError("Unexpected option type " + type);
}
this.isDefault = false;
}
}
!
! @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
! private Object getValue() {
! if (value == NULL_VALUE) {
! return null;
! }
! if (value == null) {
! return defaultValue;
! }
! return value;
}
/**
* Gets the name of system property from which this option gets its value.
*/
*** 332,341 ****
--- 352,416 ----
for (String line : option.helpLines) {
out.printf("%" + PROPERTY_HELP_INDENT + "s%s%n", "", line);
}
}
}
+
+ /**
+ * Compute string similarity based on Dice's coefficient.
+ *
+ * Ported from str_similar() in globals.cpp.
+ */
+ static float stringSimiliarity(String str1, String str2) {
+ int hit = 0;
+ for (int i = 0; i < str1.length() - 1; ++i) {
+ for (int j = 0; j < str2.length() - 1; ++j) {
+ if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) {
+ ++hit;
+ break;
+ }
+ }
+ }
+ return 2.0f * hit / (str1.length() + str2.length());
+ }
+
+ private static final float FUZZY_MATCH_THRESHOLD = 0.7F;
+
+ /**
+ * Parses all system properties starting with {@value #JVMCI_OPTION_PROPERTY_PREFIX} and
+ * initializes the options based on their values.
+ */
+ static void parse() {
+ Map<String, String> savedProps = jdk.vm.ci.services.Services.getSavedProperties();
+ for (Map.Entry<String, String> e : savedProps.entrySet()) {
+ String name = e.getKey();
+ if (name.startsWith(Option.JVMCI_OPTION_PROPERTY_PREFIX)) {
+ Object value = options.get(name);
+ if (value == null) {
+ List<String> matches = new ArrayList<>();
+ for (String pn : options.keySet()) {
+ float score = stringSimiliarity(pn, name);
+ if (score >= FUZZY_MATCH_THRESHOLD) {
+ matches.add(pn);
+ }
+ }
+ Formatter msg = new Formatter();
+ msg.format("Could not find option %s", name);
+ if (!matches.isEmpty()) {
+ msg.format("%nDid you mean one of the following?");
+ for (String match : matches) {
+ msg.format("%n %s=<value>", match);
+ }
+ }
+ throw new IllegalArgumentException(msg.toString());
+ } else if (value instanceof Option) {
+ Option option = (Option) value;
+ option.init(e.getValue());
+ }
+ }
+ }
+ }
}
private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
Iterable<HotSpotJVMCIBackendFactory> factories = getHotSpotJVMCIBackendFactories();
assert factories != null : "sanity";
*** 452,461 ****
--- 527,539 ----
vmLogStream = new PrintStream(getLogStream());
System.setOut(vmLogStream);
System.setErr(vmLogStream);
}
+ // Initialize the Option values.
+ Option.parse();
+
String hostArchitecture = config.getHostArchitectureName();
HotSpotJVMCIBackendFactory factory;
try (InitTimer t = timer("find factory:", hostArchitecture)) {
factory = findFactory(hostArchitecture);
*** 711,732 ****
}
return hsResult;
}
/**
* Shuts down the runtime.
*/
@VMEntryPoint
! private void shutdown() throws Exception {
// Cleaners are normally only processed when a new Cleaner is
// instantiated so process all remaining cleaners now.
Cleaner.clean();
for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
vmEventListener.notifyShutdown();
}
}
/**
* Notify on completion of a bootstrap.
*/
@VMEntryPoint
--- 789,818 ----
}
return hsResult;
}
/**
+ * Guard to ensure shut down actions are performed at most once.
+ */
+ private boolean isShutdown;
+
+ /**
* Shuts down the runtime.
*/
@VMEntryPoint
! private synchronized void shutdown() throws Exception {
! if (!isShutdown) {
! isShutdown = true;
// Cleaners are normally only processed when a new Cleaner is
// instantiated so process all remaining cleaners now.
Cleaner.clean();
for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
vmEventListener.notifyShutdown();
}
}
+ }
/**
* Notify on completion of a bootstrap.
*/
@VMEntryPoint
*** 913,937 ****
* private static char[] convertToCharArray(String[] a) { ... }
* }
* </pre>
*
* The implementation of the native {@code JCompile.compile0} method would be in the JVMCI
! * shared library that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0}
! * implementation will be exported as the following JNI-compatible symbol:
*
* <pre>
* Java_com_jcompile_JCompile_compile0
* </pre>
*
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names"
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#creating_the_vm"
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
*
*
! * @return an array of 4 longs where the first value is the {@code JavaVM*} value representing
! * the Java VM in the JVMCI shared library, and the remaining values are the first 3
! * pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
* @throws NullPointerException if {@code clazz == null}
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
* {@code -XX:-UseJVMCINativeLibrary})
* @throws IllegalStateException if the current execution context is the JVMCI shared library
* @throws IllegalArgumentException if {@code clazz} is {@link Class#isPrimitive()}
--- 999,1032 ----
* private static char[] convertToCharArray(String[] a) { ... }
* }
* </pre>
*
* The implementation of the native {@code JCompile.compile0} method would be in the JVMCI
! * shared library that contains the JVMCI compiler. The {@code JCompile.compile0} implementation
! * must be exported as the following JNI-compatible symbol:
*
* <pre>
* Java_com_jcompile_JCompile_compile0
* </pre>
*
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names"
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#creating_the_vm"
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
*
*
! * @return info about the Java VM in the JVMCI shared library {@code JavaVM*}. The info is
! * encoded in a long array as follows:
! *
! * <pre>
! * long[] info = {
! * javaVM, // the {@code JavaVM*} value
! * javaVM->functions->reserved0,
! * javaVM->functions->reserved1,
! * javaVM->functions->reserved2
! * }
! * </pre>
! *
* @throws NullPointerException if {@code clazz == null}
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
* {@code -XX:-UseJVMCINativeLibrary})
* @throws IllegalStateException if the current execution context is the JVMCI shared library
* @throws IllegalArgumentException if {@code clazz} is {@link Class#isPrimitive()}
*** 1016,1025 ****
--- 1111,1122 ----
* thread was already attached
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
* {@code -XX:-UseJVMCINativeLibrary})
* @throws IllegalStateException if the peer runtime has not been initialized or there is an
* error while trying to attach the thread
+ * @throws ArrayIndexOutOfBoundsException if {@code javaVMInfo} is non-null and is shorter than
+ * the length of the array returned by {@link #registerNativeMethods}
*/
public boolean attachCurrentThread(boolean asDaemon) {
return compilerToVm.attachCurrentThread(asDaemon);
}
< prev index next >