src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
changeset 54669 ad45b3802d4e
parent 54647 c0d9bc9b4e1f
child 54732 2d012a75d35c
equal deleted inserted replaced
54668:0bda2308eded 54669:ad45b3802d4e
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 package jdk.vm.ci.hotspot;
    23 package jdk.vm.ci.hotspot;
    24 
    24 
    25 import static jdk.vm.ci.common.InitTimer.timer;
    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;
    26 
    29 
    27 import java.io.IOException;
    30 import java.io.IOException;
    28 import java.io.OutputStream;
    31 import java.io.OutputStream;
    29 import java.io.PrintStream;
    32 import java.io.PrintStream;
       
    33 import java.io.Serializable;
       
    34 
       
    35 import java.lang.invoke.CallSite;
       
    36 import java.lang.invoke.ConstantCallSite;
       
    37 import java.lang.invoke.MethodHandle;
    30 import java.lang.module.ModuleDescriptor.Requires;
    38 import java.lang.module.ModuleDescriptor.Requires;
       
    39 import java.lang.ref.WeakReference;
       
    40 
       
    41 import java.util.ArrayList;
    31 import java.util.Collections;
    42 import java.util.Collections;
    32 import java.util.HashMap;
    43 import java.util.HashMap;
    33 import java.util.HashSet;
    44 import java.util.HashSet;
    34 import java.util.List;
    45 import java.util.List;
    35 import java.util.Map;
    46 import java.util.Map;
    36 import java.util.Objects;
    47 import java.util.Objects;
    37 import java.util.ServiceLoader;
    48 import java.util.ServiceLoader;
    38 import java.util.Set;
    49 import java.util.TreeMap;
    39 import java.util.function.Predicate;
    50 import java.util.function.Predicate;
    40 
    51 
    41 import jdk.internal.misc.VM;
       
    42 import jdk.internal.misc.Unsafe;
    52 import jdk.internal.misc.Unsafe;
       
    53 
    43 import jdk.vm.ci.code.Architecture;
    54 import jdk.vm.ci.code.Architecture;
    44 import jdk.vm.ci.code.CompilationRequestResult;
    55 import jdk.vm.ci.code.CompilationRequestResult;
    45 import jdk.vm.ci.code.CompiledCode;
    56 import jdk.vm.ci.code.CompiledCode;
    46 import jdk.vm.ci.code.InstalledCode;
    57 import jdk.vm.ci.code.InstalledCode;
    47 import jdk.vm.ci.common.InitTimer;
    58 import jdk.vm.ci.common.InitTimer;
    55 import jdk.vm.ci.runtime.JVMCIBackend;
    66 import jdk.vm.ci.runtime.JVMCIBackend;
    56 import jdk.vm.ci.runtime.JVMCICompiler;
    67 import jdk.vm.ci.runtime.JVMCICompiler;
    57 import jdk.vm.ci.runtime.JVMCICompilerFactory;
    68 import jdk.vm.ci.runtime.JVMCICompilerFactory;
    58 import jdk.vm.ci.runtime.JVMCIRuntime;
    69 import jdk.vm.ci.runtime.JVMCIRuntime;
    59 import jdk.vm.ci.services.JVMCIServiceLocator;
    70 import jdk.vm.ci.services.JVMCIServiceLocator;
    60 
    71 import jdk.vm.ci.services.Services;
    61 import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None;
       
    62 
    72 
    63 /**
    73 /**
    64  * HotSpot implementation of a JVMCI runtime.
    74  * HotSpot implementation of a JVMCI runtime.
    65  *
       
    66  * The initialization of this class is very fragile since it's initialized both through
       
    67  * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and
       
    68  * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class
       
    69  * can't have a static initializer and any required initialization must be done as part of
       
    70  * {@link #runtime()}. This allows the initialization to funnel back through
       
    71  * {@link JVMCI#initialize()} without deadlocking.
       
    72  */
    75  */
    73 public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
    76 public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
    74 
    77 
       
    78     /**
       
    79      * Singleton instance lazily initialized via double-checked locking.
       
    80      */
       
    81     @NativeImageReinitialize private static volatile HotSpotJVMCIRuntime instance;
       
    82 
       
    83     private HotSpotResolvedObjectTypeImpl javaLangObject;
       
    84     private HotSpotResolvedObjectTypeImpl javaLangInvokeMethodHandle;
       
    85     private HotSpotResolvedObjectTypeImpl constantCallSiteType;
       
    86     private HotSpotResolvedObjectTypeImpl callSiteType;
       
    87     private HotSpotResolvedObjectTypeImpl javaLangString;
       
    88     private HotSpotResolvedObjectTypeImpl javaLangClass;
       
    89     private HotSpotResolvedObjectTypeImpl throwableType;
       
    90     private HotSpotResolvedObjectTypeImpl serializableType;
       
    91     private HotSpotResolvedObjectTypeImpl cloneableType;
       
    92     private HotSpotResolvedObjectTypeImpl enumType;
       
    93 
       
    94     HotSpotResolvedObjectTypeImpl getJavaLangObject() {
       
    95         if (javaLangObject == null) {
       
    96             javaLangObject = (HotSpotResolvedObjectTypeImpl) fromClass(Object.class);
       
    97         }
       
    98         return javaLangObject;
       
    99     }
       
   100 
       
   101     HotSpotResolvedObjectTypeImpl getJavaLangString() {
       
   102         if (javaLangString == null) {
       
   103             javaLangString = (HotSpotResolvedObjectTypeImpl) fromClass(String.class);
       
   104         }
       
   105         return javaLangString;
       
   106     }
       
   107 
       
   108     HotSpotResolvedObjectTypeImpl getJavaLangClass() {
       
   109         if (javaLangClass == null) {
       
   110             javaLangClass = (HotSpotResolvedObjectTypeImpl) fromClass(Class.class);
       
   111         }
       
   112         return javaLangClass;
       
   113     }
       
   114 
       
   115     HotSpotResolvedObjectTypeImpl getJavaLangCloneable() {
       
   116         if (cloneableType == null) {
       
   117             cloneableType = (HotSpotResolvedObjectTypeImpl) fromClass(Cloneable.class);
       
   118         }
       
   119         return cloneableType;
       
   120     }
       
   121 
       
   122     HotSpotResolvedObjectTypeImpl getJavaLangSerializable() {
       
   123         if (serializableType == null) {
       
   124             serializableType = (HotSpotResolvedObjectTypeImpl) fromClass(Serializable.class);
       
   125         }
       
   126         return serializableType;
       
   127     }
       
   128 
       
   129     HotSpotResolvedObjectTypeImpl getJavaLangThrowable() {
       
   130         if (throwableType == null) {
       
   131             throwableType = (HotSpotResolvedObjectTypeImpl) fromClass(Throwable.class);
       
   132         }
       
   133         return throwableType;
       
   134     }
       
   135 
       
   136     HotSpotResolvedObjectTypeImpl getJavaLangEnum() {
       
   137         if (enumType == null) {
       
   138             enumType = (HotSpotResolvedObjectTypeImpl) fromClass(Enum.class);
       
   139         }
       
   140         return enumType;
       
   141     }
       
   142 
       
   143     HotSpotResolvedObjectTypeImpl getConstantCallSite() {
       
   144         if (constantCallSiteType == null) {
       
   145             constantCallSiteType = (HotSpotResolvedObjectTypeImpl) fromClass(ConstantCallSite.class);
       
   146         }
       
   147         return constantCallSiteType;
       
   148     }
       
   149 
       
   150     HotSpotResolvedObjectTypeImpl getCallSite() {
       
   151         if (callSiteType == null) {
       
   152             callSiteType = (HotSpotResolvedObjectTypeImpl) fromClass(CallSite.class);
       
   153         }
       
   154         return callSiteType;
       
   155     }
       
   156 
       
   157     HotSpotResolvedObjectType getMethodHandleClass() {
       
   158         if (javaLangInvokeMethodHandle == null) {
       
   159             javaLangInvokeMethodHandle = (HotSpotResolvedObjectTypeImpl) fromClass(MethodHandle.class);
       
   160         }
       
   161         return javaLangInvokeMethodHandle;
       
   162     }
       
   163 
       
   164     /**
       
   165      * Gets the singleton {@link HotSpotJVMCIRuntime} object.
       
   166      */
       
   167     @VMEntryPoint
    75     @SuppressWarnings("try")
   168     @SuppressWarnings("try")
    76     static class DelayedInit {
   169     public static HotSpotJVMCIRuntime runtime() {
    77         private static final HotSpotJVMCIRuntime instance;
   170         HotSpotJVMCIRuntime result = instance;
    78 
   171         if (result == null) {
    79         static {
   172             // Synchronize on JVMCI.class to avoid deadlock
    80             try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
   173             // between the two JVMCI initialization paths:
    81                 instance = new HotSpotJVMCIRuntime();
   174             // HotSpotJVMCIRuntime.runtime() and JVMCI.getRuntime().
    82 
   175             synchronized (JVMCI.class) {
    83                 // Can only do eager initialization of the JVMCI compiler
   176                 result = instance;
    84                 // once the singleton instance is available.
   177                 if (result == null) {
    85                 if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
   178                     try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
    86                     instance.getCompiler();
   179                         instance = result = new HotSpotJVMCIRuntime();
       
   180 
       
   181                         // Can only do eager initialization of the JVMCI compiler
       
   182                         // once the singleton instance is available.
       
   183                         if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
       
   184                             instance.getCompiler();
       
   185                         }
       
   186                     }
       
   187                     // Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is
       
   188                     // initialized.
       
   189                     JVMCI.getRuntime();
    87                 }
   190                 }
    88             }
   191             }
    89         }
   192         }
    90     }
   193         return result;
    91 
   194     }
    92     /**
   195 
    93      * Gets the singleton {@link HotSpotJVMCIRuntime} object.
   196     @VMEntryPoint
    94      */
   197     static Throwable decodeThrowable(String encodedThrowable) throws Throwable {
    95     public static HotSpotJVMCIRuntime runtime() {
   198         return TranslatedException.decodeThrowable(encodedThrowable);
    96         JVMCI.initialize();
   199     }
    97         return DelayedInit.instance;
   200 
       
   201     @VMEntryPoint
       
   202     static String encodeThrowable(Throwable throwable) throws Throwable {
       
   203         return TranslatedException.encodeThrowable(throwable);
       
   204     }
       
   205 
       
   206     @VMEntryPoint
       
   207     static String callToString(Object o) {
       
   208         return o.toString();
    98     }
   209     }
    99 
   210 
   100     /**
   211     /**
   101      * A list of all supported JVMCI options.
   212      * A list of all supported JVMCI options.
   102      */
   213      */
   103     public enum Option {
   214     public enum Option {
   104         // @formatter:off
   215         // @formatter:off
   105         Compiler(String.class, null, "Selects the system compiler. This must match the getCompilerName() value returned " +
   216         Compiler(String.class, null, "Selects the system compiler. This must match the getCompilerName() value returned " +
   106                                      "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
   217                 "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
   107                                      "An empty string or the value \"null\" selects a compiler " +
   218                 "An empty string or the value \"null\" selects a compiler " +
   108                                      "that will raise an exception upon receiving a compilation request."),
   219                 "that will raise an exception upon receiving a compilation request."),
   109         // Note: The following one is not used (see InitTimer.ENABLED). It is added here
   220         // Note: The following one is not used (see InitTimer.ENABLED). It is added here
   110         // so that -XX:+JVMCIPrintProperties shows the option.
   221         // so that -XX:+JVMCIPrintProperties shows the option.
   111         InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
   222         InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
   112         PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
   223         PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
   113         TraceMethodDataFilter(String.class, null,
   224         TraceMethodDataFilter(String.class, null,
   114                         "Enables tracing of profiling info when read by JVMCI.",
   225                 "Enables tracing of profiling info when read by JVMCI.",
   115                         "Empty value: trace all methods",
   226                 "Empty value: trace all methods",
   116                         "Non-empty value: trace methods whose fully qualified name contains the value."),
   227                 "Non-empty value: trace methods whose fully qualified name contains the value."),
   117         UseProfilingInformation(Boolean.class, true, "");
   228         UseProfilingInformation(Boolean.class, true, "");
   118         // @formatter:on
   229         // @formatter:on
   119 
   230 
   120         /**
   231         /**
   121          * The prefix for system properties that are JVMCI options.
   232          * The prefix for system properties that are JVMCI options.
   122          */
   233          */
   123         private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
   234         private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
   124 
   235 
   125         /**
   236         /**
   126          * Marker for uninitialized flags.
   237          * Sentinel for value initialized to {@code null} since {@code null} means uninitialized.
   127          */
   238          */
   128         private static final String UNINITIALIZED = "UNINITIALIZED";
   239         private static final String NULL_VALUE = "NULL";
   129 
   240 
   130         private final Class<?> type;
   241         private final Class<?> type;
   131         private Object value;
   242         @NativeImageReinitialize private Object value;
   132         private final Object defaultValue;
   243         private final Object defaultValue;
   133         private boolean isDefault;
   244         private boolean isDefault;
   134         private final String[] helpLines;
   245         private final String[] helpLines;
   135 
   246 
   136         Option(Class<?> type, Object defaultValue, String... helpLines) {
   247         Option(Class<?> type, Object defaultValue, String... helpLines) {
   137             assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
   248             assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
   138             this.type = type;
   249             this.type = type;
   139             this.value = UNINITIALIZED;
       
   140             this.defaultValue = defaultValue;
   250             this.defaultValue = defaultValue;
   141             this.helpLines = helpLines;
   251             this.helpLines = helpLines;
   142         }
   252         }
   143 
   253 
   144         @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
   254         @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
   145         private Object getValue() {
   255         private Object getValue() {
   146             if (value == UNINITIALIZED) {
   256             if (value == null) {
   147                 String propertyValue = VM.getSavedProperty(getPropertyName());
   257                 String propertyValue = Services.getSavedProperty(getPropertyName());
   148                 if (propertyValue == null) {
   258                 if (propertyValue == null) {
   149                     this.value = defaultValue;
   259                     this.value = defaultValue == null ? NULL_VALUE : defaultValue;
   150                     this.isDefault = true;
   260                     this.isDefault = true;
   151                 } else {
   261                 } else {
   152                     if (type == Boolean.class) {
   262                     if (type == Boolean.class) {
   153                         this.value = Boolean.parseBoolean(propertyValue);
   263                         this.value = Boolean.parseBoolean(propertyValue);
   154                     } else if (type == String.class) {
   264                     } else if (type == String.class) {
   156                     } else {
   266                     } else {
   157                         throw new JVMCIError("Unexpected option type " + type);
   267                         throw new JVMCIError("Unexpected option type " + type);
   158                     }
   268                     }
   159                     this.isDefault = false;
   269                     this.isDefault = false;
   160                 }
   270                 }
   161                 // Saved properties should not be interned - let's be sure
   271             }
   162                 assert value != UNINITIALIZED;
   272             return value == NULL_VALUE ? null : value;
   163             }
       
   164             return value;
       
   165         }
   273         }
   166 
   274 
   167         /**
   275         /**
   168          * Gets the name of system property from which this option gets its value.
   276          * Gets the name of system property from which this option gets its value.
   169          */
   277          */
   222                 }
   330                 }
   223             }
   331             }
   224         }
   332         }
   225     }
   333     }
   226 
   334 
   227     static HotSpotJVMCIBackendFactory findFactory(String architecture) {
   335     private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
   228         for (HotSpotJVMCIBackendFactory factory : ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader())) {
   336         Iterable<HotSpotJVMCIBackendFactory> factories = getHotSpotJVMCIBackendFactories();
       
   337 assert factories != null : "sanity";
       
   338         for (HotSpotJVMCIBackendFactory factory : factories) {
   229             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
   339             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
   230                 return factory;
   340                 return factory;
   231             }
   341             }
   232         }
   342         }
   233 
   343 
   234         throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
   344         throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
   235     }
   345     }
   236 
   346 
       
   347     private static volatile List<HotSpotJVMCIBackendFactory> cachedHotSpotJVMCIBackendFactories;
       
   348 
       
   349     @SuppressFBWarnings(value = "LI_LAZY_INIT_UPDATE_STATIC", justification = "not sure about this")
       
   350     private static Iterable<HotSpotJVMCIBackendFactory> getHotSpotJVMCIBackendFactories() {
       
   351         if (IS_IN_NATIVE_IMAGE || cachedHotSpotJVMCIBackendFactories != null) {
       
   352             return cachedHotSpotJVMCIBackendFactories;
       
   353         }
       
   354         Iterable<HotSpotJVMCIBackendFactory> result = ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader());
       
   355         if (IS_BUILDING_NATIVE_IMAGE) {
       
   356             cachedHotSpotJVMCIBackendFactories = new ArrayList<>();
       
   357             for (HotSpotJVMCIBackendFactory factory : result) {
       
   358                 cachedHotSpotJVMCIBackendFactories.add(factory);
       
   359             }
       
   360         }
       
   361         return result;
       
   362     }
       
   363 
   237     /**
   364     /**
   238      * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend.
   365      * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend.
   239      */
   366      */
   240     public static JavaKind getHostWordKind() {
   367     public static JavaKind getHostWordKind() {
   241         return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind;
   368         return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind;
   242     }
   369     }
   243 
   370 
   244     final CompilerToVM compilerToVm;
   371     protected final CompilerToVM compilerToVm;
   245 
   372 
   246     protected final HotSpotVMConfigStore configStore;
   373     protected final HotSpotVMConfigStore configStore;
   247     private final HotSpotVMConfig config;
   374     protected final HotSpotVMConfig config;
   248     private final JVMCIBackend hostBackend;
   375     private final JVMCIBackend hostBackend;
   249 
   376 
   250     private final JVMCICompilerFactory compilerFactory;
   377     private final JVMCICompilerFactory compilerFactory;
   251     private final HotSpotJVMCICompilerFactory hsCompilerFactory;
   378     private final HotSpotJVMCICompilerFactory hsCompilerFactory;
   252     private volatile JVMCICompiler compiler;
   379     private volatile JVMCICompiler compiler;
   253     final HotSpotJVMCIMetaAccessContext metaAccessContext;
   380     protected final HotSpotJVMCIReflection reflection;
       
   381 
       
   382     @NativeImageReinitialize private volatile boolean creatingCompiler;
       
   383 
       
   384     /**
       
   385      * Cache for speeding up {@link #fromClass(Class)}.
       
   386      */
       
   387     @NativeImageReinitialize private volatile ClassValue<WeakReference<HotSpotResolvedJavaType>> resolvedJavaType;
       
   388 
       
   389     @NativeImageReinitialize private HashMap<Long, WeakReference<ResolvedJavaType>> resolvedJavaTypes;
   254 
   390 
   255     /**
   391     /**
   256      * Stores the value set by {@link #excludeFromJVMCICompilation(Module...)} so that it can
   392      * Stores the value set by {@link #excludeFromJVMCICompilation(Module...)} so that it can
   257      * be read from the VM.
   393      * be read from the VM.
   258      */
   394      */
   259     @SuppressWarnings("unused") @NativeImageReinitialize private Module[] excludeFromJVMCICompilation;
   395     @SuppressWarnings("unused")//
       
   396     @NativeImageReinitialize private Module[] excludeFromJVMCICompilation;
   260 
   397 
   261 
   398 
   262     private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
   399     private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
   263 
   400 
   264     private volatile List<HotSpotVMEventListener> vmEventListeners;
   401     private volatile List<HotSpotVMEventListener> vmEventListeners;
   281         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
   418         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
   282             configStore = new HotSpotVMConfigStore(compilerToVm);
   419             configStore = new HotSpotVMConfigStore(compilerToVm);
   283             config = new HotSpotVMConfig(configStore);
   420             config = new HotSpotVMConfig(configStore);
   284         }
   421         }
   285 
   422 
       
   423         reflection = IS_IN_NATIVE_IMAGE ? new SharedLibraryJVMCIReflection() : new HotSpotJDKReflection();
       
   424 
       
   425         PrintStream vmLogStream = null;
       
   426         if (IS_IN_NATIVE_IMAGE) {
       
   427             // Redirect System.out and System.err to HotSpot's TTY stream
       
   428             vmLogStream = new PrintStream(getLogStream());
       
   429             System.setOut(vmLogStream);
       
   430             System.setErr(vmLogStream);
       
   431         }
       
   432 
   286         String hostArchitecture = config.getHostArchitectureName();
   433         String hostArchitecture = config.getHostArchitectureName();
   287 
   434 
   288         HotSpotJVMCIBackendFactory factory;
   435         HotSpotJVMCIBackendFactory factory;
   289         try (InitTimer t = timer("find factory:", hostArchitecture)) {
   436         try (InitTimer t = timer("find factory:", hostArchitecture)) {
   290             factory = findFactory(hostArchitecture);
   437             factory = findFactory(hostArchitecture);
   291         }
   438         }
   292 
   439 
   293         try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
   440         try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
   294             hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
   441             hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
   295         }
   442         }
   296 
       
   297         metaAccessContext = new HotSpotJVMCIMetaAccessContext();
       
   298 
   443 
   299         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
   444         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
   300         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
   445         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
   301             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
   446             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
   302             if (hsCompilerFactory.getCompilationLevelAdjustment() != None) {
   447             if (hsCompilerFactory.getCompilationLevelAdjustment() != None) {
   308         } else {
   453         } else {
   309             hsCompilerFactory = null;
   454             hsCompilerFactory = null;
   310         }
   455         }
   311 
   456 
   312         if (config.getFlag("JVMCIPrintProperties", Boolean.class)) {
   457         if (config.getFlag("JVMCIPrintProperties", Boolean.class)) {
   313             PrintStream out = new PrintStream(getLogStream());
   458             if (vmLogStream == null) {
   314             Option.printProperties(out);
   459                 vmLogStream = new PrintStream(getLogStream());
   315             compilerFactory.printProperties(out);
   460             }
       
   461             Option.printProperties(vmLogStream);
       
   462             compilerFactory.printProperties(vmLogStream);
   316             System.exit(0);
   463             System.exit(0);
   317         }
   464         }
   318 
   465 
   319         if (Option.PrintConfig.getBoolean()) {
   466         if (Option.PrintConfig.getBoolean()) {
   320             configStore.printConfig();
   467             printConfig(configStore, compilerToVm);
   321         }
   468         }
       
   469     }
       
   470 
       
   471     HotSpotResolvedJavaType createClass(Class<?> javaClass) {
       
   472         if (javaClass.isPrimitive()) {
       
   473             return HotSpotResolvedPrimitiveType.forKind(JavaKind.fromJavaClass(javaClass));
       
   474         }
       
   475         if (IS_IN_NATIVE_IMAGE) {
       
   476             try {
       
   477                 return compilerToVm.lookupType(javaClass.getName().replace('.', '/'), null, true);
       
   478             } catch (ClassNotFoundException e) {
       
   479                 throw new JVMCIError(e);
       
   480             }
       
   481         }
       
   482         return compilerToVm.lookupClass(javaClass);
       
   483     }
       
   484 
       
   485     private HotSpotResolvedJavaType fromClass0(Class<?> javaClass) {
       
   486         if (resolvedJavaType == null) {
       
   487             synchronized (this) {
       
   488                 if (resolvedJavaType == null) {
       
   489                     resolvedJavaType = new ClassValue<WeakReference<HotSpotResolvedJavaType>>() {
       
   490                         @Override
       
   491                         protected WeakReference<HotSpotResolvedJavaType> computeValue(Class<?> type) {
       
   492                             return new WeakReference<>(createClass(type));
       
   493                         }
       
   494                     };
       
   495                 }
       
   496             }
       
   497         }
       
   498         HotSpotResolvedJavaType javaType = null;
       
   499         while (javaType == null) {
       
   500             WeakReference<HotSpotResolvedJavaType> type = resolvedJavaType.get(javaClass);
       
   501             javaType = type.get();
       
   502             if (javaType == null) {
       
   503                 /*
       
   504                  * If the referent has become null, clear out the current value and let computeValue
       
   505                  * above create a new value. Reload the value in a loop because in theory the
       
   506                  * WeakReference referent can be reclaimed at any point.
       
   507                  */
       
   508                 resolvedJavaType.remove(javaClass);
       
   509             }
       
   510         }
       
   511         return javaType;
       
   512     }
       
   513 
       
   514     /**
       
   515      * Gets the JVMCI mirror for a {@link Class} object.
       
   516      *
       
   517      * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
       
   518      */
       
   519     HotSpotResolvedJavaType fromClass(Class<?> javaClass) {
       
   520         if (javaClass == null) {
       
   521             return null;
       
   522         }
       
   523         return fromClass0(javaClass);
       
   524     }
       
   525 
       
   526     synchronized HotSpotResolvedObjectTypeImpl fromMetaspace(long klassPointer, String signature) {
       
   527         if (resolvedJavaTypes == null) {
       
   528             resolvedJavaTypes = new HashMap<>();
       
   529         }
       
   530         assert klassPointer != 0;
       
   531         WeakReference<ResolvedJavaType> klassReference = resolvedJavaTypes.get(klassPointer);
       
   532         HotSpotResolvedObjectTypeImpl javaType = null;
       
   533         if (klassReference != null) {
       
   534             javaType = (HotSpotResolvedObjectTypeImpl) klassReference.get();
       
   535         }
       
   536         if (javaType == null) {
       
   537             javaType = new HotSpotResolvedObjectTypeImpl(klassPointer, signature);
       
   538             resolvedJavaTypes.put(klassPointer, new WeakReference<>(javaType));
       
   539         }
       
   540         return javaType;
   322     }
   541     }
   323 
   542 
   324     private JVMCIBackend registerBackend(JVMCIBackend backend) {
   543     private JVMCIBackend registerBackend(JVMCIBackend backend) {
   325         Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass();
   544         Class<? extends Architecture> arch = backend.getCodeCache().getTarget().arch.getClass();
   326         JVMCIBackend oldValue = backends.put(arch, backend);
   545         JVMCIBackend oldValue = backends.put(arch, backend);
   327         assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName();
   546         assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName();
   328         return backend;
   547         return backend;
   329     }
   548     }
   330 
   549 
   331     ResolvedJavaType fromClass(Class<?> javaClass) {
       
   332         return metaAccessContext.fromClass(javaClass);
       
   333     }
       
   334 
       
   335     public HotSpotVMConfigStore getConfigStore() {
   550     public HotSpotVMConfigStore getConfigStore() {
   336         return configStore;
   551         return configStore;
   337     }
   552     }
   338 
   553 
   339     HotSpotVMConfig getConfig() {
   554     public HotSpotVMConfig getConfig() {
   340         return config;
   555         return config;
   341     }
   556     }
   342 
   557 
   343     CompilerToVM getCompilerToVM() {
   558     public CompilerToVM getCompilerToVM() {
   344         return compilerToVm;
   559         return compilerToVm;
   345     }
   560     }
   346 
   561 
   347     // Non-volatile since multi-initialization is harmless
   562     HotSpotJVMCIReflection getReflection() {
   348     private Predicate<ResolvedJavaType> intrinsificationTrustPredicate;
   563         return reflection;
       
   564     }
   349 
   565 
   350     /**
   566     /**
   351      * Gets a predicate that determines if a given type can be considered trusted for the purpose of
   567      * Gets a predicate that determines if a given type can be considered trusted for the purpose of
   352      * intrinsifying methods it declares.
   568      * intrinsifying methods it declares.
   353      *
   569      *
   354      * @param compilerLeafClasses classes in the leaves of the module graph comprising the JVMCI
   570      * @param compilerLeafClasses classes in the leaves of the module graph comprising the JVMCI
   355      *            compiler.
   571      *            compiler.
   356      */
   572      */
   357     public Predicate<ResolvedJavaType> getIntrinsificationTrustPredicate(Class<?>... compilerLeafClasses) {
   573     public Predicate<ResolvedJavaType> getIntrinsificationTrustPredicate(Class<?>... compilerLeafClasses) {
   358         if (intrinsificationTrustPredicate == null) {
   574         return new Predicate<ResolvedJavaType>() {
   359             intrinsificationTrustPredicate = new Predicate<>() {
   575             @Override
   360                 @Override
   576             public boolean test(ResolvedJavaType type) {
   361                 public boolean test(ResolvedJavaType type) {
   577                 if (type instanceof HotSpotResolvedObjectTypeImpl) {
   362                     if (type instanceof HotSpotResolvedJavaType) {
   578                     HotSpotResolvedObjectTypeImpl hsType = (HotSpotResolvedObjectTypeImpl) type;
   363                         Class<?> mirror = getMirror(type);
   579                     return compilerToVm.isTrustedForIntrinsics(hsType);
   364                         Module module = mirror.getModule();
   580                 } else {
   365                         return getTrustedModules().contains(module);
   581                     return false;
   366                     } else {
       
   367                         return false;
       
   368                     }
       
   369                 }
   582                 }
   370 
   583             }
   371                 private volatile Set<Module> trustedModules;
   584         };
   372 
       
   373                 private Set<Module> getTrustedModules() {
       
   374                     Set<Module> modules = trustedModules;
       
   375                     if (modules == null) {
       
   376                         modules = new HashSet<>();
       
   377                         for (Class<?> compilerConfiguration : compilerLeafClasses) {
       
   378                             Module compilerConfigurationModule = compilerConfiguration.getModule();
       
   379                             if (compilerConfigurationModule.getDescriptor().isAutomatic()) {
       
   380                                 throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
       
   381                                                 compilerConfigurationModule.getName(), compilerConfiguration.getClass().getName()));
       
   382                             }
       
   383                             modules.add(compilerConfigurationModule);
       
   384                             for (Requires require : compilerConfigurationModule.getDescriptor().requires()) {
       
   385                                 for (Module module : compilerConfigurationModule.getLayer().modules()) {
       
   386                                     if (module.getName().equals(require.name())) {
       
   387                                         modules.add(module);
       
   388                                     }
       
   389                                 }
       
   390                             }
       
   391                         }
       
   392                         trustedModules = modules;
       
   393                     }
       
   394                     return modules;
       
   395                 }
       
   396             };
       
   397         }
       
   398         return intrinsificationTrustPredicate;
       
   399     }
   585     }
   400 
   586 
   401     /**
   587     /**
   402      * Get the {@link Class} corresponding to {@code type}.
   588      * Get the {@link Class} corresponding to {@code type}.
   403      *
   589      *
   404      * @param type the type for which a {@link Class} is requested
   590      * @param type the type for which a {@link Class} is requested
   405      * @return the original Java class corresponding to {@code type} or {@code null} if this runtime
   591      * @return the original Java class corresponding to {@code type} or {@code null} if this runtime
   406      *         does not support mapping {@link ResolvedJavaType} instances to {@link Class}
   592      *         does not support mapping {@link ResolvedJavaType} instances to {@link Class}
   407      *         instances
   593      *         instances
   408      */
   594      */
   409     @SuppressWarnings("static-method")
       
   410     public Class<?> getMirror(ResolvedJavaType type) {
   595     public Class<?> getMirror(ResolvedJavaType type) {
   411         return ((HotSpotResolvedJavaType) type).mirror();
   596         if (type instanceof HotSpotResolvedJavaType && reflection instanceof HotSpotJDKReflection) {
       
   597             return ((HotSpotJDKReflection) reflection).getMirror((HotSpotResolvedJavaType) type);
       
   598         }
       
   599         return null;
   412     }
   600     }
   413 
   601 
   414     @Override
   602     @Override
   415     public JVMCICompiler getCompiler() {
   603     public JVMCICompiler getCompiler() {
   416         if (compiler == null) {
   604         if (compiler == null) {
   417             synchronized (this) {
   605             synchronized (this) {
   418                 if (compiler == null) {
   606                 if (compiler == null) {
       
   607                     assert !creatingCompiler : "recursive compiler creation";
       
   608                     creatingCompiler = true;
   419                     compiler = compilerFactory.createCompiler(this);
   609                     compiler = compilerFactory.createCompiler(this);
       
   610                     creatingCompiler = false;
   420                 }
   611                 }
   421             }
   612             }
   422         }
   613         }
   423         return compiler;
   614         return compiler;
   424     }
   615     }
   436      * @throws LinkageError if {@code resolve == true} and the resolution failed
   627      * @throws LinkageError if {@code resolve == true} and the resolution failed
   437      * @throws NullPointerException if {@code accessingClass} is {@code null}
   628      * @throws NullPointerException if {@code accessingClass} is {@code null}
   438      */
   629      */
   439     public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
   630     public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
   440         Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
   631         Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
       
   632         return lookupTypeInternal(name, accessingType, resolve);
       
   633     }
       
   634 
       
   635     JavaType lookupTypeInternal(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
   441         // If the name represents a primitive type we can short-circuit the lookup.
   636         // If the name represents a primitive type we can short-circuit the lookup.
   442         if (name.length() == 1) {
   637         if (name.length() == 1) {
   443             JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
   638             JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
   444             return fromClass(kind.toJavaClass());
   639             return HotSpotResolvedPrimitiveType.forKind(kind);
   445         }
   640         }
   446 
   641 
   447         // Resolve non-primitive types in the VM.
   642         // Resolve non-primitive types in the VM.
   448         HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType;
   643         HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType;
   449         try {
   644         try {
   450             final HotSpotResolvedObjectTypeImpl klass = compilerToVm.lookupType(name, hsAccessingType.mirror(), resolve);
   645             final HotSpotResolvedJavaType klass = compilerToVm.lookupType(name, hsAccessingType, resolve);
   451 
   646 
   452             if (klass == null) {
   647             if (klass == null) {
   453                 assert resolve == false;
   648                 assert resolve == false : name;
   454                 return UnresolvedJavaType.create(name);
   649                 return UnresolvedJavaType.create(name);
   455             }
   650             }
   456             return klass;
   651             return klass;
   457         } catch (ClassNotFoundException e) {
   652         } catch (ClassNotFoundException e) {
   458             throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e);
   653             throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e);
   472 
   667 
   473     public Map<Class<? extends Architecture>, JVMCIBackend> getJVMCIBackends() {
   668     public Map<Class<? extends Architecture>, JVMCIBackend> getJVMCIBackends() {
   474         return Collections.unmodifiableMap(backends);
   669         return Collections.unmodifiableMap(backends);
   475     }
   670     }
   476 
   671 
   477     /**
   672     @VMEntryPoint
   478      * Called from the VM.
   673     private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long compileState, int id) {
   479      */
   674         CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, compileState, id));
   480     @SuppressWarnings({"unused"})
       
   481     private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
       
   482         CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id));
       
   483         assert result != null : "compileMethod must always return something";
   675         assert result != null : "compileMethod must always return something";
   484         HotSpotCompilationRequestResult hsResult;
   676         HotSpotCompilationRequestResult hsResult;
   485         if (result instanceof HotSpotCompilationRequestResult) {
   677         if (result instanceof HotSpotCompilationRequestResult) {
   486             hsResult = (HotSpotCompilationRequestResult) result;
   678             hsResult = (HotSpotCompilationRequestResult) result;
   487         } else {
   679         } else {
   498         return hsResult;
   690         return hsResult;
   499     }
   691     }
   500 
   692 
   501     /**
   693     /**
   502      * Shuts down the runtime.
   694      * Shuts down the runtime.
   503      *
   695      */
   504      * Called from the VM.
   696     @VMEntryPoint
   505      */
       
   506     @SuppressWarnings({"unused"})
       
   507     private void shutdown() throws Exception {
   697     private void shutdown() throws Exception {
       
   698         // Cleaners are normally only processed when a new Cleaner is
       
   699         // instantiated so process all remaining cleaners now.
       
   700         Cleaner.clean();
       
   701 
   508         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
   702         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
   509             vmEventListener.notifyShutdown();
   703             vmEventListener.notifyShutdown();
   510         }
   704         }
   511     }
   705     }
   512 
   706 
   513     /**
   707     /**
   514      * Notify on completion of a bootstrap.
   708      * Notify on completion of a bootstrap.
   515      *
   709      */
   516      * Called from the VM.
   710     @VMEntryPoint
   517      */
       
   518     @SuppressWarnings({"unused"})
       
   519     private void bootstrapFinished() throws Exception {
   711     private void bootstrapFinished() throws Exception {
   520         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
   712         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
   521             vmEventListener.notifyBootstrapFinished();
   713             vmEventListener.notifyBootstrapFinished();
   522         }
   714         }
   523     }
   715     }
   530      * @param compiledCode
   722      * @param compiledCode
   531      */
   723      */
   532     void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
   724     void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
   533         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
   725         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
   534             vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compiledCode);
   726             vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compiledCode);
       
   727         }
       
   728     }
       
   729 
       
   730     @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
       
   731     private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
       
   732         String line = String.format(format, args);
       
   733         byte[] lineBytes = line.getBytes();
       
   734         vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
       
   735         vm.flushDebugOutput();
       
   736     }
       
   737 
       
   738     private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
       
   739         TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
       
   740         for (VMField field : fields.values()) {
       
   741             if (!field.isStatic()) {
       
   742                 printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
       
   743             } else {
       
   744                 String value = field.value == null ? "null" : field.value instanceof Boolean ? field.value.toString() : String.format("%d[0x%x]", field.value, field.value);
       
   745                 printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
       
   746             }
       
   747         }
       
   748         TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
       
   749         for (VMFlag flag : flags.values()) {
       
   750             printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
       
   751         }
       
   752         TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
       
   753         for (Map.Entry<String, Long> e : addresses.entrySet()) {
       
   754             printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
       
   755         }
       
   756         TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
       
   757         for (Map.Entry<String, Long> e : constants.entrySet()) {
       
   758             printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
       
   759         }
       
   760         for (VMIntrinsicMethod e : store.getIntrinsics()) {
       
   761             printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
   535         }
   762         }
   536     }
   763     }
   537 
   764 
   538     /**
   765     /**
   539      * Gets an output stream that writes to HotSpot's {@code tty} stream.
   766      * Gets an output stream that writes to HotSpot's {@code tty} stream.
   575     /**
   802     /**
   576      * The offset from the origin of an array to the first element.
   803      * The offset from the origin of an array to the first element.
   577      *
   804      *
   578      * @return the offset in bytes
   805      * @return the offset in bytes
   579      */
   806      */
   580     @SuppressWarnings("static-method")
       
   581     public int getArrayBaseOffset(JavaKind kind) {
   807     public int getArrayBaseOffset(JavaKind kind) {
   582         switch (kind) {
   808         switch (kind) {
   583             case Boolean:
   809             case Boolean:
   584                 return Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
   810                 return compilerToVm.ARRAY_BOOLEAN_BASE_OFFSET;
   585             case Byte:
   811             case Byte:
   586                 return Unsafe.ARRAY_BYTE_BASE_OFFSET;
   812                 return compilerToVm.ARRAY_BYTE_BASE_OFFSET;
   587             case Char:
   813             case Char:
   588                 return Unsafe.ARRAY_CHAR_BASE_OFFSET;
   814                 return compilerToVm.ARRAY_CHAR_BASE_OFFSET;
   589             case Short:
   815             case Short:
   590                 return Unsafe.ARRAY_SHORT_BASE_OFFSET;
   816                 return compilerToVm.ARRAY_SHORT_BASE_OFFSET;
   591             case Int:
   817             case Int:
   592                 return Unsafe.ARRAY_INT_BASE_OFFSET;
   818                 return compilerToVm.ARRAY_INT_BASE_OFFSET;
   593             case Long:
   819             case Long:
   594                 return Unsafe.ARRAY_LONG_BASE_OFFSET;
   820                 return compilerToVm.ARRAY_LONG_BASE_OFFSET;
   595             case Float:
   821             case Float:
   596                 return Unsafe.ARRAY_FLOAT_BASE_OFFSET;
   822                 return compilerToVm.ARRAY_FLOAT_BASE_OFFSET;
   597             case Double:
   823             case Double:
   598                 return Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
   824                 return compilerToVm.ARRAY_DOUBLE_BASE_OFFSET;
   599             case Object:
   825             case Object:
   600                 return Unsafe.ARRAY_OBJECT_BASE_OFFSET;
   826                 return compilerToVm.ARRAY_OBJECT_BASE_OFFSET;
   601             default:
   827             default:
   602                 throw new JVMCIError("%s", kind);
   828                 throw new JVMCIError("%s", kind);
   603         }
   829         }
   604 
   830 
   605     }
   831     }
   607     /**
   833     /**
   608      * The scale used for the index when accessing elements of an array of this kind.
   834      * The scale used for the index when accessing elements of an array of this kind.
   609      *
   835      *
   610      * @return the scale in order to convert the index into a byte offset
   836      * @return the scale in order to convert the index into a byte offset
   611      */
   837      */
   612     @SuppressWarnings("static-method")
       
   613     public int getArrayIndexScale(JavaKind kind) {
   838     public int getArrayIndexScale(JavaKind kind) {
   614         switch (kind) {
   839         switch (kind) {
   615             case Boolean:
   840             case Boolean:
   616                 return Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
   841                 return compilerToVm.ARRAY_BOOLEAN_INDEX_SCALE;
   617             case Byte:
   842             case Byte:
   618                 return Unsafe.ARRAY_BYTE_INDEX_SCALE;
   843                 return compilerToVm.ARRAY_BYTE_INDEX_SCALE;
   619             case Char:
   844             case Char:
   620                 return Unsafe.ARRAY_CHAR_INDEX_SCALE;
   845                 return compilerToVm.ARRAY_CHAR_INDEX_SCALE;
   621             case Short:
   846             case Short:
   622                 return Unsafe.ARRAY_SHORT_INDEX_SCALE;
   847                 return compilerToVm.ARRAY_SHORT_INDEX_SCALE;
   623             case Int:
   848             case Int:
   624                 return Unsafe.ARRAY_INT_INDEX_SCALE;
   849                 return compilerToVm.ARRAY_INT_INDEX_SCALE;
   625             case Long:
   850             case Long:
   626                 return Unsafe.ARRAY_LONG_INDEX_SCALE;
   851                 return compilerToVm.ARRAY_LONG_INDEX_SCALE;
   627             case Float:
   852             case Float:
   628                 return Unsafe.ARRAY_FLOAT_INDEX_SCALE;
   853                 return compilerToVm.ARRAY_FLOAT_INDEX_SCALE;
   629             case Double:
   854             case Double:
   630                 return Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
   855                 return compilerToVm.ARRAY_DOUBLE_INDEX_SCALE;
   631             case Object:
   856             case Object:
   632                 return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
   857                 return compilerToVm.ARRAY_OBJECT_INDEX_SCALE;
   633             default:
   858             default:
   634                 throw new JVMCIError("%s", kind);
   859                 throw new JVMCIError("%s", kind);
   635 
   860 
   636         }
   861         }
   637     }
   862     }
   638 
   863 
   639     /**
   864     /**
   640      * Links each native method in {@code clazz} to an implementation in the JVMCI SVM library.
   865      * Links each native method in {@code clazz} to an implementation in the JVMCI shared library.
   641      * <p>
   866      * <p>
   642      * A use case for this is a JVMCI compiler implementation that offers an API to Java code
   867      * A use case for this is a JVMCI compiler implementation that offers an API to Java code
   643      * executing in HotSpot to exercise functionality (mostly) in the JVMCI SVM library. For
   868      * executing in HotSpot to exercise functionality (mostly) in the JVMCI shared library. For
   644      * example:
   869      * example:
   645      *
   870      *
   646      * <pre>
   871      * <pre>
   647      * package com.jcompile;
   872      * package com.jcompile;
   648      *
   873      *
   663      *     private static long getHandle(Method method) { ... }
   888      *     private static long getHandle(Method method) { ... }
   664      *     private static char[] convertToCharArray(String[] a) { ... }
   889      *     private static char[] convertToCharArray(String[] a) { ... }
   665      * }
   890      * }
   666      * </pre>
   891      * </pre>
   667      *
   892      *
   668      * The implementation of the native {@code JCompile.compile0} method would be in the SVM library
   893      * The implementation of the native {@code JCompile.compile0} method would be in the JVMCI
   669      * that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0} implementation
   894      * shared library that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0}
   670      * will be exported as the following JNI-compliant symbol:
   895      * implementation will be exported as the following JNI-compatible symbol:
   671      *
   896      *
   672      * <pre>
   897      * <pre>
   673      * Java_com_jcompile_JCompile_compile0
   898      * Java_com_jcompile_JCompile_compile0
   674      * </pre>
   899      * </pre>
   675      *
   900      *
   676      * How the JVMCI compiler SVM library is built is outside the scope of this document.
   901      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names"
   677      *
   902      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#creating_the_vm"
   678      * @see "https://docs.oracle.com/javase/10/docs/specs/jni/design.html#resolving-native-method-names"
   903      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
   679      *
   904      *
       
   905      *
       
   906      * @return an array of 4 longs where the first value is the {@code JavaVM*} value representing
       
   907      *         the Java VM in the JVMCI shared library, and the remaining values are the first 3
       
   908      *         pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
   680      * @throws NullPointerException if {@code clazz == null}
   909      * @throws NullPointerException if {@code clazz == null}
   681      * @throws IllegalArgumentException if the current execution context is SVM or if {@code clazz}
   910      * @throws IllegalArgumentException if the current execution context is the JVMCI shared library
   682      *             is {@link Class#isPrimitive()}
   911      *             or if {@code clazz} is {@link Class#isPrimitive()}
   683      * @throws UnsatisfiedLinkError if the JVMCI SVM library is not available, a native method in
   912      * @throws UnsatisfiedLinkError if the JVMCI shared library is not available, a native method in
   684      *             {@code clazz} is already linked or the SVM JVMCI library does not contain a
   913      *             {@code clazz} is already linked or the JVMCI shared library does not contain a
   685      *             JNI-compliant symbol for a native method in {@code clazz}
   914      *             JNI-compatible symbol for a native method in {@code clazz}
   686      */
   915      */
   687     @SuppressWarnings({"static-method", "unused"})
   916     public long[] registerNativeMethods(Class<?> clazz) {
   688     public void registerNativeMethods(Class<?> clazz) {
   917         return compilerToVm.registerNativeMethods(clazz);
   689         throw new UnsatisfiedLinkError("SVM library is not available");
   918     }
       
   919 
       
   920     /**
       
   921      * Creates or retrieves an object in the peer runtime that mirrors {@code obj}. The types whose
       
   922      * objects can be translated are:
       
   923      * <ul>
       
   924      * <li>{@link HotSpotResolvedJavaMethodImpl},</li>
       
   925      * <li>{@link HotSpotResolvedObjectTypeImpl},</li>
       
   926      * <li>{@link HotSpotResolvedPrimitiveType},</li>
       
   927      * <li>{@link IndirectHotSpotObjectConstantImpl},</li>
       
   928      * <li>{@link DirectHotSpotObjectConstantImpl} and</li>
       
   929      * <li>{@link HotSpotNmethod}</li>
       
   930      * </ul>
       
   931      *
       
   932      * This mechanism can be used to pass and return values between the HotSpot and JVMCI shared
       
   933      * library runtimes. In the receiving runtime, the value can be converted back to an object with
       
   934      * {@link #unhand(Class, long)}.
       
   935      *
       
   936      * @param obj an object for which an equivalent instance in the peer runtime is requested
       
   937      * @return a JNI global reference to the mirror of {@code obj} in the peer runtime
       
   938      * @throws IllegalArgumentException if {@code obj} is not of a translatable type
       
   939      *
       
   940      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
       
   941      */
       
   942     public long translate(Object obj) {
       
   943         return compilerToVm.translate(obj);
       
   944     }
       
   945 
       
   946     /**
       
   947      * Dereferences and returns the object referred to by the JNI global reference {@code handle}.
       
   948      * The global reference is deleted prior to returning. Any further use of {@code handle} is
       
   949      * invalid.
       
   950      *
       
   951      * @param handle a JNI global reference to an object in the current runtime
       
   952      * @return the object referred to by {@code handle}
       
   953      * @throws ClassCastException if the returned object cannot be case to {@code type}
       
   954      *
       
   955      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
       
   956      *
       
   957      */
       
   958     public <T> T unhand(Class<T> type, long handle) {
       
   959         return type.cast(compilerToVm.unhand(handle));
   690     }
   960     }
   691 
   961 
   692     /**
   962     /**
   693      * Informs HotSpot that no method whose module is in {@code modules} is to be compiled
   963      * Informs HotSpot that no method whose module is in {@code modules} is to be compiled
   694      * with {@link #compileMethod}.
   964      * with {@link #compileMethod}.