< 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 /*
   2  * Copyright (c) 2015, 2019, 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.vm.ci.hotspot;
  24 
  25 import static jdk.vm.ci.common.InitTimer.timer;
  26 import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None;
  27 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
  28 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
  29 
  30 import java.io.IOException;
  31 import java.io.OutputStream;
  32 import java.io.PrintStream;
  33 import java.io.Serializable;
  34 import java.lang.invoke.CallSite;
  35 import java.lang.invoke.ConstantCallSite;
  36 import java.lang.invoke.MethodHandle;
  37 import java.lang.ref.WeakReference;
  38 import java.util.ArrayList;
  39 import java.util.Collections;

  40 import java.util.HashMap;
  41 import java.util.List;
  42 import java.util.Map;
  43 import java.util.Objects;
  44 import java.util.ServiceLoader;
  45 import java.util.function.Predicate;
  46 
  47 import jdk.vm.ci.code.Architecture;
  48 import jdk.vm.ci.code.CompilationRequestResult;
  49 import jdk.vm.ci.code.CompiledCode;
  50 import jdk.vm.ci.code.InstalledCode;
  51 import jdk.vm.ci.common.InitTimer;
  52 import jdk.vm.ci.common.JVMCIError;
  53 import jdk.vm.ci.common.NativeImageReinitialize;
  54 import jdk.vm.ci.meta.JavaKind;
  55 import jdk.vm.ci.meta.JavaType;
  56 import jdk.vm.ci.meta.ResolvedJavaType;
  57 import jdk.vm.ci.meta.UnresolvedJavaType;
  58 import jdk.vm.ci.runtime.JVMCI;
  59 import jdk.vm.ci.runtime.JVMCIBackend;


 194         }
 195         return result;
 196     }
 197 
 198     @VMEntryPoint
 199     static Throwable decodeThrowable(String encodedThrowable) throws Throwable {
 200         return TranslatedException.decodeThrowable(encodedThrowable);
 201     }
 202 
 203     @VMEntryPoint
 204     static String encodeThrowable(Throwable throwable) throws Throwable {
 205         return TranslatedException.encodeThrowable(throwable);
 206     }
 207 
 208     @VMEntryPoint
 209     static String callToString(Object o) {
 210         return o.toString();
 211     }
 212 
 213     /**









 214      * A list of all supported JVMCI options.
 215      */
 216     public enum Option {
 217         // @formatter:off
 218         Compiler(String.class, null, "Selects the system compiler. This must match the getCompilerName() value returned " +
 219                 "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
 220                 "An empty string or the value \"null\" selects a compiler " +
 221                 "that will raise an exception upon receiving a compilation request."),
 222         // Note: The following one is not used (see InitTimer.ENABLED). It is added here
 223         // so that -XX:+JVMCIPrintProperties shows the option.
 224         InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
 225         PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
 226         AuditHandles(Boolean.class, false, "Record stack trace along with scoped foreign object reference wrappers " +
 227                 "to debug issue with a wrapper being used after its scope has closed."),
 228         TraceMethodDataFilter(String.class, null,
 229                 "Enables tracing of profiling info when read by JVMCI.",
 230                 "Empty value: trace all methods",
 231                 "Non-empty value: trace methods whose fully qualified name contains the value."),
 232         UseProfilingInformation(Boolean.class, true, "");
 233         // @formatter:on
 234 
 235         /**
 236          * The prefix for system properties that are JVMCI options.
 237          */
 238         private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
 239 
 240         /**
 241          * Sentinel for value initialized to {@code null} since {@code null} means uninitialized.
 242          */
 243         private static final String NULL_VALUE = "NULL";
 244 
 245         private final Class<?> type;
 246         @NativeImageReinitialize private Object value;
 247         private final Object defaultValue;
 248         private boolean isDefault;
 249         private final String[] helpLines;
 250 
 251         Option(Class<?> type, Object defaultValue, String... helpLines) {
 252             assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
 253             this.type = type;
 254             this.defaultValue = defaultValue;
 255             this.helpLines = helpLines;


 256         }
 257 
 258         @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
 259         private Object getValue() {
 260             if (value == null) {
 261                 String propertyValue = Services.getSavedProperty(getPropertyName());
 262                 if (propertyValue == null) {
 263                     this.value = defaultValue == null ? NULL_VALUE : defaultValue;
 264                     this.isDefault = true;
 265                 } else {
 266                     if (type == Boolean.class) {
 267                         this.value = Boolean.parseBoolean(propertyValue);
 268                     } else if (type == String.class) {
 269                         this.value = propertyValue;
 270                     } else {
 271                         throw new JVMCIError("Unexpected option type " + type);
 272                     }
 273                     this.isDefault = false;
 274                 }
 275             }
 276             return value == NULL_VALUE ? null : value;









 277         }
 278 
 279         /**
 280          * Gets the name of system property from which this option gets its value.
 281          */
 282         public String getPropertyName() {
 283             return JVMCI_OPTION_PROPERTY_PREFIX + name();
 284         }
 285 
 286         /**
 287          * Returns the option's value as boolean.
 288          *
 289          * @return option's value
 290          */
 291         public boolean getBoolean() {
 292             return (boolean) getValue();
 293         }
 294 
 295         /**
 296          * Returns the option's value as String.


 317                 if (value instanceof String) {
 318                     value = '"' + String.valueOf(value) + '"';
 319                 }
 320 
 321                 String name = option.getPropertyName();
 322                 String assign = option.isDefault ? "=" : ":=";
 323                 String typeName = option.type.getSimpleName();
 324                 String linePrefix = String.format("%s %s %s ", name, assign, value);
 325                 int typeStartPos = PROPERTY_LINE_WIDTH - typeName.length();
 326                 int linePad = typeStartPos - linePrefix.length();
 327                 if (linePad > 0) {
 328                     out.printf("%s%-" + linePad + "s[%s]%n", linePrefix, "", typeName);
 329                 } else {
 330                     out.printf("%s[%s]%n", linePrefix, typeName);
 331                 }
 332                 for (String line : option.helpLines) {
 333                     out.printf("%" + PROPERTY_HELP_INDENT + "s%s%n", "", line);
 334                 }
 335             }
 336         }























































 337     }
 338 
 339     private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
 340         Iterable<HotSpotJVMCIBackendFactory> factories = getHotSpotJVMCIBackendFactories();
 341         assert factories != null : "sanity";
 342         for (HotSpotJVMCIBackendFactory factory : factories) {
 343             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
 344                 return factory;
 345             }
 346         }
 347 
 348         throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
 349     }
 350 
 351     private static volatile List<HotSpotJVMCIBackendFactory> cachedHotSpotJVMCIBackendFactories;
 352 
 353     @SuppressFBWarnings(value = "LI_LAZY_INIT_UPDATE_STATIC", justification = "not sure about this")
 354     private static Iterable<HotSpotJVMCIBackendFactory> getHotSpotJVMCIBackendFactories() {
 355         if (IS_IN_NATIVE_IMAGE || cachedHotSpotJVMCIBackendFactories != null) {
 356             return cachedHotSpotJVMCIBackendFactories;


 437 
 438     @SuppressWarnings("try")
 439     private HotSpotJVMCIRuntime() {
 440         compilerToVm = new CompilerToVM();
 441 
 442         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
 443             configStore = new HotSpotVMConfigStore(compilerToVm);
 444             config = new HotSpotVMConfig(configStore);
 445         }
 446 
 447         reflection = IS_IN_NATIVE_IMAGE ? new SharedLibraryJVMCIReflection() : new HotSpotJDKReflection();
 448 
 449         PrintStream vmLogStream = null;
 450         if (IS_IN_NATIVE_IMAGE) {
 451             // Redirect System.out and System.err to HotSpot's TTY stream
 452             vmLogStream = new PrintStream(getLogStream());
 453             System.setOut(vmLogStream);
 454             System.setErr(vmLogStream);
 455         }
 456 



 457         String hostArchitecture = config.getHostArchitectureName();
 458 
 459         HotSpotJVMCIBackendFactory factory;
 460         try (InitTimer t = timer("find factory:", hostArchitecture)) {
 461             factory = findFactory(hostArchitecture);
 462         }
 463 
 464         try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
 465             hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
 466         }
 467 
 468         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
 469         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
 470             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
 471             if (hsCompilerFactory.getCompilationLevelAdjustment() != None) {
 472                 String name = HotSpotJVMCICompilerFactory.class.getName();
 473                 String msg = String.format("%s.getCompilationLevelAdjustment() is no longer supported. " +
 474                                 "Use %s.excludeFromJVMCICompilation() instead.", name, name);
 475                 throw new UnsupportedOperationException(msg);
 476             }


 696         HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, compileState, id);
 697         CompilationRequestResult result = getCompiler().compileMethod(request);
 698         assert result != null : "compileMethod must always return something";
 699         HotSpotCompilationRequestResult hsResult;
 700         if (result instanceof HotSpotCompilationRequestResult) {
 701             hsResult = (HotSpotCompilationRequestResult) result;
 702         } else {
 703             Object failure = result.getFailure();
 704             if (failure != null) {
 705                 boolean retry = false; // Be conservative with unknown compiler
 706                 hsResult = HotSpotCompilationRequestResult.failure(failure.toString(), retry);
 707             } else {
 708                 int inlinedBytecodes = -1;
 709                 hsResult = HotSpotCompilationRequestResult.success(inlinedBytecodes);
 710             }
 711         }
 712         return hsResult;
 713     }
 714 
 715     /**





 716      * Shuts down the runtime.
 717      */
 718     @VMEntryPoint
 719     private void shutdown() throws Exception {


 720         // Cleaners are normally only processed when a new Cleaner is
 721         // instantiated so process all remaining cleaners now.
 722         Cleaner.clean();
 723 
 724         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
 725             vmEventListener.notifyShutdown();
 726         }
 727     }

 728 
 729     /**
 730      * Notify on completion of a bootstrap.
 731      */
 732     @VMEntryPoint
 733     private void bootstrapFinished() throws Exception {
 734         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
 735             vmEventListener.notifyBootstrapFinished();
 736         }
 737     }
 738 
 739     /**
 740      * Notify on successful install into the CodeCache.
 741      *
 742      * @param hotSpotCodeCacheProvider
 743      * @param installedCode
 744      * @param compiledCode
 745      */
 746     void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
 747         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {


 898      * import java.lang.reflect.Method;
 899      *
 900      * public static class JCompile {
 901      *     static {
 902      *         HotSpotJVMCIRuntime.runtime().registerNativeMethods(JCompile.class);
 903      *     }
 904      *     public static boolean compile(Method method, String[] options) {
 905      *         // Convert to simpler data types for passing/serializing across native interface
 906      *         long metaspaceMethodHandle = getHandle(method);
 907      *         char[] opts = convertToCharArray(options);
 908      *         return compile(metaspaceMethodHandle, opts);
 909      *     }
 910      *     private static native boolean compile0(long metaspaceMethodHandle, char[] options);
 911      *
 912      *     private static long getHandle(Method method) { ... }
 913      *     private static char[] convertToCharArray(String[] a) { ... }
 914      * }
 915      * </pre>
 916      *
 917      * The implementation of the native {@code JCompile.compile0} method would be in the JVMCI
 918      * shared library that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0}
 919      * implementation will be exported as the following JNI-compatible symbol:
 920      *
 921      * <pre>
 922      * Java_com_jcompile_JCompile_compile0
 923      * </pre>
 924      *
 925      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names"
 926      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#creating_the_vm"
 927      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
 928      *
 929      *
 930      * @return an array of 4 longs where the first value is the {@code JavaVM*} value representing
 931      *         the Java VM in the JVMCI shared library, and the remaining values are the first 3
 932      *         pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})









 933      * @throws NullPointerException if {@code clazz == null}
 934      * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
 935      *             {@code -XX:-UseJVMCINativeLibrary})
 936      * @throws IllegalStateException if the current execution context is the JVMCI shared library
 937      * @throws IllegalArgumentException if {@code clazz} is {@link Class#isPrimitive()}
 938      * @throws UnsatisfiedLinkError if there's a problem linking a native method in {@code clazz}
 939      *             (no matching JNI symbol or the native method is already linked to a different
 940      *             address)
 941      */
 942     public long[] registerNativeMethods(Class<?> clazz) {
 943         return compilerToVm.registerNativeMethods(clazz);
 944     }
 945 
 946     /**
 947      * Creates or retrieves an object in the peer runtime that mirrors {@code obj}. The types whose
 948      * objects can be translated are:
 949      * <ul>
 950      * <li>{@link HotSpotResolvedJavaMethodImpl},</li>
 951      * <li>{@link HotSpotResolvedObjectTypeImpl},</li>
 952      * <li>{@link HotSpotResolvedPrimitiveType},</li>


1001     }
1002 
1003     /**
1004      * Gets the address of the HotSpot {@code JavaThread} C++ object for the current thread. This
1005      * will return {@code 0} if called from an unattached JVMCI shared library thread.
1006      */
1007     public long getCurrentJavaThread() {
1008         return compilerToVm.getCurrentJavaThread();
1009     }
1010 
1011     /**
1012      * Ensures the current thread is attached to the peer runtime.
1013      *
1014      * @param asDaemon if the thread is not yet attached, should it be attached as a daemon
1015      * @return {@code true} if this call attached the current thread, {@code false} if the current
1016      *         thread was already attached
1017      * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
1018      *             {@code -XX:-UseJVMCINativeLibrary})
1019      * @throws IllegalStateException if the peer runtime has not been initialized or there is an
1020      *             error while trying to attach the thread


1021      */
1022     public boolean attachCurrentThread(boolean asDaemon) {
1023         return compilerToVm.attachCurrentThread(asDaemon);
1024     }
1025 
1026     /**
1027      * Detaches the current thread from the peer runtime.
1028      *
1029      * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
1030      *             {@code -XX:-UseJVMCINativeLibrary})
1031      * @throws IllegalStateException if the peer runtime has not been initialized or if the current
1032      *             thread is not attached or if there is an error while trying to detach the thread
1033      */
1034     public void detachCurrentThread() {
1035         compilerToVm.detachCurrentThread();
1036     }
1037 
1038     /**
1039      * Informs HotSpot that no method whose module is in {@code modules} is to be compiled
1040      * with {@link #compileMethod}.
   1 /*
   2  * Copyright (c) 2015, 2020, 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.vm.ci.hotspot;
  24 
  25 import static jdk.vm.ci.common.InitTimer.timer;
  26 import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None;
  27 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
  28 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
  29 
  30 import java.io.IOException;
  31 import java.io.OutputStream;
  32 import java.io.PrintStream;
  33 import java.io.Serializable;
  34 import java.lang.invoke.CallSite;
  35 import java.lang.invoke.ConstantCallSite;
  36 import java.lang.invoke.MethodHandle;
  37 import java.lang.ref.WeakReference;
  38 import java.util.ArrayList;
  39 import java.util.Collections;
  40 import java.util.Formatter;
  41 import java.util.HashMap;
  42 import java.util.List;
  43 import java.util.Map;
  44 import java.util.Objects;
  45 import java.util.ServiceLoader;
  46 import java.util.function.Predicate;
  47 
  48 import jdk.vm.ci.code.Architecture;
  49 import jdk.vm.ci.code.CompilationRequestResult;
  50 import jdk.vm.ci.code.CompiledCode;
  51 import jdk.vm.ci.code.InstalledCode;
  52 import jdk.vm.ci.common.InitTimer;
  53 import jdk.vm.ci.common.JVMCIError;
  54 import jdk.vm.ci.common.NativeImageReinitialize;
  55 import jdk.vm.ci.meta.JavaKind;
  56 import jdk.vm.ci.meta.JavaType;
  57 import jdk.vm.ci.meta.ResolvedJavaType;
  58 import jdk.vm.ci.meta.UnresolvedJavaType;
  59 import jdk.vm.ci.runtime.JVMCI;
  60 import jdk.vm.ci.runtime.JVMCIBackend;


 195         }
 196         return result;
 197     }
 198 
 199     @VMEntryPoint
 200     static Throwable decodeThrowable(String encodedThrowable) throws Throwable {
 201         return TranslatedException.decodeThrowable(encodedThrowable);
 202     }
 203 
 204     @VMEntryPoint
 205     static String encodeThrowable(Throwable throwable) throws Throwable {
 206         return TranslatedException.encodeThrowable(throwable);
 207     }
 208 
 209     @VMEntryPoint
 210     static String callToString(Object o) {
 211         return o.toString();
 212     }
 213 
 214     /**
 215      * Set of recognized {@code "jvmci.*"} system properties. Entries not associated with an
 216      * {@link Option} have this object as their value.
 217      */
 218     static final Map<String, Object> options = new HashMap<>();
 219     static {
 220         options.put("jvmci.class.path.append", options);
 221     }
 222 
 223     /**
 224      * A list of all supported JVMCI options.
 225      */
 226     public enum Option {
 227         // @formatter:off
 228         Compiler(String.class, null, "Selects the system compiler. This must match the getCompilerName() value returned " +
 229                 "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
 230                 "An empty string or the value \"null\" selects a compiler " +
 231                 "that will raise an exception upon receiving a compilation request."),
 232         // Note: The following one is not used (see InitTimer.ENABLED). It is added here
 233         // so that -XX:+JVMCIPrintProperties shows the option.
 234         InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
 235         PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
 236         AuditHandles(Boolean.class, false, "Record stack trace along with scoped foreign object reference wrappers " +
 237                 "to debug issue with a wrapper being used after its scope has closed."),
 238         TraceMethodDataFilter(String.class, null,
 239                 "Enables tracing of profiling info when read by JVMCI.",
 240                 "Empty value: trace all methods",
 241                         "Non-empty value: trace methods whose fully qualified name contains the value."),
 242         UseProfilingInformation(Boolean.class, true, "");
 243         // @formatter:on
 244 
 245         /**
 246          * The prefix for system properties that are JVMCI options.
 247          */
 248         private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
 249 
 250         /**
 251          * Sentinel for value initialized to {@code null} since {@code null} means uninitialized.
 252          */
 253         private static final String NULL_VALUE = "NULL";
 254 
 255         private final Class<?> type;
 256         @NativeImageReinitialize private Object value;
 257         private final Object defaultValue;
 258         private boolean isDefault = true;
 259         private final String[] helpLines;
 260 
 261         Option(Class<?> type, Object defaultValue, String... helpLines) {
 262             assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
 263             this.type = type;
 264             this.defaultValue = defaultValue;
 265             this.helpLines = helpLines;
 266             Object existing = options.put(getPropertyName(), this);
 267             assert existing == null : getPropertyName();
 268         }
 269 
 270         @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
 271         private void init(String propertyValue) {
 272             assert value == null : "cannot re-initialize " + name();

 273             if (propertyValue == null) {
 274                 this.value = defaultValue == null ? NULL_VALUE : defaultValue;
 275                 this.isDefault = true;
 276             } else {
 277                 if (type == Boolean.class) {
 278                     this.value = Boolean.parseBoolean(propertyValue);
 279                 } else if (type == String.class) {
 280                     this.value = propertyValue;
 281                 } else {
 282                     throw new JVMCIError("Unexpected option type " + type);
 283                 }
 284                 this.isDefault = false;
 285             }
 286         }
 287 
 288         @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
 289         private Object getValue() {
 290             if (value == NULL_VALUE) {
 291                 return null;
 292             }
 293             if (value == null) {
 294                 return defaultValue;
 295             }
 296             return value;
 297         }
 298 
 299         /**
 300          * Gets the name of system property from which this option gets its value.
 301          */
 302         public String getPropertyName() {
 303             return JVMCI_OPTION_PROPERTY_PREFIX + name();
 304         }
 305 
 306         /**
 307          * Returns the option's value as boolean.
 308          *
 309          * @return option's value
 310          */
 311         public boolean getBoolean() {
 312             return (boolean) getValue();
 313         }
 314 
 315         /**
 316          * Returns the option's value as String.


 337                 if (value instanceof String) {
 338                     value = '"' + String.valueOf(value) + '"';
 339                 }
 340 
 341                 String name = option.getPropertyName();
 342                 String assign = option.isDefault ? "=" : ":=";
 343                 String typeName = option.type.getSimpleName();
 344                 String linePrefix = String.format("%s %s %s ", name, assign, value);
 345                 int typeStartPos = PROPERTY_LINE_WIDTH - typeName.length();
 346                 int linePad = typeStartPos - linePrefix.length();
 347                 if (linePad > 0) {
 348                     out.printf("%s%-" + linePad + "s[%s]%n", linePrefix, "", typeName);
 349                 } else {
 350                     out.printf("%s[%s]%n", linePrefix, typeName);
 351                 }
 352                 for (String line : option.helpLines) {
 353                     out.printf("%" + PROPERTY_HELP_INDENT + "s%s%n", "", line);
 354                 }
 355             }
 356         }
 357 
 358         /**
 359          * Compute string similarity based on Dice's coefficient.
 360          *
 361          * Ported from str_similar() in globals.cpp.
 362          */
 363         static float stringSimiliarity(String str1, String str2) {
 364             int hit = 0;
 365             for (int i = 0; i < str1.length() - 1; ++i) {
 366                 for (int j = 0; j < str2.length() - 1; ++j) {
 367                     if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) {
 368                         ++hit;
 369                         break;
 370                     }
 371                 }
 372             }
 373             return 2.0f * hit / (str1.length() + str2.length());
 374         }
 375 
 376         private static final float FUZZY_MATCH_THRESHOLD = 0.7F;
 377 
 378         /**
 379          * Parses all system properties starting with {@value #JVMCI_OPTION_PROPERTY_PREFIX} and
 380          * initializes the options based on their values.
 381          */
 382         static void parse() {
 383             Map<String, String> savedProps = jdk.vm.ci.services.Services.getSavedProperties();
 384             for (Map.Entry<String, String> e : savedProps.entrySet()) {
 385                 String name = e.getKey();
 386                 if (name.startsWith(Option.JVMCI_OPTION_PROPERTY_PREFIX)) {
 387                     Object value = options.get(name);
 388                     if (value == null) {
 389                         List<String> matches = new ArrayList<>();
 390                         for (String pn : options.keySet()) {
 391                             float score = stringSimiliarity(pn, name);
 392                             if (score >= FUZZY_MATCH_THRESHOLD) {
 393                                 matches.add(pn);
 394                             }
 395                         }
 396                         Formatter msg = new Formatter();
 397                         msg.format("Could not find option %s", name);
 398                         if (!matches.isEmpty()) {
 399                             msg.format("%nDid you mean one of the following?");
 400                             for (String match : matches) {
 401                                 msg.format("%n    %s=<value>", match);
 402                             }
 403                         }
 404                         throw new IllegalArgumentException(msg.toString());
 405                     } else if (value instanceof Option) {
 406                         Option option = (Option) value;
 407                         option.init(e.getValue());
 408                     }
 409                 }
 410             }
 411         }
 412     }
 413 
 414     private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
 415         Iterable<HotSpotJVMCIBackendFactory> factories = getHotSpotJVMCIBackendFactories();
 416         assert factories != null : "sanity";
 417         for (HotSpotJVMCIBackendFactory factory : factories) {
 418             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
 419                 return factory;
 420             }
 421         }
 422 
 423         throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
 424     }
 425 
 426     private static volatile List<HotSpotJVMCIBackendFactory> cachedHotSpotJVMCIBackendFactories;
 427 
 428     @SuppressFBWarnings(value = "LI_LAZY_INIT_UPDATE_STATIC", justification = "not sure about this")
 429     private static Iterable<HotSpotJVMCIBackendFactory> getHotSpotJVMCIBackendFactories() {
 430         if (IS_IN_NATIVE_IMAGE || cachedHotSpotJVMCIBackendFactories != null) {
 431             return cachedHotSpotJVMCIBackendFactories;


 512 
 513     @SuppressWarnings("try")
 514     private HotSpotJVMCIRuntime() {
 515         compilerToVm = new CompilerToVM();
 516 
 517         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
 518             configStore = new HotSpotVMConfigStore(compilerToVm);
 519             config = new HotSpotVMConfig(configStore);
 520         }
 521 
 522         reflection = IS_IN_NATIVE_IMAGE ? new SharedLibraryJVMCIReflection() : new HotSpotJDKReflection();
 523 
 524         PrintStream vmLogStream = null;
 525         if (IS_IN_NATIVE_IMAGE) {
 526             // Redirect System.out and System.err to HotSpot's TTY stream
 527             vmLogStream = new PrintStream(getLogStream());
 528             System.setOut(vmLogStream);
 529             System.setErr(vmLogStream);
 530         }
 531 
 532         // Initialize the Option values.
 533         Option.parse();
 534 
 535         String hostArchitecture = config.getHostArchitectureName();
 536 
 537         HotSpotJVMCIBackendFactory factory;
 538         try (InitTimer t = timer("find factory:", hostArchitecture)) {
 539             factory = findFactory(hostArchitecture);
 540         }
 541 
 542         try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
 543             hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
 544         }
 545 
 546         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
 547         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
 548             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
 549             if (hsCompilerFactory.getCompilationLevelAdjustment() != None) {
 550                 String name = HotSpotJVMCICompilerFactory.class.getName();
 551                 String msg = String.format("%s.getCompilationLevelAdjustment() is no longer supported. " +
 552                                 "Use %s.excludeFromJVMCICompilation() instead.", name, name);
 553                 throw new UnsupportedOperationException(msg);
 554             }


 774         HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, compileState, id);
 775         CompilationRequestResult result = getCompiler().compileMethod(request);
 776         assert result != null : "compileMethod must always return something";
 777         HotSpotCompilationRequestResult hsResult;
 778         if (result instanceof HotSpotCompilationRequestResult) {
 779             hsResult = (HotSpotCompilationRequestResult) result;
 780         } else {
 781             Object failure = result.getFailure();
 782             if (failure != null) {
 783                 boolean retry = false; // Be conservative with unknown compiler
 784                 hsResult = HotSpotCompilationRequestResult.failure(failure.toString(), retry);
 785             } else {
 786                 int inlinedBytecodes = -1;
 787                 hsResult = HotSpotCompilationRequestResult.success(inlinedBytecodes);
 788             }
 789         }
 790         return hsResult;
 791     }
 792 
 793     /**
 794      * Guard to ensure shut down actions are performed at most once.
 795      */
 796     private boolean isShutdown;
 797 
 798     /**
 799      * Shuts down the runtime.
 800      */
 801     @VMEntryPoint
 802     private synchronized void shutdown() throws Exception {
 803         if (!isShutdown) {
 804             isShutdown = true;
 805             // Cleaners are normally only processed when a new Cleaner is
 806             // instantiated so process all remaining cleaners now.
 807             Cleaner.clean();
 808 
 809             for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
 810                 vmEventListener.notifyShutdown();
 811             }
 812         }
 813     }
 814 
 815     /**
 816      * Notify on completion of a bootstrap.
 817      */
 818     @VMEntryPoint
 819     private void bootstrapFinished() throws Exception {
 820         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
 821             vmEventListener.notifyBootstrapFinished();
 822         }
 823     }
 824 
 825     /**
 826      * Notify on successful install into the CodeCache.
 827      *
 828      * @param hotSpotCodeCacheProvider
 829      * @param installedCode
 830      * @param compiledCode
 831      */
 832     void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
 833         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {


 984      * import java.lang.reflect.Method;
 985      *
 986      * public static class JCompile {
 987      *     static {
 988      *         HotSpotJVMCIRuntime.runtime().registerNativeMethods(JCompile.class);
 989      *     }
 990      *     public static boolean compile(Method method, String[] options) {
 991      *         // Convert to simpler data types for passing/serializing across native interface
 992      *         long metaspaceMethodHandle = getHandle(method);
 993      *         char[] opts = convertToCharArray(options);
 994      *         return compile(metaspaceMethodHandle, opts);
 995      *     }
 996      *     private static native boolean compile0(long metaspaceMethodHandle, char[] options);
 997      *
 998      *     private static long getHandle(Method method) { ... }
 999      *     private static char[] convertToCharArray(String[] a) { ... }
1000      * }
1001      * </pre>
1002      *
1003      * The implementation of the native {@code JCompile.compile0} method would be in the JVMCI
1004      * shared library that contains the JVMCI compiler. The {@code JCompile.compile0} implementation
1005      * must be exported as the following JNI-compatible symbol:
1006      *
1007      * <pre>
1008      * Java_com_jcompile_JCompile_compile0
1009      * </pre>
1010      *
1011      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names"
1012      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#creating_the_vm"
1013      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
1014      *
1015      *
1016      * @return info about the Java VM in the JVMCI shared library {@code JavaVM*}. The info is
1017      *         encoded in a long array as follows:
1018      *
1019      *         <pre>
1020      *     long[] info = {
1021      *         javaVM, // the {@code JavaVM*} value
1022      *         javaVM->functions->reserved0,
1023      *         javaVM->functions->reserved1,
1024      *         javaVM->functions->reserved2
1025      *     }
1026      *         </pre>
1027      *
1028      * @throws NullPointerException if {@code clazz == null}
1029      * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
1030      *             {@code -XX:-UseJVMCINativeLibrary})
1031      * @throws IllegalStateException if the current execution context is the JVMCI shared library
1032      * @throws IllegalArgumentException if {@code clazz} is {@link Class#isPrimitive()}
1033      * @throws UnsatisfiedLinkError if there's a problem linking a native method in {@code clazz}
1034      *             (no matching JNI symbol or the native method is already linked to a different
1035      *             address)
1036      */
1037     public long[] registerNativeMethods(Class<?> clazz) {
1038         return compilerToVm.registerNativeMethods(clazz);
1039     }
1040 
1041     /**
1042      * Creates or retrieves an object in the peer runtime that mirrors {@code obj}. The types whose
1043      * objects can be translated are:
1044      * <ul>
1045      * <li>{@link HotSpotResolvedJavaMethodImpl},</li>
1046      * <li>{@link HotSpotResolvedObjectTypeImpl},</li>
1047      * <li>{@link HotSpotResolvedPrimitiveType},</li>


1096     }
1097 
1098     /**
1099      * Gets the address of the HotSpot {@code JavaThread} C++ object for the current thread. This
1100      * will return {@code 0} if called from an unattached JVMCI shared library thread.
1101      */
1102     public long getCurrentJavaThread() {
1103         return compilerToVm.getCurrentJavaThread();
1104     }
1105 
1106     /**
1107      * Ensures the current thread is attached to the peer runtime.
1108      *
1109      * @param asDaemon if the thread is not yet attached, should it be attached as a daemon
1110      * @return {@code true} if this call attached the current thread, {@code false} if the current
1111      *         thread was already attached
1112      * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
1113      *             {@code -XX:-UseJVMCINativeLibrary})
1114      * @throws IllegalStateException if the peer runtime has not been initialized or there is an
1115      *             error while trying to attach the thread
1116      * @throws ArrayIndexOutOfBoundsException if {@code javaVMInfo} is non-null and is shorter than
1117      *             the length of the array returned by {@link #registerNativeMethods}
1118      */
1119     public boolean attachCurrentThread(boolean asDaemon) {
1120         return compilerToVm.attachCurrentThread(asDaemon);
1121     }
1122 
1123     /**
1124      * Detaches the current thread from the peer runtime.
1125      *
1126      * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
1127      *             {@code -XX:-UseJVMCINativeLibrary})
1128      * @throws IllegalStateException if the peer runtime has not been initialized or if the current
1129      *             thread is not attached or if there is an error while trying to detach the thread
1130      */
1131     public void detachCurrentThread() {
1132         compilerToVm.detachCurrentThread();
1133     }
1134 
1135     /**
1136      * Informs HotSpot that no method whose module is in {@code modules} is to be compiled
1137      * with {@link #compileMethod}.
< prev index next >