< 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 >