changeset 13428:9906107f9050

Merge
author alanb
date Thu, 04 May 2017 11:02:40 +0100
parents 1fc81a6c3d44 fa79b980fa63
children 1d55ec6b9bc7
files src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/JLModule.java src/share/vm/classfile/moduleEntry.cpp src/share/vm/classfile/modules.cpp src/share/vm/classfile/packageEntry.cpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/logging/logTag.hpp src/share/vm/oops/instanceKlass.cpp src/share/vm/prims/jvmti.xml src/share/vm/prims/jvmtiExport.cpp src/share/vm/prims/jvmtiExport.hpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/globals.hpp src/share/vm/runtime/thread.cpp src/share/vm/services/attachListener.cpp test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java test/compiler/jvmci/compilerToVM/AsResolvedJavaMethodTest.java test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java test/compiler/jvmci/compilerToVM/GetBytecodeTest.java test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java test/compiler/jvmci/compilerToVM/GetImplementorTest.java test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java test/compiler/jvmci/compilerToVM/GetSymbolTest.java test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java test/compiler/jvmci/compilerToVM/HasNeverInlineDirectiveTest.java test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java test/compiler/jvmci/compilerToVM/LookupTypeTest.java test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java test/compiler/jvmci/compilerToVM/ReprofileTest.java test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java test/compiler/jvmci/compilerToVM/ResolveMethodTest.java test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java test/compiler/jvmci/errors/TestInvalidCompilationResult.java test/compiler/jvmci/errors/TestInvalidDebugInfo.java test/compiler/jvmci/errors/TestInvalidOopMap.java test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MethodHandleAccessProviderTest.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java test/runtime/logging/ModulesTest.java test/runtime/modules/JVMAddModuleExports.java test/runtime/modules/JVMAddModulePackage.java test/runtime/modules/JVMDefineModule.java test/runtime/modules/ModuleStress/ModuleStressGC.java
diffstat 111 files changed, 1258 insertions(+), 754 deletions(-) [+]
line wrap: on
line diff
--- a/.mx.jvmci/.pydevproject	Tue May 02 08:50:05 2017 +0100
+++ b/.mx.jvmci/.pydevproject	Thu May 04 11:02:40 2017 +0100
@@ -3,7 +3,7 @@
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
 <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
-<path>/.mx.jvmci</path>
+<path>/mx.jvmci</path>
 </pydev_pathproperty>
 <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
 <path>/mx</path>
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/EventProvider.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/EventProvider.java	Thu May 04 11:02:40 2017 +0100
@@ -24,7 +24,6 @@
 
 import jdk.vm.ci.hotspot.EmptyEventProvider.EmptyCompilationEvent;
 import jdk.vm.ci.hotspot.EmptyEventProvider.EmptyCompilerFailureEvent;
-import jdk.vm.ci.services.JVMCIPermission;
 
 /**
  * Service-provider class for logging compiler related events.
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Thu May 04 11:02:40 2017 +0100
@@ -28,9 +28,9 @@
 import jdk.vm.ci.runtime.JVMCICompiler;
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
 import jdk.vm.ci.runtime.JVMCIRuntime;
+import jdk.vm.ci.services.JVMCIPermission;
 import jdk.vm.ci.services.JVMCIServiceLocator;
-import jdk.vm.ci.services.JVMCIPermission;
-import jdk.vm.ci.services.Services;
+import jdk.vm.ci.services.internal.ReflectionAccessJDK;
 
 final class HotSpotJVMCICompilerConfig {
 
@@ -47,7 +47,7 @@
 
         @Override
         public String getCompilerName() {
-            return "<none>";
+            return "null";
         }
 
         @Override
@@ -73,19 +73,23 @@
             JVMCICompilerFactory factory = null;
             String compilerName = Option.Compiler.getString();
             if (compilerName != null) {
-                for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
-                    if (f.getCompilerName().equals(compilerName)) {
-                        factory = f;
+                if (compilerName.isEmpty() || compilerName.equals("null")) {
+                    factory = new DummyCompilerFactory();
+                } else {
+                    for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
+                        if (f.getCompilerName().equals(compilerName)) {
+                            factory = f;
+                        }
                     }
-                }
-                if (factory == null) {
-                    throw new JVMCIError("JVMCI compiler '%s' not found", compilerName);
+                    if (factory == null) {
+                        throw new JVMCIError("JVMCI compiler '%s' not found", compilerName);
+                    }
                 }
             } else {
                 // Auto select a single available compiler
                 for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
                     if (factory == null) {
-                        Services.exportJVMCITo(f.getClass());
+                        ReflectionAccessJDK.openJVMCITo(f.getClass());
                         factory = f;
                     } else {
                         // Multiple factories seen - cancel auto selection
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Thu May 04 11:02:40 2017 +0100
@@ -32,6 +32,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.ServiceLoader;
 import java.util.TreeMap;
 
 import jdk.internal.misc.VM;
@@ -50,7 +51,6 @@
 import jdk.vm.ci.runtime.JVMCICompiler;
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
 import jdk.vm.ci.services.JVMCIServiceLocator;
-import jdk.vm.ci.services.Services;
 
 /**
  * HotSpot implementation of a JVMCI runtime.
@@ -88,7 +88,10 @@
      */
     public enum Option {
         // @formatter:off
-        Compiler(String.class, null, "Selects the system compiler."),
+        Compiler(String.class, null, "Selects the system compiler. This must match the getCompilerName() value returned " +
+                                     "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
+                                     "An empty string or the value \"null\" selects a compiler " +
+                                     "that will raise an exception upon receiving a compilation request."),
         // Note: The following one is not used (see InitTimer.ENABLED). It is added here
         // so that -XX:+JVMCIPrintProperties shows the option.
         InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
@@ -208,7 +211,7 @@
     }
 
     public static HotSpotJVMCIBackendFactory findFactory(String architecture) {
-        for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) {
+        for (HotSpotJVMCIBackendFactory factory : ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader())) {
             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
                 return factory;
             }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Thu May 04 11:02:40 2017 +0100
@@ -98,7 +98,7 @@
             boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
             if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
                 int index = (int) ((displacement - headerSize) / sizeOfElement);
-                throw new AssertionError("Unsafe array access: reading element of kind " + kind +
+                throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind +
                                 " at offset " + displacement + " (index ~ " + index + ") in " +
                                 type.toJavaName() + " object of length " + length);
             }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu May 04 11:02:40 2017 +0100
@@ -801,8 +801,7 @@
         }
         if (elementType.getName().startsWith("Ljava/")) {
             // Classes in a java.* package can only be defined by the
-            // boot class loader. This is enforced by ClassLoader.preDefineClass()
-            assert mirror().getClassLoader() == null;
+            // boot or platform class loader.
             return true;
         }
         ClassLoader thisCl = mirror().getClassLoader();
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java	Thu May 04 11:02:40 2017 +0100
@@ -24,12 +24,15 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.ServiceLoader;
+
+import jdk.vm.ci.services.internal.ReflectionAccessJDK;
 
 /**
  * Service-provider class for the runtime to locate providers of JVMCI services where the latter are
- * not in packages exported by the JVMCI module. As part of instantiating
- * {@link JVMCIServiceLocator}, all JVMCI packages will be {@linkplain Services#exportJVMCITo(Class)
- * exported} to the module defining the class of the instantiated object.
+ * not in packages exported by the JVMCI module. As part of instantiating a
+ * {@link JVMCIServiceLocator}, all JVMCI packages will be opened to the module defining the class
+ * of the instantiated object.
  *
  * While the {@link #getProvider(Class)} method can be used directly, it's usually easier to use
  * {@link #getProviders(Class)}.
@@ -49,30 +52,39 @@
     }
 
     /**
-     * Creates a capability for accessing JVMCI. Once successfully instantiated, JVMCI exports all
-     * its packages to the module defining the type of this object.
+     * Creates a capability for accessing JVMCI. Once successfully instantiated, JVMCI opens all its
+     * packages to the module defining the type of this object.
      *
      * @throws SecurityException if a security manager has been installed and it denies
      *             {@link JVMCIPermission}
      */
     protected JVMCIServiceLocator() {
         this(checkPermission());
-        Services.exportJVMCITo(getClass());
+        Services.checkJVMCIEnabled();
+        ReflectionAccessJDK.openJVMCITo(getClass());
     }
 
     /**
      * Gets the provider of the service defined by {@code service} or {@code null} if this object
      * does not have a provider for {@code service}.
      */
-    public abstract <S> S getProvider(Class<S> service);
+    protected abstract <S> S getProvider(Class<S> service);
 
     /**
-     * Gets the providers of the service defined by {@code service} by querying the
-     * {@link JVMCIServiceLocator} providers obtained by {@link Services#load(Class)}.
+     * Gets the providers of the service defined by {@code service} by querying the available
+     * {@link JVMCIServiceLocator} providers.
+     *
+     * @throws SecurityException if a security manager is present and it denies
+     *             {@link JVMCIPermission}
      */
     public static <S> List<S> getProviders(Class<S> service) {
+        Services.checkJVMCIEnabled();
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new JVMCIPermission());
+        }
         List<S> providers = new ArrayList<>();
-        for (JVMCIServiceLocator access : Services.load(JVMCIServiceLocator.class)) {
+        for (JVMCIServiceLocator access : ServiceLoader.load(JVMCIServiceLocator.class, ClassLoader.getSystemClassLoader())) {
             S provider = access.getProvider(service);
             if (provider != null) {
                 providers.add(provider);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java	Thu May 04 11:02:40 2017 +0100
@@ -22,167 +22,64 @@
  */
 package jdk.vm.ci.services;
 
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.Formatter;
-import java.util.Iterator;
-import java.util.ServiceConfigurationError;
-import java.util.ServiceLoader;
-import java.util.Set;
+import java.util.Map;
 
 /**
- * A mechanism for accessing service providers via JVMCI.
+ * Provides utilities needed by JVMCI clients.
  */
 public final class Services {
 
+    // This class must be compilable and executable on JDK 8 since it's used in annotation
+    // processors while building JDK 9 so use of API added in JDK 9 is made via reflection.
+
     private Services() {
     }
 
-    private static int getJavaSpecificationVersion() {
-        String value = System.getProperty("java.specification.version");
-        if (value.startsWith("1.")) {
-            value = value.substring(2);
-        }
-        return Integer.parseInt(value);
-    }
-
-    /**
-     * The integer value corresponding to the value of the {@code java.specification.version} system
-     * property after any leading {@code "1."} has been stripped.
-     */
-    public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion();
-
-    // Use reflection so that this compiles on Java 8
-    private static final Method getModule;
-    private static final Method getPackages;
-    private static final Method addUses;
-    private static final Method isExported;
-    private static final Method addExports;
-
-    static {
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            try {
-                getModule = Class.class.getMethod("getModule");
-                Class<?> moduleClass = getModule.getReturnType();
-                getPackages = moduleClass.getMethod("getPackages");
-                addUses = moduleClass.getMethod("addUses", Class.class);
-                isExported = moduleClass.getMethod("isExported", String.class, moduleClass);
-                addExports = moduleClass.getMethod("addExports", String.class, moduleClass);
-            } catch (NoSuchMethodException | SecurityException e) {
-                throw new InternalError(e);
-            }
-        } else {
-            getModule = null;
-            getPackages = null;
-            addUses = null;
-            isExported = null;
-            addExports = null;
-        }
-    }
-
     @SuppressWarnings("unchecked")
-    static <T> T invoke(Method method, Object receiver, Object... args) {
+    private static Map<String, String> initSavedProperties() throws InternalError {
         try {
-            return (T) method.invoke(receiver, args);
-        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+            Class<?> vmClass = Class.forName("jdk.internal.misc.VM");
+            Method m = vmClass.getMethod("getSavedProperties");
+            return (Map<String, String>) m.invoke(null);
+        } catch (Exception e) {
             throw new InternalError(e);
         }
     }
 
+    static final Map<String, String> SAVED_PROPERTIES = initSavedProperties();
+    static final boolean JVMCI_ENABLED = Boolean.parseBoolean(SAVED_PROPERTIES.get("jdk.internal.vm.ci.enabled"));
+
     /**
-     * Performs any required security checks and dynamic reconfiguration to allow the module of a
-     * given class to access the classes in the JVMCI module.
-     *
-     * Note: This API uses {@link Class} instead of {@code Module} to provide backwards
-     * compatibility for JVMCI clients compiled against a JDK release earlier than 9.
-     *
-     * @param requestor a class requesting access to the JVMCI module for its module
-     * @throws SecurityException if a security manager is present and it denies
-     *             {@link JVMCIPermission}
+     * Checks that JVMCI is enabled in the VM and throws an error if it isn't.
      */
-    public static void exportJVMCITo(Class<?> requestor) {
+    static void checkJVMCIEnabled() {
+        if (!JVMCI_ENABLED) {
+            throw new Error("The EnableJVMCI VM option must be true (i.e., -XX:+EnableJVMCI) to use JVMCI");
+        }
+    }
+
+    /**
+     * Gets an unmodifiable copy of the system properties saved when {@link System} is initialized.
+     */
+    public static Map<String, String> getSavedProperties() {
+        checkJVMCIEnabled();
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(new JVMCIPermission());
         }
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            Object jvmci = invoke(getModule, Services.class);
-            Object requestorModule = invoke(getModule, requestor);
-            if (jvmci != requestorModule) {
-                Set<String> packages = invoke(getPackages, jvmci);
-                for (String pkg : packages) {
-                    // Export all JVMCI packages dynamically instead
-                    // of requiring a long list of --add-exports
-                    // options on the JVM command line.
-                    boolean exported = invoke(isExported, jvmci, pkg, requestorModule);
-                    if (!exported) {
-                        invoke(addExports, jvmci, pkg, requestorModule);
-                    }
-                }
-            }
-        }
+        return SAVED_PROPERTIES;
     }
 
     /**
-     * Gets an {@link Iterable} of the JVMCI providers available for a given service.
-     *
-     * @throws SecurityException if a security manager is present and it denies
-     *             {@link JVMCIPermission}
+     * Causes the JVMCI subsystem to be initialized if it isn't already initialized.
      */
-    public static <S> Iterable<S> load(Class<S> service) {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            sm.checkPermission(new JVMCIPermission());
+    public static void initializeJVMCI() {
+        checkJVMCIEnabled();
+        try {
+            Class.forName("jdk.vm.ci.runtime.JVMCI");
+        } catch (ClassNotFoundException e) {
+            throw new InternalError(e);
         }
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            Object jvmci = invoke(getModule, Services.class);
-            invoke(addUses, jvmci, service);
-        }
-
-        // Restrict JVMCI clients to be on the class path or module path
-        return ServiceLoader.load(service, ClassLoader.getSystemClassLoader());
-    }
-
-    /**
-     * Gets the JVMCI provider for a given service for which at most one provider must be available.
-     *
-     * @param service the service whose provider is being requested
-     * @param required specifies if an {@link InternalError} should be thrown if no provider of
-     *            {@code service} is available
-     * @throws SecurityException if a security manager is present and it denies
-     *             {@link JVMCIPermission}
-     */
-    public static <S> S loadSingle(Class<S> service, boolean required) {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            sm.checkPermission(new JVMCIPermission());
-        }
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            Object jvmci = invoke(getModule, Services.class);
-            invoke(addUses, jvmci, service);
-        }
-        // Restrict JVMCI clients to be on the class path or module path
-        Iterable<S> providers = ServiceLoader.load(service, ClassLoader.getSystemClassLoader());
-        S singleProvider = null;
-        try {
-            for (Iterator<S> it = providers.iterator(); it.hasNext();) {
-                singleProvider = it.next();
-                if (it.hasNext()) {
-                    throw new InternalError(String.format("Multiple %s providers found", service.getName()));
-                }
-            }
-        } catch (ServiceConfigurationError e) {
-            // If the service is required we will bail out below.
-        }
-        if (singleProvider == null && required) {
-            String javaHome = System.getProperty("java.home");
-            String vmName = System.getProperty("java.vm.name");
-            Formatter errorMessage = new Formatter();
-            errorMessage.format("The VM does not expose required service %s.%n", service.getName());
-            errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
-            errorMessage.format("Currently used VM configuration is: %s", vmName);
-            throw new UnsupportedOperationException(errorMessage.toString());
-        }
-        return singleProvider;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/internal/ReflectionAccessJDK.java	Thu May 04 11:02:40 2017 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.services.internal;
+
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import jdk.vm.ci.services.Services;
+
+/**
+ * Reflection based access to API introduced in JDK 9. This allows the API to be used in code that
+ * must be compiled (but not executed) on JDK 8.
+ */
+public final class ReflectionAccessJDK {
+
+    /**
+     * {@code Class.getModule()}.
+     */
+    private static final Method getModule;
+
+    /**
+     * {@code java.lang.Module.addOpens(String, Module)}.
+     */
+    private static final Method addOpens;
+
+    /**
+     * {@code java.lang.Module.getPackages(Module, String, Module)}.
+     */
+    private static final Method getPackages;
+
+    /**
+     * {@code java.lang.Module.isOpen(String, Module)}.
+     */
+    private static final Method isOpenTo;
+
+    /**
+     * Opens all JVMCI packages to the module of a given class.
+     *
+     * @param other all JVMCI packages will be opened to the module of this class
+     */
+    @SuppressWarnings("unchecked")
+    public static void openJVMCITo(Class<?> other) {
+        try {
+            Object jvmci = getModule.invoke(Services.class);
+            Object otherModule = getModule.invoke(other);
+            if (jvmci != otherModule) {
+                Set<String> packages = (Set<String>) getPackages.invoke(jvmci);
+                for (String pkg : packages) {
+                    boolean opened = (Boolean) isOpenTo.invoke(jvmci, pkg, otherModule);
+                    if (!opened) {
+                        addOpens.invoke(jvmci, pkg, otherModule);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    static {
+        try {
+            getModule = Class.class.getMethod("getModule");
+            Class<?> moduleClass = getModule.getReturnType();
+            getPackages = moduleClass.getMethod("getPackages");
+            isOpenTo = moduleClass.getMethod("isOpen", String.class, moduleClass);
+            addOpens = moduleClass.getDeclaredMethod("addOpens", String.class, moduleClass);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new InternalError(e);
+        }
+    }
+}
--- a/src/jdk.internal.vm.ci/share/classes/module-info.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.ci/share/classes/module-info.java	Thu May 04 11:02:40 2017 +0100
@@ -33,37 +33,4 @@
         jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory,
         jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory,
         jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory;
-
-    exports jdk.vm.ci.aarch64 to
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.amd64 to
-        jdk.aot,
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.code to
-        jdk.aot,
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.code.site to
-        jdk.aot,
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.code.stack to
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.common to
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.hotspot to
-        jdk.aot,
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.hotspot.aarch64 to
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.hotspot.amd64 to
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.hotspot.sparc to
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.meta to
-        jdk.aot,
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.runtime to
-        jdk.aot,
-        jdk.internal.vm.compiler;
-    exports jdk.vm.ci.sparc to
-        jdk.internal.vm.compiler;
 }
--- a/src/jdk.internal.vm.compiler/.mx.graal/.pydevproject	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/.mx.graal/.pydevproject	Thu May 04 11:02:40 2017 +0100
@@ -3,9 +3,9 @@
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
 <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
-<path>/mx.graal</path>
-<path>/mx.graal</path>
-<path>/mx.graal</path>
+<path>/.mx.graal</path>
+<path>/.mx.graal</path>
+<path>/.mx.graal</path>
 </pydev_pathproperty>
 
 </pydev_project>
--- a/src/jdk.internal.vm.compiler/.mx.graal/suite.py	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/.mx.graal/suite.py	Thu May 04 11:02:40 2017 +0100
@@ -8,6 +8,36 @@
   # (e.g., macosx-x86_64-normal-server-release).
   "outputRoot" : "../../../build/mx/hotspot",
 
+  "jdklibraries" : {
+    "JVMCI_SERVICES" : {
+      "path" : "lib/jvmci-services.jar",
+      "sourcePath" : "lib/jvmci-services.src.zip",
+      "optional" : False,
+      "jdkStandardizedSince" : "9",
+      "module" : "jdk.internal.vm.ci"
+    },
+    "JVMCI_API" : {
+      "path" : "lib/jvmci/jvmci-api.jar",
+      "sourcePath" : "lib/jvmci/jvmci-api.src.zip",
+      "dependencies" : [
+        "JVMCI_SERVICES",
+      ],
+      "optional" : False,
+      "jdkStandardizedSince" : "9",
+      "module" : "jdk.internal.vm.ci"
+    },
+    "JVMCI_HOTSPOT" : {
+      "path" : "lib/jvmci/jvmci-hotspot.jar",
+      "sourcePath" : "lib/jvmci/jvmci-hotspot.src.zip",
+      "dependencies" : [
+        "JVMCI_API",
+      ],
+      "optional" : False,
+      "jdkStandardizedSince" : "9",
+      "module" : "jdk.internal.vm.ci"
+    },
+  },
+
   "libraries" : {
 
     # ------------- Libraries -------------
@@ -17,6 +47,16 @@
       "sha1" : "476d9a44cd19d6b55f81571077dfa972a4f8a083",
       "bootClassPathAgent" : "true",
     },
+    "ASM5" : {
+      "sha1" : "0da08b8cce7bbf903602a25a3a163ae252435795",
+      "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/asm-5.0.4.jar"],
+    },
+
+    "ASM_TREE5" : {
+      "sha1" : "396ce0c07ba2b481f25a70195c7c94922f0d1b0b",
+      "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/asm-tree-5.0.4.jar"],
+      "dependencies" : ["ASM5"],
+    },
   },
 
   "projects" : {
@@ -32,6 +72,7 @@
 
     "org.graalvm.compiler.serviceprovider" : {
       "subDir" : "share/classes",
+      "dependencies" : ["JVMCI_SERVICES"],
       "sourceDirs" : ["src"],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
@@ -49,6 +90,7 @@
 
     "org.graalvm.compiler.options" : {
       "subDir" : "share/classes",
+      "dependencies" : ["JVMCI_SERVICES", "JVMCI_API"],
       "sourceDirs" : ["src"],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
@@ -83,6 +125,7 @@
       "sourceDirs" : ["src"],
       "checkstyle" : "org.graalvm.compiler.graph",
       "dependencies" : [
+        "JVMCI_API",
         "org.graalvm.compiler.serviceprovider",
         "org.graalvm.compiler.options"
       ],
@@ -137,6 +180,7 @@
       "sourceDirs" : ["src"],
       "checkstyle" : "org.graalvm.compiler.graph",
       "dependencies" : [
+        "JVMCI_HOTSPOT",
         "org.graalvm.compiler.core.test",
       ],
       "javaCompliance" : "1.8",
@@ -146,6 +190,9 @@
     "org.graalvm.compiler.api.runtime" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
+      "dependencies" : [
+        "JVMCI_API",
+      ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "API,Graal",
@@ -156,6 +203,7 @@
       "sourceDirs" : ["src"],
       "dependencies" : [
         "mx:JUNIT",
+        "JVMCI_SERVICES",
         "org.graalvm.compiler.api.runtime",
       ],
       "checkstyle" : "org.graalvm.compiler.graph",
@@ -166,6 +214,7 @@
     "org.graalvm.compiler.api.replacements" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
+      "dependencies" : ["JVMCI_API"],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "API,Graal,Replacements",
@@ -175,6 +224,7 @@
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
       "dependencies" : [
+        "JVMCI_HOTSPOT",
         "org.graalvm.compiler.api.runtime",
         "org.graalvm.compiler.replacements",
         "org.graalvm.compiler.runtime",
@@ -261,6 +311,8 @@
         "org.graalvm.compiler.hotspot",
         "org.graalvm.compiler.lir.jtt",
         "org.graalvm.compiler.lir.test",
+        "JVMCI_API",
+        "JVMCI_HOTSPOT",
       ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
@@ -347,6 +399,9 @@
     "org.graalvm.compiler.asm" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
+      "dependencies" : [
+        "JVMCI_API",
+      ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,Assembler",
@@ -403,6 +458,7 @@
     "org.graalvm.compiler.bytecode" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
+      "dependencies" : ["JVMCI_API"],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,Java",
@@ -774,6 +830,7 @@
       "dependencies" : [
         "org.graalvm.compiler.lir.jtt",
         "org.graalvm.compiler.lir.aarch64",
+        "JVMCI_HOTSPOT"
       ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
@@ -803,6 +860,7 @@
       "dependencies" : [
         "org.graalvm.compiler.lir.jtt",
         "org.graalvm.compiler.lir.amd64",
+        "JVMCI_HOTSPOT"
       ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
@@ -831,6 +889,7 @@
       "sourceDirs" : ["src"],
       "dependencies" : [
         "org.graalvm.compiler.lir.jtt",
+        "JVMCI_HOTSPOT"
       ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
@@ -908,6 +967,7 @@
         "org.graalvm.compiler.graph.test",
         "org.graalvm.compiler.printer",
         "JAVA_ALLOCATION_INSTRUMENTER",
+        "ASM_TREE5",
       ],
       "annotationProcessors" : ["GRAAL_NODEINFO_PROCESSOR"],
       "checkstyle" : "org.graalvm.compiler.graph",
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java	Thu May 04 11:02:40 2017 +0100
@@ -40,7 +40,7 @@
     private static final GraalRuntime runtime = initializeRuntime();
 
     private static GraalRuntime initializeRuntime() {
-        Services.exportJVMCITo(Graal.class);
+        Services.initializeJVMCI();
         JVMCICompiler compiler = JVMCI.getRuntime().getCompiler();
         if (compiler instanceof GraalJVMCICompiler) {
             GraalJVMCICompiler graal = (GraalJVMCICompiler) compiler;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java	Thu May 04 11:02:40 2017 +0100
@@ -53,11 +53,6 @@
     public static final ModuleAPI getModule;
 
     /**
-     * {@code jdk.internal.module.Modules.addExports(Module, String, Module)}.
-     */
-    public static final ModuleAPI addExports;
-
-    /**
      * {@code java.lang.Module.getResourceAsStream(String)}.
      */
     public static final ModuleAPI getResourceAsStream;
@@ -116,13 +111,11 @@
             try {
                 getModule = new ModuleAPI(Class.class.getMethod("getModule"));
                 Class<?> moduleClass = getModule.method.getReturnType();
-                Class<?> modulesClass = Class.forName("jdk.internal.module.Modules");
                 getResourceAsStream = new ModuleAPI(moduleClass.getMethod("getResourceAsStream", String.class));
                 canRead = new ModuleAPI(moduleClass.getMethod("canRead", moduleClass));
                 isExported = new ModuleAPI(moduleClass.getMethod("isExported", String.class));
                 isExportedTo = new ModuleAPI(moduleClass.getMethod("isExported", String.class, moduleClass));
-                addExports = new ModuleAPI(modulesClass.getDeclaredMethod("addExports", moduleClass, String.class, moduleClass));
-            } catch (NoSuchMethodException | SecurityException | ClassNotFoundException e) {
+            } catch (NoSuchMethodException | SecurityException e) {
                 throw new InternalError(e);
             }
         } else {
@@ -132,8 +125,6 @@
             canRead = unavailable;
             isExported = unavailable;
             isExportedTo = unavailable;
-            addExports = unavailable;
         }
-
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Thu May 04 11:02:40 2017 +0100
@@ -127,7 +127,7 @@
         MetaAccessProvider metaAccess = providers.getMetaAccess();
 
         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
-        Plugins plugins = new Plugins(new InvocationPlugins(metaAccess));
+        Plugins plugins = new Plugins(new InvocationPlugins());
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java	Thu May 04 11:02:40 2017 +0100
@@ -26,15 +26,14 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 
-import org.junit.Test;
-
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.test.ExportingClassLoader;
+import org.junit.Test;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
 
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java	Thu May 04 11:02:40 2017 +0100
@@ -44,19 +44,17 @@
 import java.util.ServiceLoader;
 import java.util.Set;
 
-import org.junit.Test;
-
 import org.graalvm.compiler.options.OptionDescriptor;
 import org.graalvm.compiler.options.OptionDescriptors;
 import org.graalvm.compiler.options.OptionValue;
 import org.graalvm.compiler.test.GraalTest;
-
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassVisitor;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.internal.org.objectweb.asm.Type;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
 
 /**
  * Verifies a class declaring one or more {@linkplain OptionValue options} has a class initializer
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java	Thu May 04 11:02:40 2017 +0100
@@ -83,7 +83,7 @@
         MetaAccessProvider metaAccess = providers.getMetaAccess();
 
         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
-        Plugins plugins = new Plugins(new InvocationPlugins(metaAccess));
+        Plugins plugins = new Plugins(new InvocationPlugins());
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java	Thu May 04 11:02:40 2017 +0100
@@ -24,10 +24,10 @@
 
 import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
 
 import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID;
 
@@ -86,7 +86,7 @@
         ResolvedJavaMethod method = getResolvedJavaMethod(LOADER.findClass(INNER_CLASS_NAME), name);
         try {
             StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID);
-            Plugins plugins = new Plugins(new InvocationPlugins(getMetaAccess()));
+            Plugins plugins = new Plugins(new InvocationPlugins());
             GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
             OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java	Thu May 04 11:02:40 2017 +0100
@@ -122,7 +122,7 @@
         Providers providers = rt.getHostBackend().getProviders();
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
-        Plugins plugins = new Plugins(new InvocationPlugins(metaAccess));
+        Plugins plugins = new Plugins(new InvocationPlugins());
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java	Thu May 04 11:02:40 2017 +0100
@@ -300,7 +300,7 @@
         Providers providers = rt.getHostBackend().getProviders();
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
-        Plugins plugins = new Plugins(new InvocationPlugins(metaAccess));
+        Plugins plugins = new Plugins(new InvocationPlugins());
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java	Thu May 04 11:02:40 2017 +0100
@@ -267,7 +267,7 @@
         Providers providers = rt.getHostBackend().getProviders();
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
-        Plugins plugins = new Plugins(new InvocationPlugins(metaAccess));
+        Plugins plugins = new Plugins(new InvocationPlugins());
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java	Thu May 04 11:02:40 2017 +0100
@@ -249,7 +249,7 @@
         Providers providers = rt.getHostBackend().getProviders();
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
-        Plugins plugins = new Plugins(new InvocationPlugins(metaAccess));
+        Plugins plugins = new Plugins(new InvocationPlugins());
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java	Thu May 04 11:02:40 2017 +0100
@@ -253,7 +253,7 @@
                      * the code before static analysis, the classes would otherwise be not loaded
                      * yet and the bytecode parser would only create a graph.
                      */
-                    Plugins plugins = new Plugins(new InvocationPlugins(metaAccess));
+                    Plugins plugins = new Plugins(new InvocationPlugins());
                     GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
                     /*
                      * For simplicity, we ignore all exception handling during the static analysis.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Thu May 04 11:02:40 2017 +0100
@@ -29,15 +29,12 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.stream.Collectors;
 
-import org.junit.Test;
-
 import org.graalvm.compiler.api.test.Graal;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -45,12 +42,15 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding;
 import org.graalvm.compiler.runtime.RuntimeProvider;
 import org.graalvm.compiler.test.GraalTest;
+import org.junit.Test;
 
 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
 import jdk.vm.ci.hotspot.VMIntrinsicMethod;
 import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.MetaUtil;
 import jdk.vm.ci.meta.MethodHandleAccessProvider.IntrinsicMethod;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
@@ -63,11 +63,10 @@
  */
 public class CheckGraalIntrinsics extends GraalTest {
 
-    public static boolean match(ResolvedJavaMethod method, VMIntrinsicMethod intrinsic) {
-        if (intrinsic.name.equals(method.getName())) {
-            if (intrinsic.descriptor.equals(method.getSignature().toMethodDescriptor())) {
-                String declaringClass = method.getDeclaringClass().toClassName().replace('.', '/');
-                if (declaringClass.equals(intrinsic.declaringClass)) {
+    public static boolean match(String type, Binding binding, VMIntrinsicMethod intrinsic) {
+        if (intrinsic.name.equals(binding.name)) {
+            if (intrinsic.descriptor.startsWith(binding.argumentsDescriptor)) {
+                if (type.equals(intrinsic.declaringClass)) {
                     return true;
                 }
             }
@@ -75,16 +74,20 @@
         return false;
     }
 
-    private static ResolvedJavaMethod findMethod(Set<ResolvedJavaMethod> methods, VMIntrinsicMethod intrinsic) {
-        for (ResolvedJavaMethod method : methods) {
-            if (match(method, intrinsic)) {
-                return method;
+    public static InvocationPlugin findPlugin(Map<String, List<Binding>> bindings, VMIntrinsicMethod intrinsic) {
+        for (Map.Entry<String, List<Binding>> e : bindings.entrySet()) {
+            // Match format of VMIntrinsicMethod.declaringClass
+            String type = MetaUtil.internalNameToJava(e.getKey(), true, false).replace('.', '/');
+            for (Binding binding : e.getValue()) {
+                if (match(type, binding, intrinsic)) {
+                    return binding.plugin;
+                }
             }
         }
         return null;
     }
 
-    private static ResolvedJavaMethod resolveIntrinsic(MetaAccessProvider metaAccess, VMIntrinsicMethod intrinsic) throws ClassNotFoundException {
+    public static ResolvedJavaMethod resolveIntrinsic(MetaAccessProvider metaAccess, VMIntrinsicMethod intrinsic) throws ClassNotFoundException {
         Class<?> c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader());
         for (Method javaMethod : c.getDeclaredMethods()) {
             if (javaMethod.getName().equals(intrinsic.name)) {
@@ -425,28 +428,20 @@
     public void test() throws ClassNotFoundException {
         HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class);
         HotSpotProviders providers = rt.getHostBackend().getProviders();
-        Map<ResolvedJavaMethod, Object> impl = new HashMap<>();
         Plugins graphBuilderPlugins = providers.getGraphBuilderPlugins();
         InvocationPlugins invocationPlugins = graphBuilderPlugins.getInvocationPlugins();
-        for (ResolvedJavaMethod method : invocationPlugins.getMethods()) {
-            InvocationPlugin plugin = invocationPlugins.lookupInvocation(method);
-            assert plugin != null;
-            impl.put(method, plugin);
-        }
 
-        Set<ResolvedJavaMethod> methods = invocationPlugins.getMethods();
         HotSpotVMConfigStore store = rt.getVMConfig().getStore();
         List<VMIntrinsicMethod> intrinsics = store.getIntrinsics();
 
         List<String> missing = new ArrayList<>();
+        Map<String, List<Binding>> bindings = invocationPlugins.getBindings(true);
         for (VMIntrinsicMethod intrinsic : intrinsics) {
-            ResolvedJavaMethod method = findMethod(methods, intrinsic);
-            if (method == null) {
-                method = resolveIntrinsic(providers.getMetaAccess(), intrinsic);
-
-                IntrinsicMethod intrinsicMethod = null;
+            InvocationPlugin plugin = findPlugin(bindings, intrinsic);
+            if (plugin == null) {
+                ResolvedJavaMethod method = resolveIntrinsic(providers.getMetaAccess(), intrinsic);
                 if (method != null) {
-                    intrinsicMethod = providers.getConstantReflection().getMethodHandleAccess().lookupMethodHandleIntrinsic(method);
+                    IntrinsicMethod intrinsicMethod = providers.getConstantReflection().getMethodHandleAccess().lookupMethodHandleIntrinsic(method);
                     if (intrinsicMethod != null) {
                         continue;
                     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java	Thu May 04 11:02:40 2017 +0100
@@ -39,9 +39,9 @@
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements Opcodes {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java	Thu May 04 11:02:40 2017 +0100
@@ -22,13 +22,12 @@
  */
 package org.graalvm.compiler.hotspot.test;
 
+import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID;
+
 import java.util.List;
-import java.util.Set;
-
-import org.junit.Test;
+import java.util.Map;
 
 import org.graalvm.compiler.api.test.Graal;
-import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -37,8 +36,10 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding;
 import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
 import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.junit.Test;
 
 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
 import jdk.vm.ci.hotspot.VMIntrinsicMethod;
@@ -50,46 +51,27 @@
  */
 public class TestIntrinsicCompiles extends GraalCompilerTest {
 
-    private static boolean match(ResolvedJavaMethod method, VMIntrinsicMethod intrinsic) {
-        if (intrinsic.name.equals(method.getName())) {
-            if (intrinsic.descriptor.equals(method.getSignature().toMethodDescriptor())) {
-                String declaringClass = method.getDeclaringClass().toClassName().replace('.', '/');
-                if (declaringClass.equals(intrinsic.declaringClass)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private static ResolvedJavaMethod findMethod(Set<ResolvedJavaMethod> methods, VMIntrinsicMethod intrinsic) {
-        for (ResolvedJavaMethod method : methods) {
-            if (match(method, intrinsic)) {
-                return method;
-            }
-        }
-        return null;
-    }
-
     @Test
     @SuppressWarnings("try")
-    public void test() {
+    public void test() throws ClassNotFoundException {
         HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) JVMCI.getRuntime().getCompiler();
         HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class);
         HotSpotProviders providers = rt.getHostBackend().getProviders();
         Plugins graphBuilderPlugins = providers.getGraphBuilderPlugins();
         InvocationPlugins invocationPlugins = graphBuilderPlugins.getInvocationPlugins();
 
-        Set<ResolvedJavaMethod> pluginMethods = invocationPlugins.getMethods();
+        Map<String, List<Binding>> bindings = invocationPlugins.getBindings(true);
         HotSpotVMConfigStore store = rt.getVMConfig().getStore();
         List<VMIntrinsicMethod> intrinsics = store.getIntrinsics();
         for (VMIntrinsicMethod intrinsic : intrinsics) {
-            ResolvedJavaMethod method = findMethod(pluginMethods, intrinsic);
-            if (method != null) {
-                InvocationPlugin plugin = invocationPlugins.lookupInvocation(method);
-                if (plugin instanceof MethodSubstitutionPlugin && !method.isNative()) {
-                    StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, CompilationIdentifier.INVALID_COMPILATION_ID);
-                    getCode(method, graph);
+            InvocationPlugin plugin = CheckGraalIntrinsics.findPlugin(bindings, intrinsic);
+            if (plugin != null) {
+                if (plugin instanceof MethodSubstitutionPlugin) {
+                    ResolvedJavaMethod method = CheckGraalIntrinsics.resolveIntrinsic(getMetaAccess(), intrinsic);
+                    if (!method.isNative()) {
+                        StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, INVALID_COMPILATION_ID);
+                        getCode(method, graph);
+                    }
                 }
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java	Thu May 04 11:02:40 2017 +0100
@@ -102,7 +102,6 @@
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.runtime.JVMCI;
 import jdk.vm.ci.runtime.JVMCICompiler;
-import jdk.vm.ci.services.Services;
 
 /**
  * This class implements compile-the-world functionality with JVMCI.
@@ -785,7 +784,6 @@
     }
 
     public static void main(String[] args) throws Throwable {
-        Services.exportJVMCITo(CompileTheWorld.class);
         HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) HotSpotJVMCIRuntime.runtime().getCompiler();
         compiler.compileTheWorld();
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Thu May 04 11:02:40 2017 +0100
@@ -22,21 +22,19 @@
  */
 package org.graalvm.compiler.hotspot;
 
-import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier;
+import static jdk.vm.ci.common.InitTimer.timer;
 import static org.graalvm.compiler.options.OptionValue.PROFILE_OPTIONVALUE_PROPERTY_NAME;
-import static jdk.vm.ci.common.InitTimer.timer;
 
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintStream;
-import java.lang.reflect.Field;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.ServiceLoader;
 
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.MethodFilter;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionDescriptors;
@@ -46,10 +44,11 @@
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 
 import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotSignature;
-import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
 import jdk.vm.ci.runtime.JVMCIRuntime;
+import jdk.vm.ci.services.Services;
 
 public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory {
 
@@ -135,8 +134,8 @@
         if (allOptionsSettings == null) {
             try (InitTimer t = timer("InitializeOptions")) {
                 ServiceLoader<OptionDescriptors> loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader());
-                Properties savedProps = getSavedProperties(Java8OrEarlier);
-                String optionsFile = savedProps.getProperty(GRAAL_OPTIONS_FILE_PROPERTY_NAME);
+                Map<String, String> savedProps = Services.getSavedProperties();
+                String optionsFile = savedProps.get(GRAAL_OPTIONS_FILE_PROPERTY_NAME);
 
                 if (optionsFile != null) {
                     File graalOptions = new File(optionsFile);
@@ -165,15 +164,15 @@
                 }
 
                 Map<String, String> optionSettings = new HashMap<>();
-                for (Map.Entry<Object, Object> e : savedProps.entrySet()) {
-                    String name = (String) e.getKey();
+                for (Entry<String, String> e : savedProps.entrySet()) {
+                    String name = e.getKey();
                     if (name.startsWith(GRAAL_OPTION_PROPERTY_PREFIX)) {
                         if (name.equals("graal.PrintFlags") || name.equals("graal.ShowFlags")) {
                             System.err.println("The " + name + " option has been removed and will be ignored. Use -XX:+JVMCIPrintProperties instead.");
                         } else if (name.equals(GRAAL_OPTIONS_FILE_PROPERTY_NAME) || name.equals(GRAAL_VERSION_PROPERTY_NAME) || name.equals(PROFILE_OPTIONVALUE_PROPERTY_NAME)) {
                             // Ignore well known properties that do not denote an option
                         } else {
-                            String value = (String) e.getValue();
+                            String value = e.getValue();
                             optionSettings.put(name.substring(GRAAL_OPTION_PROPERTY_PREFIX.length()), value);
                         }
                     }
@@ -206,18 +205,6 @@
         }
     }
 
-    private static Properties getSavedProperties(boolean jdk8OrEarlier) {
-        try {
-            String vmClassName = jdk8OrEarlier ? "sun.misc.VM" : "jdk.internal.misc.VM";
-            Class<?> vmClass = Class.forName(vmClassName);
-            Field savedPropsField = vmClass.getDeclaredField("savedProps");
-            savedPropsField.setAccessible(true);
-            return (Properties) savedPropsField.get(null);
-        } catch (Exception e) {
-            throw new GraalError(e);
-        }
-    }
-
     @Override
     public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) {
         HotSpotGraalCompiler compiler = createCompiler(runtime, CompilerConfigurationFactory.selectFactory(null));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java	Thu May 04 11:02:40 2017 +0100
@@ -22,10 +22,6 @@
  */
 package org.graalvm.compiler.hotspot;
 
-import static org.graalvm.compiler.core.common.util.ModuleAPI.addExports;
-import static org.graalvm.compiler.core.common.util.ModuleAPI.getModule;
-import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERSION;
-
 import org.graalvm.compiler.serviceprovider.ServiceProvider;
 
 import jdk.vm.ci.hotspot.HotSpotVMEventListener;
@@ -35,43 +31,45 @@
 @ServiceProvider(JVMCIServiceLocator.class)
 public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator {
 
-    private boolean exportsAdded;
+    /**
+     * Holds the state shared between all {@link HotSpotGraalJVMCIServiceLocator} instances. This is
+     * necessary as a service provider instance is created each time the service is loaded.
+     */
+    private static final class Shared {
+        static final Shared SINGLETON = new Shared();
 
-    /**
-     * Dynamically exports various internal JDK packages to the Graal module. This requires only
-     * {@code --add-exports=java.base/jdk.internal.module=org.graalvm.compiler.graal_core} on the VM
-     * command line instead of a {@code --add-exports} instance for each JDK internal package used
-     * by Graal.
-     */
-    private void addExports() {
-        if (JAVA_SPECIFICATION_VERSION >= 9 && !exportsAdded) {
-            Object javaBaseModule = getModule.invoke(String.class);
-            Object graalModule = getModule.invoke(getClass());
-            addExports.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule);
-            addExports.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule);
-            addExports.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule);
-            exportsAdded = true;
+        <T> T getProvider(Class<T> service, HotSpotGraalJVMCIServiceLocator locator) {
+            if (service == JVMCICompilerFactory.class) {
+                return service.cast(new HotSpotGraalCompilerFactory(locator));
+            } else if (service == HotSpotVMEventListener.class) {
+                if (graalRuntime != null) {
+                    return service.cast(new HotSpotGraalVMEventListener(graalRuntime));
+                }
+            }
+            return null;
+        }
+
+        private HotSpotGraalRuntime graalRuntime;
+
+        /**
+         * Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
+         */
+        void onCompilerCreation(HotSpotGraalCompiler compiler) {
+            assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created";
+            this.graalRuntime = (HotSpotGraalRuntime) compiler.getGraalRuntime();
         }
     }
 
-    private HotSpotGraalRuntime graalRuntime;
-
     @Override
     public <T> T getProvider(Class<T> service) {
-        if (service == JVMCICompilerFactory.class) {
-            addExports();
-            return service.cast(new HotSpotGraalCompilerFactory(this));
-        } else if (service == HotSpotVMEventListener.class) {
-            if (graalRuntime != null) {
-                addExports();
-                return service.cast(new HotSpotGraalVMEventListener(graalRuntime));
-            }
-        }
-        return null;
+        return Shared.SINGLETON.getProvider(service, this);
     }
 
-    public void onCompilerCreation(HotSpotGraalCompiler compiler) {
-        assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created";
-        this.graalRuntime = (HotSpotGraalRuntime) compiler.getGraalRuntime();
+    /**
+     * Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
+     */
+    @SuppressWarnings("static-method")
+    void onCompilerCreation(HotSpotGraalCompiler compiler) {
+        Shared.SINGLETON.onCompilerCreation(compiler);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu May 04 11:02:40 2017 +0100
@@ -128,7 +128,7 @@
      */
     public static Plugins create(GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection,
                     SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements) {
-        InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess);
+        InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config);
 
         Plugins plugins = new Plugins(invocationPlugins);
         NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java	Thu May 04 11:02:40 2017 +0100
@@ -38,7 +38,6 @@
 import org.graalvm.compiler.replacements.nodes.MacroNode;
 
 import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
@@ -47,8 +46,7 @@
 final class HotSpotInvocationPlugins extends InvocationPlugins {
     final GraalHotSpotVMConfig config;
 
-    HotSpotInvocationPlugins(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) {
-        super(metaAccess);
+    HotSpotInvocationPlugins(GraalHotSpotVMConfig config) {
         this.config = config;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java	Thu May 04 11:02:40 2017 +0100
@@ -29,8 +29,6 @@
 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
 
-import java.lang.reflect.Field;
-
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.core.common.LocationIdentity;
@@ -61,7 +59,7 @@
     static final long kOffset;
     static final long lastKeyOffset;
     static final Class<?> AESCryptClass;
-    static final int AES_BLOCK_SIZE;
+    static final int AES_BLOCK_SIZE_IN_BYTES;
 
     static {
         try {
@@ -72,9 +70,9 @@
             AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl);
             kOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("K"));
             lastKeyOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("lastKey"));
-            Field aesBlockSizeField = Class.forName("com.sun.crypto.provider.AESConstants", true, cl).getDeclaredField("AES_BLOCK_SIZE");
-            aesBlockSizeField.setAccessible(true);
-            AES_BLOCK_SIZE = aesBlockSizeField.getInt(null);
+            // Thankfully the AES block size is a constant (128 bits) and so we don't need to
+            // reflect on com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE.
+            AES_BLOCK_SIZE_IN_BYTES = 16;
         } catch (Exception ex) {
             throw new GraalError(ex);
         }
@@ -141,7 +139,7 @@
      * Perform null and array bounds checks for arguments to a cipher operation.
      */
     static void checkArgs(byte[] in, int inOffset, byte[] out, int outOffset) {
-        if (probability(VERY_SLOW_PATH_PROBABILITY, inOffset < 0 || in.length - AES_BLOCK_SIZE < inOffset || outOffset < 0 || out.length - AES_BLOCK_SIZE < outOffset)) {
+        if (probability(VERY_SLOW_PATH_PROBABILITY, inOffset < 0 || in.length - AES_BLOCK_SIZE_IN_BYTES < inOffset || outOffset < 0 || out.length - AES_BLOCK_SIZE_IN_BYTES < outOffset)) {
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java	Thu May 04 11:02:40 2017 +0100
@@ -57,7 +57,7 @@
         return config.crcTableAddress;
     }
 
-    @MethodSubstitution
+    @MethodSubstitution(optional = true)
     static int update(int crc, int b) {
         final long crcTableRawAddress = GraalHotSpotVMConfigNode.crcTableAddress();
 
@@ -69,7 +69,7 @@
         return ~result;
     }
 
-    @MethodSubstitution
+    @MethodSubstitution(optional = true)
     static int updateBytes(int crc, byte[] buf, int off, int len) {
         Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off));
         return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len);
@@ -84,7 +84,7 @@
         return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len);
     }
 
-    @MethodSubstitution
+    @MethodSubstitution(optional = true)
     static int updateByteBuffer(int crc, long addr, int off, int len) {
         Word bufAddr = Word.unsigned(addr).add(off);
         return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java	Thu May 04 11:02:40 2017 +0100
@@ -45,7 +45,7 @@
 @ClassSubstitution(Thread.class)
 public class ThreadSubstitutions {
 
-    @MethodSubstitution(isStatic = false)
+    @MethodSubstitution(isStatic = false, optional = true)
     public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
         Word javaThread = CurrentJavaThreadNode.get();
         Object thread = javaThread.readObject(threadObjectOffset(INJECTED_VMCONFIG), JAVA_THREAD_THREAD_OBJECT_LOCATION);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java	Thu May 04 11:02:40 2017 +0100
@@ -40,8 +40,7 @@
 
     /**
      * The receiver in a non-static method. The class literal for this interface must be used with
-     * {@link InvocationPlugins#put(InvocationPlugin, boolean, boolean, boolean, Class, String, Class...)}
-     * to denote the receiver argument for such a non-static method.
+     * {@link InvocationPlugins#put} to denote the receiver argument for such a non-static method.
      */
     public interface Receiver {
         /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Thu May 04 11:02:40 2017 +0100
@@ -23,8 +23,9 @@
 package org.graalvm.compiler.nodes.graphbuilderconf;
 
 import static java.lang.String.format;
+import static org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.LateClassPlugins.CLOSED_LATE_CLASS_PLUGIN;
 
-import java.lang.reflect.Executable;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
@@ -32,10 +33,8 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitutionRegistry;
@@ -46,12 +45,24 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
 
-import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.MetaUtil;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
 
 /**
  * Manages a set of {@link InvocationPlugin}s.
+ *
+ * Most plugins are registered during initialization (i.e., before
+ * {@link #lookupInvocation(ResolvedJavaMethod)} or {@link #getBindings} is called). These
+ * registrations can be made with {@link Registration},
+ * {@link #register(InvocationPlugin, String, String, Type...)},
+ * {@link #register(InvocationPlugin, Type, String, Type...)} or
+ * {@link #registerOptional(InvocationPlugin, Type, String, Type...)}. Initialization is not
+ * thread-safe and so must only be performed by a single thread.
+ *
+ * Plugins that are not guaranteed to be made during initialization must use
+ * {@link LateRegistration}.
  */
 public class InvocationPlugins {
 
@@ -260,6 +271,26 @@
         }
 
         /**
+         * Registers a plugin for a method with 6 arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void register6(String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, InvocationPlugin plugin) {
+            plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6);
+        }
+
+        /**
+         * Registers a plugin for a method with 7 arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void register7(String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, Type arg7, InvocationPlugin plugin) {
+            plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+        }
+
+        /**
          * Registers a plugin for an optional method with no arguments.
          *
          * @param name the name of the method
@@ -337,168 +368,151 @@
          */
         @Override
         public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, String substituteName, Type... argumentTypes) {
+            MethodSubstitutionPlugin plugin = createMethodSubstitution(substituteDeclaringClass, substituteName, argumentTypes);
+            plugins.register(plugin, false, allowOverwrite, declaringType, name, argumentTypes);
+        }
+
+        public MethodSubstitutionPlugin createMethodSubstitution(Class<?> substituteDeclaringClass, String substituteName, Type... argumentTypes) {
             assert methodSubstitutionBytecodeProvider != null : "Registration used for method substitutions requires a non-null methodSubstitutionBytecodeProvider";
             MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(methodSubstitutionBytecodeProvider, substituteDeclaringClass, substituteName, argumentTypes);
-            plugins.register(plugin, false, allowOverwrite, declaringType, name, argumentTypes);
+            return plugin;
+        }
+
+    }
+
+    /**
+     * Utility for registering plugins after Graal may have been initialized. Registrations made via
+     * this class are not finalized until {@link #close} is called.
+     */
+    public static class LateRegistration implements AutoCloseable {
+
+        private InvocationPlugins plugins;
+        private final List<Binding> bindings = new ArrayList<>();
+        private final Type declaringType;
+
+        /**
+         * Creates an object for registering {@link InvocationPlugin}s for methods declared by a
+         * given class.
+         *
+         * @param plugins where to register the plugins
+         * @param declaringType the class declaring the methods for which plugins will be registered
+         *            via this object
+         */
+        public LateRegistration(InvocationPlugins plugins, Type declaringType) {
+            this.plugins = plugins;
+            this.declaringType = declaringType;
+        }
+
+        /**
+         * Registers an invocation plugin for a given method. There must be no plugin currently
+         * registered for {@code method}.
+         *
+         * @param argumentTypes the argument types of the method. Element 0 of this array must be
+         *            the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method
+         *            is non-static. Upon returning, element 0 will have been rewritten to
+         *            {@code declaringClass}
+         */
+        public void register(InvocationPlugin plugin, String name, Type... argumentTypes) {
+            boolean isStatic = argumentTypes.length == 0 || argumentTypes[0] != InvocationPlugin.Receiver.class;
+            if (!isStatic) {
+                argumentTypes[0] = declaringType;
+            }
+
+            assert isStatic || argumentTypes[0] == declaringType;
+            Binding binding = new Binding(plugin, isStatic, name, argumentTypes);
+            bindings.add(binding);
+
+            assert Checks.check(this.plugins, declaringType, binding);
+            assert Checks.checkResolvable(false, declaringType, binding);
+        }
+
+        @Override
+        public void close() {
+            assert plugins != null : String.format("Late registrations of invocation plugins for %s is already closed", declaringType);
+            plugins.registerLate(declaringType, bindings);
+            plugins = null;
         }
     }
 
     /**
-     * Key for a {@linkplain ClassPlugins#entries resolved} plugin registration. Due to the
-     * possibility of class redefinition, we cannot directly use {@link ResolvedJavaMethod}s as
-     * keys. A {@link ResolvedJavaMethod} implementation might implement {@code equals()} and
-     * {@code hashCode()} based on internal representation subject to change by class redefinition.
+     * Associates an {@link InvocationPlugin} with the details of a method it substitutes.
      */
-    static final class ResolvedJavaMethodKey {
-        private final ResolvedJavaMethod method;
+    public static class Binding {
+        /**
+         * The plugin this binding is for.
+         */
+        public final InvocationPlugin plugin;
 
-        ResolvedJavaMethodKey(ResolvedJavaMethod method) {
-            this.method = method;
+        /**
+         * Specifies if the associated method is static.
+         */
+        public final boolean isStatic;
+
+        /**
+         * The name of the associated method.
+         */
+        public final String name;
+
+        /**
+         * A partial
+         * <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
+         * descriptor</a> for the associated method. The descriptor includes enclosing {@code '('}
+         * and {@code ')'} characters but omits the return type suffix.
+         */
+        public final String argumentsDescriptor;
+
+        /**
+         * Link in a list of bindings.
+         */
+        private Binding next;
+
+        Binding(InvocationPlugin data, boolean isStatic, String name, Type... argumentTypes) {
+            this.plugin = data;
+            this.isStatic = isStatic;
+            this.name = name;
+            StringBuilder buf = new StringBuilder();
+            buf.append('(');
+            for (int i = isStatic ? 0 : 1; i < argumentTypes.length; i++) {
+                buf.append(MetaUtil.toInternalName(argumentTypes[i].getTypeName()));
+            }
+            buf.append(')');
+            this.argumentsDescriptor = buf.toString();
+            assert !name.equals("<init>") || !isStatic : this;
         }
 
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof ResolvedJavaMethodKey) {
-                ResolvedJavaMethodKey that = (ResolvedJavaMethodKey) obj;
-                if (this.method.isStatic() == that.method.isStatic()) {
-                    if (this.method.getDeclaringClass().equals(that.method.getDeclaringClass())) {
-                        if (this.method.getName().equals(that.method.getName())) {
-                            if (this.method.getSignature().equals(that.method.getSignature())) {
-                                return true;
-                            }
-                        }
-                    }
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return this.method.getName().hashCode();
+        Binding(ResolvedJavaMethod resolved, InvocationPlugin data) {
+            this.plugin = data;
+            this.isStatic = resolved.isStatic();
+            this.name = resolved.getName();
+            Signature sig = resolved.getSignature();
+            String desc = sig.toMethodDescriptor();
+            assert desc.indexOf(')') != -1 : desc;
+            this.argumentsDescriptor = desc.substring(0, desc.indexOf(')') + 1);
+            assert !name.equals("<init>") || !isStatic : this;
         }
 
         @Override
         public String toString() {
-            return "ResolvedJavaMethodKey<" + method + ">";
+            return name + argumentsDescriptor;
         }
     }
 
     /**
-     * Key for {@linkplain ClassPlugins#registrations registering} an {@link InvocationPlugin} for a
-     * specific method.
+     * Plugin registrations for already resolved methods. If non-null, then {@link #registrations}
+     * is null and no further registrations can be made.
      */
-    static class MethodKey {
-        final boolean isStatic;
-
-        /**
-         * This method is optional. This is used for new API methods not present in previous JDK
-         * versions.
-         */
-        final boolean isOptional;
-
-        final String name;
-        final Type[] argumentTypes;
-        final InvocationPlugin value;
-
-        /**
-         * Used to lazily initialize {@link #resolved}.
-         */
-        private final MetaAccessProvider metaAccess;
-
-        private volatile ResolvedJavaMethod resolved;
-
-        MethodKey(MetaAccessProvider metaAccess, InvocationPlugin data, boolean isStatic, boolean isOptional, String name, Type... argumentTypes) {
-            this.metaAccess = metaAccess;
-            this.value = data;
-            this.isStatic = isStatic;
-            this.isOptional = isOptional;
-            this.name = name;
-            this.argumentTypes = argumentTypes;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof MethodKey) {
-                MethodKey that = (MethodKey) obj;
-                boolean res = this.name.equals(that.name) && areEqual(this.argumentTypes, that.argumentTypes);
-                assert !res || this.isStatic == that.isStatic;
-                return res;
-            }
-            return false;
-        }
-
-        private static boolean areEqual(Type[] args1, Type[] args2) {
-            if (args1.length == args2.length) {
-                for (int i = 0; i < args1.length; i++) {
-                    if (!args1[i].getTypeName().equals(args2[i].getTypeName())) {
-                        return false;
-                    }
-                }
-                return true;
-            }
-            return false;
-        }
-
-        public int getDeclaredParameterCount() {
-            return isStatic ? argumentTypes.length : argumentTypes.length - 1;
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-
-        private ResolvedJavaMethod resolve(Class<?> declaringClass) {
-            if (resolved == null) {
-                Executable method = resolveJava(declaringClass);
-                if (method == null) {
-                    return null;
-                }
-                resolved = metaAccess.lookupJavaMethod(method);
-            }
-            return resolved;
-        }
-
-        private Executable resolveJava(Class<?> declaringClass) {
-            try {
-                Executable res;
-                Class<?>[] parameterTypes = resolveTypes(argumentTypes, isStatic ? 0 : 1, argumentTypes.length);
-                if (name.equals("<init>")) {
-                    res = declaringClass.getDeclaredConstructor(parameterTypes);
-                } else {
-                    res = declaringClass.getDeclaredMethod(name, parameterTypes);
-                }
-                assert Modifier.isStatic(res.getModifiers()) == isStatic : res;
-                return res;
-            } catch (NoSuchMethodException | SecurityException e) {
-                if (isOptional) {
-                    return null;
-                }
-                throw new InternalError(e);
-            }
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder(name).append('(');
-            for (Type p : argumentTypes) {
-                if (sb.charAt(sb.length() - 1) != '(') {
-                    sb.append(", ");
-                }
-                sb.append(p.getTypeName());
-            }
-            return sb.append(')').toString();
-        }
-    }
-
-    private final MetaAccessProvider metaAccess;
-
-    private final Map<String, ClassPlugins> registrations = new HashMap<>();
+    private final Map<ResolvedJavaMethod, InvocationPlugin> resolvedRegistrations;
 
     /**
-     * Deferred registrations as well as guard for initialization. The guard uses double-checked
-     * locking which is why this field is {@code volatile}.
+     * Map from class names in {@linkplain MetaUtil#toInternalName(String) internal} form to the
+     * invocation plugin bindings for the class. Tf non-null, then {@link #resolvedRegistrations}
+     * will be null.
+     */
+    private final Map<String, ClassPlugins> registrations;
+
+    /**
+     * Deferred registrations as well as the guard for delimiting the initial registration phase.
+     * The guard uses double-checked locking which is why this field is {@code volatile}.
      */
     private volatile List<Runnable> deferredRegistrations = new ArrayList<>();
 
@@ -512,119 +526,159 @@
     }
 
     /**
-     * Per-class invocation plugins.
+     * Support for registering plugins once this object may be accessed by multiple threads.
      */
-    protected static class ClassPlugins {
-        private final Type declaringType;
+    private volatile LateClassPlugins lateRegistrations;
 
-        private final List<MethodKey> registrations = new ArrayList<>();
+    /**
+     * Per-class bindings.
+     */
+    static class ClassPlugins {
 
-        public ClassPlugins(Type declaringClass) {
-            this.declaringType = declaringClass;
+        /**
+         * Maps method names to binding lists.
+         */
+        private final Map<String, Binding> bindings = new HashMap<>();
+
+        /**
+         * Gets the invocation plugin for a given method.
+         *
+         * @return the invocation plugin for {@code method} or {@code null}
+         */
+        InvocationPlugin get(ResolvedJavaMethod method) {
+            assert !method.isBridge();
+            Binding binding = bindings.get(method.getName());
+            while (binding != null) {
+                if (method.isStatic() == binding.isStatic) {
+                    if (method.getSignature().toMethodDescriptor().startsWith(binding.argumentsDescriptor)) {
+                        return binding.plugin;
+                    }
+                }
+                binding = binding.next;
+            }
+            return null;
+        }
+
+        public void register(Binding binding, boolean allowOverwrite) {
+            if (allowOverwrite) {
+                if (lookup(binding) != null) {
+                    register(binding);
+                    return;
+                }
+            } else {
+                assert lookup(binding) == null : "a value is already registered for " + binding;
+            }
+            register(binding);
+        }
+
+        InvocationPlugin lookup(Binding binding) {
+            Binding b = bindings.get(binding.name);
+            while (b != null) {
+                if (b.isStatic == binding.isStatic && b.argumentsDescriptor.equals(binding.argumentsDescriptor)) {
+                    return b.plugin;
+                }
+                b = b.next;
+            }
+            return null;
         }
 
         /**
-         * Entry map that is initialized upon first call to {@link #get(ResolvedJavaMethod)}.
-         *
-         * Note: this must be volatile as threads may race to initialize it.
+         * Registers {@code binding}.
          */
-        private volatile Map<ResolvedJavaMethodKey, InvocationPlugin> entries;
+        void register(Binding binding) {
+            Binding head = bindings.get(binding.name);
+            assert binding.next == null;
+            binding.next = head;
+            bindings.put(binding.name, binding);
+        }
+    }
 
-        void initializeMap() {
-            if (!isClosed()) {
-                if (registrations.isEmpty()) {
-                    entries = Collections.emptyMap();
-                } else {
-                    Class<?> declaringClass = resolveType(declaringType, true);
-                    if (declaringClass == null) {
-                        // An optional type that could not be resolved
-                        entries = Collections.emptyMap();
-                    } else {
-                        Map<ResolvedJavaMethodKey, InvocationPlugin> newEntries = new HashMap<>();
-                        for (MethodKey methodKey : registrations) {
-                            ResolvedJavaMethod m = methodKey.resolve(declaringClass);
-                            if (m != null) {
-                                newEntries.put(new ResolvedJavaMethodKey(m), methodKey.value);
-                                if (entries != null) {
-                                    // Another thread finished initializing entries first
-                                    return;
-                                }
-                            }
-                        }
-                        entries = newEntries;
-                    }
-                }
-            }
-        }
+    static class LateClassPlugins extends ClassPlugins {
+        static final String CLOSED_LATE_CLASS_PLUGIN = "-----";
+        private final String className;
+        private final LateClassPlugins next;
 
-        public InvocationPlugin get(ResolvedJavaMethod method) {
-            if (!isClosed()) {
-                initializeMap();
-            }
-            return entries.get(new ResolvedJavaMethodKey(method));
-        }
-
-        public void register(MethodKey methodKey, boolean allowOverwrite) {
-            assert !isClosed() : "registration is closed: " + methodKey + " " + Arrays.toString(entries.keySet().toArray());
-            if (allowOverwrite) {
-                int index = registrations.indexOf(methodKey);
-                if (index >= 0) {
-                    registrations.set(index, methodKey);
-                    return;
-                }
-            } else {
-                assert !registrations.contains(methodKey) : "a value is already registered for " + declaringType + "." + methodKey;
-            }
-            registrations.add(methodKey);
-        }
-
-        public boolean isClosed() {
-            return entries != null;
+        LateClassPlugins(LateClassPlugins next, String className) {
+            assert next == null || next.className != CLOSED_LATE_CLASS_PLUGIN : "Late registration of invocation plugins is closed";
+            this.next = next;
+            this.className = className;
         }
     }
 
     /**
-     * Adds an entry to this map for a specified method.
+     * Registers a binding of a method to an invocation plugin.
      *
-     * @param value value to be associated with the specified method
+     * @param plugin invocation plugin to be associated with the specified method
      * @param isStatic specifies if the method is static
-     * @param isOptional specifies if the method is optional
      * @param declaringClass the class declaring the method
      * @param name the name of the method
      * @param argumentTypes the argument types of the method. Element 0 of this array must be
      *            {@code declaringClass} iff the method is non-static.
      * @return an object representing the method
      */
-    MethodKey put(InvocationPlugin value, boolean isStatic, boolean isOptional, boolean allowOverwrite, Type declaringClass, String name, Type... argumentTypes) {
+    Binding put(InvocationPlugin plugin, boolean isStatic, boolean allowOverwrite, Type declaringClass, String name, Type... argumentTypes) {
+        assert resolvedRegistrations == null : "registration is closed";
+        String internalName = MetaUtil.toInternalName(declaringClass.getTypeName());
         assert isStatic || argumentTypes[0] == declaringClass;
+        assert deferredRegistrations != null : "initial registration is closed - use " + LateRegistration.class.getName() + " for late registrations";
 
-        String internalName = MetaUtil.toInternalName(declaringClass.getTypeName());
         ClassPlugins classPlugins = registrations.get(internalName);
         if (classPlugins == null) {
-            classPlugins = new ClassPlugins(declaringClass);
+            classPlugins = new ClassPlugins();
             registrations.put(internalName, classPlugins);
         }
-        assert isStatic || argumentTypes[0] == declaringClass;
-        MethodKey methodKey = new MethodKey(metaAccess, value, isStatic, isOptional, name, argumentTypes);
-        classPlugins.register(methodKey, allowOverwrite);
-        return methodKey;
+        Binding binding = new Binding(plugin, isStatic, name, argumentTypes);
+        classPlugins.register(binding, allowOverwrite);
+        return binding;
+    }
+
+    InvocationPlugin get(ResolvedJavaMethod method) {
+        if (resolvedRegistrations != null) {
+            return resolvedRegistrations.get(method);
+        } else {
+            if (!method.isBridge()) {
+                ResolvedJavaType declaringClass = method.getDeclaringClass();
+                flushDeferrables();
+                String internalName = declaringClass.getName();
+                ClassPlugins classPlugins = registrations.get(internalName);
+                InvocationPlugin res = null;
+                if (classPlugins != null) {
+                    res = classPlugins.get(method);
+                }
+                if (res == null) {
+                    LateClassPlugins lcp = findLateClassPlugins(internalName);
+                    if (lcp != null) {
+                        res = lcp.get(method);
+                    }
+                }
+                if (res != null) {
+                    if (canBeIntrinsified(declaringClass)) {
+                        return res;
+                    }
+                }
+            } else {
+                // Supporting plugins for bridge methods would require including
+                // the return type in the registered signature. Until needed,
+                // this extra complexity is best avoided.
+            }
+        }
+        return null;
     }
 
     /**
-     * Determines if a method denoted by a given {@link MethodKey} is in this map.
+     * Determines if methods in a given class can have invocation plugins.
+     *
+     * @param declaringClass the class to test
      */
-    boolean containsKey(Type declaringType, MethodKey key) {
-        String internalName = MetaUtil.toInternalName(declaringType.getTypeName());
-        ClassPlugins classPlugins = registrations.get(internalName);
-        return classPlugins != null && classPlugins.registrations.contains(key);
+    protected boolean canBeIntrinsified(ResolvedJavaType declaringClass) {
+        return true;
     }
 
-    InvocationPlugin get(ResolvedJavaMethod method) {
-        flushDeferrables();
-        String internalName = method.getDeclaringClass().getName();
-        ClassPlugins classPlugins = registrations.get(internalName);
-        if (classPlugins != null) {
-            return classPlugins.get(method);
+    LateClassPlugins findLateClassPlugins(String internalClassName) {
+        for (LateClassPlugins lcp = lateRegistrations; lcp != null; lcp = lcp.next) {
+            if (lcp.className.equals(internalClassName)) {
+                return lcp;
+            }
         }
         return null;
     }
@@ -639,25 +693,39 @@
                     deferredRegistrations = null;
                 }
             }
-            for (Map.Entry<String, ClassPlugins> e : registrations.entrySet()) {
-                e.getValue().initializeMap();
-            }
         }
     }
 
+    synchronized void registerLate(Type declaringType, List<Binding> bindings) {
+        String internalName = MetaUtil.toInternalName(declaringType.getTypeName());
+        assert findLateClassPlugins(internalName) == null : "Cannot have more than one late registration of invocation plugins for " + internalName;
+        LateClassPlugins lateClassPlugins = new LateClassPlugins(lateRegistrations, internalName);
+        for (Binding b : bindings) {
+            lateClassPlugins.register(b);
+        }
+        lateRegistrations = lateClassPlugins;
+    }
+
+    private synchronized boolean closeLateRegistrations() {
+        if (lateRegistrations == null || lateRegistrations.className != CLOSED_LATE_CLASS_PLUGIN) {
+            lateRegistrations = new LateClassPlugins(lateRegistrations, CLOSED_LATE_CLASS_PLUGIN);
+        }
+        return true;
+    }
+
     /**
-     * Disallows new registrations of new plugins, and creates the internal tables for method
-     * lookup.
+     * Processes deferred registrations and then closes this object for future registration.
      */
     public void closeRegistration() {
+        assert closeLateRegistrations();
         flushDeferrables();
-        for (Map.Entry<String, ClassPlugins> e : registrations.entrySet()) {
-            e.getValue().initializeMap();
-        }
     }
 
-    public int size() {
-        return registrations.size();
+    public boolean isEmpty() {
+        if (resolvedRegistrations != null) {
+            return resolvedRegistrations.isEmpty();
+        }
+        return registrations.size() == 0 && lateRegistrations == null;
     }
 
     /**
@@ -666,47 +734,39 @@
      */
     protected final InvocationPlugins parent;
 
-    private InvocationPlugins(InvocationPlugins parent, MetaAccessProvider metaAccess) {
-        this.metaAccess = metaAccess;
-        InvocationPlugins p = parent;
-        this.parent = p;
+    /**
+     * Creates a set of invocation plugins with no parent.
+     */
+    public InvocationPlugins() {
+        this(null);
     }
 
     /**
-     * Creates a set of invocation plugins with a non-null {@linkplain #getParent() parent}.
+     * Creates a set of invocation plugins.
+     *
+     * @param parent if non-null, this object will be searched first when looking up plugins
      */
     public InvocationPlugins(InvocationPlugins parent) {
-        this(parent, parent.getMetaAccess());
+        InvocationPlugins p = parent;
+        this.parent = p;
+        this.registrations = new HashMap<>();
+        this.resolvedRegistrations = null;
     }
 
-    public InvocationPlugins(Map<ResolvedJavaMethod, InvocationPlugin> plugins, InvocationPlugins parent, MetaAccessProvider metaAccess) {
-        this.metaAccess = metaAccess;
+    /**
+     * Creates a closed set of invocation plugins for a set of resolved methods. Such an object
+     * cannot have further plugins registered.
+     */
+    public InvocationPlugins(Map<ResolvedJavaMethod, InvocationPlugin> plugins, InvocationPlugins parent) {
         this.parent = parent;
-
+        this.registrations = null;
         this.deferredRegistrations = null;
+        Map<ResolvedJavaMethod, InvocationPlugin> map = new HashMap<>(plugins.size());
 
         for (Map.Entry<ResolvedJavaMethod, InvocationPlugin> entry : plugins.entrySet()) {
-            ResolvedJavaMethod method = entry.getKey();
-            InvocationPlugin plugin = entry.getValue();
-
-            String internalName = method.getDeclaringClass().getName();
-            ClassPlugins classPlugins = registrations.get(internalName);
-            if (classPlugins == null) {
-                classPlugins = new ClassPlugins(null);
-                registrations.put(internalName, classPlugins);
-                classPlugins.entries = new HashMap<>();
-            }
-
-            classPlugins.entries.put(new ResolvedJavaMethodKey(method), plugin);
+            map.put(entry.getKey(), entry.getValue());
         }
-    }
-
-    public MetaAccessProvider getMetaAccess() {
-        return metaAccess;
-    }
-
-    public InvocationPlugins(MetaAccessProvider metaAccess) {
-        this(null, metaAccess);
+        this.resolvedRegistrations = map;
     }
 
     protected void register(InvocationPlugin plugin, boolean isOptional, boolean allowOverwrite, Type declaringClass, String name, Type... argumentTypes) {
@@ -714,8 +774,9 @@
         if (!isStatic) {
             argumentTypes[0] = declaringClass;
         }
-        MethodKey methodKey = put(plugin, isStatic, isOptional, allowOverwrite, declaringClass, name, argumentTypes);
-        assert Checker.check(this, declaringClass, methodKey, plugin);
+        Binding binding = put(plugin, isStatic, allowOverwrite, declaringClass, name, argumentTypes);
+        assert Checks.check(this, declaringClass, binding);
+        assert Checks.checkResolvable(isOptional, declaringClass, binding);
     }
 
     /**
@@ -765,23 +826,56 @@
     }
 
     /**
-     * Gets the set of methods for which invocation plugins have been registered. Once this method
-     * is called, no further registrations can be made.
+     * Gets the set of registered invocation plugins.
+     *
+     * @return a map from class names in {@linkplain MetaUtil#toInternalName(String) internal} form
+     *         to the invocation plugin bindings for methods in the class
      */
-    public Set<ResolvedJavaMethod> getMethods() {
-        Set<ResolvedJavaMethod> res = new HashSet<>();
-        if (parent != null) {
-            res.addAll(parent.getMethods());
+    public Map<String, List<Binding>> getBindings(boolean includeParents) {
+        Map<String, List<Binding>> res = new HashMap<>();
+        if (parent != null && includeParents) {
+            res.putAll(parent.getBindings(true));
         }
-        flushDeferrables();
-        for (ClassPlugins cp : registrations.values()) {
-            for (ResolvedJavaMethodKey key : cp.entries.keySet()) {
-                res.add(key.method);
+        if (resolvedRegistrations != null) {
+            for (Map.Entry<ResolvedJavaMethod, InvocationPlugin> e : resolvedRegistrations.entrySet()) {
+                ResolvedJavaMethod method = e.getKey();
+                InvocationPlugin plugin = e.getValue();
+                String type = method.getDeclaringClass().getName();
+                List<Binding> bindings = res.get(type);
+                if (bindings == null) {
+                    bindings = new ArrayList<>();
+                    res.put(type, bindings);
+                }
+                bindings.add(new Binding(method, plugin));
+            }
+        } else {
+            flushDeferrables();
+            for (Map.Entry<String, ClassPlugins> e : registrations.entrySet()) {
+                String type = e.getKey();
+                ClassPlugins cp = e.getValue();
+                collectBindingsTo(res, type, cp);
+            }
+            for (LateClassPlugins lcp = lateRegistrations; lcp != null; lcp = lcp.next) {
+                String type = lcp.className;
+                collectBindingsTo(res, type, lcp);
             }
         }
         return res;
     }
 
+    private static void collectBindingsTo(Map<String, List<Binding>> res, String type, ClassPlugins cp) {
+        for (Map.Entry<String, Binding> e : cp.bindings.entrySet()) {
+            List<Binding> bindings = res.get(type);
+            if (bindings == null) {
+                bindings = new ArrayList<>();
+                res.put(type, bindings);
+            }
+            for (Binding b = e.getValue(); b != null; b = b.next) {
+                bindings.add(b);
+            }
+        }
+    }
+
     /**
      * Gets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched}
      * before searching in this object.
@@ -792,17 +886,36 @@
 
     @Override
     public String toString() {
+        List<String> all = new ArrayList<>();
+        for (Map.Entry<String, List<Binding>> e : getBindings(false).entrySet()) {
+            String c = MetaUtil.internalNameToJava(e.getKey(), true, false);
+            for (Binding b : e.getValue()) {
+                all.add(c + '.' + b);
+            }
+        }
+        Collections.sort(all);
         StringBuilder buf = new StringBuilder();
-        registrations.forEach((name, cp) -> buf.append(name).append('.').append(cp).append(", "));
-        String s = buf.toString();
-        if (buf.length() != 0) {
-            s = s.substring(buf.length() - ", ".length());
+        String nl = String.format("%n");
+        for (String s : all) {
+            if (buf.length() != 0) {
+                buf.append(nl);
+            }
+            buf.append(s);
         }
-        return s + " / parent: " + this.parent;
+        if (parent != null) {
+            if (buf.length() != 0) {
+                buf.append(nl);
+            }
+            buf.append("// parent").append(nl).append(parent);
+        }
+        return buf.toString();
     }
 
-    private static class Checker {
-        private static final int MAX_ARITY = 5;
+    /**
+     * Code only used in assertions. Putting this in a separate class reduces class load time.
+     */
+    private static class Checks {
+        private static final int MAX_ARITY = 7;
         /**
          * The set of all {@link InvocationPlugin#apply} method signatures.
          */
@@ -828,10 +941,17 @@
             SIGS = sigs.toArray(new Class<?>[sigs.size()][]);
         }
 
-        public static boolean check(InvocationPlugins plugins, Type declaringType, MethodKey method, InvocationPlugin plugin) {
+        static boolean containsBinding(InvocationPlugins p, Type declaringType, Binding key) {
+            String internalName = MetaUtil.toInternalName(declaringType.getTypeName());
+            ClassPlugins classPlugins = p.registrations.get(internalName);
+            return classPlugins != null && classPlugins.lookup(key) != null;
+        }
+
+        public static boolean check(InvocationPlugins plugins, Type declaringType, Binding binding) {
+            InvocationPlugin plugin = binding.plugin;
             InvocationPlugins p = plugins.parent;
             while (p != null) {
-                assert !p.containsKey(declaringType, method) : "a plugin is already registered for " + method;
+                assert !containsBinding(p, declaringType, binding) : "a plugin is already registered for " + binding;
                 p = p.parent;
             }
             if (plugin instanceof ForeignCallPlugin || plugin instanceof GeneratedInvocationPlugin) {
@@ -843,8 +963,8 @@
                 assert substitute.getAnnotation(MethodSubstitution.class) != null : format("Substitute method must be annotated with @%s: %s", MethodSubstitution.class.getSimpleName(), substitute);
                 return true;
             }
-            int arguments = method.getDeclaredParameterCount();
-            assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method);
+            int arguments = parseParameters(binding.argumentsDescriptor).size();
+            assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, binding);
             for (Method m : plugin.getClass().getDeclaredMethods()) {
                 if (m.getName().equals("apply")) {
                     Class<?>[] parameterTypes = m.getParameterTypes();
@@ -853,7 +973,24 @@
                     }
                 }
             }
-            throw new AssertionError(format("graph builder plugin for %s not found", method));
+            throw new AssertionError(format("graph builder plugin for %s not found", binding));
+        }
+
+        static boolean checkResolvable(boolean isOptional, Type declaringType, Binding binding) {
+            Class<?> declaringClass = InvocationPlugins.resolveType(declaringType, isOptional);
+            if (declaringClass == null) {
+                return true;
+            }
+            if (binding.name.equals("<init>")) {
+                if (resolveConstructor(declaringClass, binding) == null && !isOptional) {
+                    throw new AssertionError(String.format("Constructor not found: %s%s", declaringClass.getName(), binding.argumentsDescriptor));
+                }
+            } else {
+                if (resolveMethod(declaringClass, binding) == null && !isOptional) {
+                    throw new AssertionError(String.format("Method not found: %s.%s%s", declaringClass.getName(), binding.name, binding.argumentsDescriptor));
+                }
+            }
+            return true;
         }
     }
 
@@ -904,31 +1041,119 @@
         if (type instanceof Class) {
             return (Class<?>) type;
         }
-        if (optional && type instanceof OptionalLazySymbol) {
+        if (type instanceof OptionalLazySymbol) {
             return ((OptionalLazySymbol) type).resolve();
         }
         return resolveClass(type.getTypeName(), optional);
     }
 
-    private static final Class<?>[] NO_CLASSES = {};
+    private static List<String> toInternalTypeNames(Class<?>[] types) {
+        String[] res = new String[types.length];
+        for (int i = 0; i < types.length; i++) {
+            res[i] = MetaUtil.toInternalName(types[i].getTypeName());
+        }
+        return Arrays.asList(res);
+    }
 
     /**
-     * Resolves an array of {@link Type}s to an array of {@link Class}es.
+     * Resolves a given binding to a method in a given class. If more than one method with the
+     * parameter types matching {@code binding} is found and the return types of all the matching
+     * methods form an inheritance chain, the one with the most specific type is returned; otherwise
+     * {@link NoSuchMethodError} is thrown.
      *
-     * @param types the types to resolve
-     * @param from the initial index of the range to be resolved, inclusive
-     * @param to the final index of the range to be resolved, exclusive
-     * @return the resolved class or null if resolution fails and {@code optional} is true
+     * @param declaringClass the class to search for a method matching {@code binding}
+     * @return the method (if any) in {@code declaringClass} matching binding
      */
-    public static Class<?>[] resolveTypes(Type[] types, int from, int to) {
-        int length = to - from;
-        if (length <= 0) {
-            return NO_CLASSES;
+    public static Method resolveMethod(Class<?> declaringClass, Binding binding) {
+        if (binding.name.equals("<init>")) {
+            return null;
         }
-        Class<?>[] classes = new Class<?>[length];
-        for (int i = 0; i < length; i++) {
-            classes[i] = resolveType(types[i + from], false);
+        Method[] methods = declaringClass.getDeclaredMethods();
+        List<String> parameterTypeNames = parseParameters(binding.argumentsDescriptor);
+        for (int i = 0; i < methods.length; ++i) {
+            Method m = methods[i];
+            if (binding.isStatic == Modifier.isStatic(m.getModifiers()) && m.getName().equals(binding.name)) {
+                if (parameterTypeNames.equals(toInternalTypeNames(m.getParameterTypes()))) {
+                    for (int j = i + 1; j < methods.length; ++j) {
+                        Method other = methods[j];
+                        if (binding.isStatic == Modifier.isStatic(other.getModifiers()) && other.getName().equals(binding.name)) {
+                            if (parameterTypeNames.equals(toInternalTypeNames(other.getParameterTypes()))) {
+                                if (m.getReturnType().isAssignableFrom(other.getReturnType())) {
+                                    // `other` has a more specific return type - choose it
+                                    // (m is most likely a bridge method)
+                                    m = other;
+                                } else {
+                                    if (!other.getReturnType().isAssignableFrom(m.getReturnType())) {
+                                        throw new NoSuchMethodError(String.format(
+                                                        "Found 2 methods with same name and parameter types but unrelated return types:%n %s%n %s", m, other));
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    return m;
+                }
+            }
         }
-        return classes;
+        return null;
+    }
+
+    /**
+     * Resolves a given binding to a constructor in a given class.
+     *
+     * @param declaringClass the class to search for a constructor matching {@code binding}
+     * @return the constructor (if any) in {@code declaringClass} matching binding
+     */
+    public static Constructor<?> resolveConstructor(Class<?> declaringClass, Binding binding) {
+        if (!binding.name.equals("<init>")) {
+            return null;
+        }
+        Constructor<?>[] constructors = declaringClass.getDeclaredConstructors();
+        List<String> parameterTypeNames = parseParameters(binding.argumentsDescriptor);
+        for (int i = 0; i < constructors.length; ++i) {
+            Constructor<?> c = constructors[i];
+            if (parameterTypeNames.equals(toInternalTypeNames(c.getParameterTypes()))) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    private static List<String> parseParameters(String argumentsDescriptor) {
+        assert argumentsDescriptor.startsWith("(") && argumentsDescriptor.endsWith(")") : argumentsDescriptor;
+        List<String> res = new ArrayList<>();
+        int cur = 1;
+        int end = argumentsDescriptor.length() - 1;
+        while (cur != end) {
+            char first;
+            int start = cur;
+            do {
+                first = argumentsDescriptor.charAt(cur++);
+            } while (first == '[');
+
+            switch (first) {
+                case 'L':
+                    int endObject = argumentsDescriptor.indexOf(';', cur);
+                    if (endObject == -1) {
+                        throw new GraalError("Invalid object type at index %d in signature: %s", cur, argumentsDescriptor);
+                    }
+                    cur = endObject + 1;
+                    break;
+                case 'V':
+                case 'I':
+                case 'B':
+                case 'C':
+                case 'D':
+                case 'F':
+                case 'J':
+                case 'S':
+                case 'Z':
+                    break;
+                default:
+                    throw new GraalError("Invalid character at index %d in signature: %s", cur, argumentsDescriptor);
+            }
+            res.add(argumentsDescriptor.substring(start, cur));
+        }
+        return res;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java	Thu May 04 11:02:40 2017 +0100
@@ -69,8 +69,7 @@
     void close();
 
     /**
-     * A JVMCI package {@linkplain Services#exportJVMCITo(Class) dynamically exported} to trusted
-     * modules.
+     * A JVMCI package dynamically exported to trusted modules.
      */
     String JVMCI_RUNTIME_PACKAGE = JVMCI.class.getPackage().getName();
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java	Thu May 04 11:02:40 2017 +0100
@@ -30,10 +30,10 @@
 import org.junit.Assert;
 import org.junit.Test;
 
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Thu May 04 11:02:40 2017 +0100
@@ -22,9 +22,17 @@
  */
 package org.graalvm.compiler.serviceprovider;
 
+import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.JDK9Method.addOpens;
+import static org.graalvm.compiler.serviceprovider.JDK9Method.getModule;
+import static org.graalvm.compiler.serviceprovider.JDK9Method.getPackages;
+import static org.graalvm.compiler.serviceprovider.JDK9Method.isOpenTo;
+
+import java.lang.reflect.Method;
 import java.util.Iterator;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
+import java.util.Set;
 
 import jdk.vm.ci.services.JVMCIPermission;
 import jdk.vm.ci.services.Services;
@@ -32,14 +40,32 @@
 /**
  * A mechanism for accessing service providers that abstracts over whether Graal is running on
  * JVMCI-8 or JVMCI-9. In JVMCI-8, a JVMCI specific mechanism is used to lookup services via the
- * hidden JVMCI class loader. in JVMCI-9, the standard {@link ServiceLoader} mechanism is used.
+ * hidden JVMCI class loader. In JVMCI-9, the standard {@link ServiceLoader} mechanism is used.
  */
 public final class GraalServices {
 
     private GraalServices() {
     }
 
-    public static final boolean Java8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0;
+    /**
+     * Opens all JVMCI packages to the module of a given class. This relies on JVMCI already having
+     * opened all its packages to the module defining {@link GraalServices}.
+     *
+     * @param other all JVMCI packages will be opened to the module defining this class
+     */
+    public static void openJVMCITo(Class<?> other) {
+        Object jvmci = getModule.invoke(Services.class);
+        Object otherModule = getModule.invoke(other);
+        if (jvmci != otherModule) {
+            Set<String> packages = getPackages.invoke(jvmci);
+            for (String pkg : packages) {
+                boolean opened = isOpenTo.invoke(jvmci, pkg, otherModule);
+                if (!opened) {
+                    addOpens.invoke(jvmci, pkg, otherModule);
+                }
+            }
+        }
+    }
 
     /**
      * Gets an {@link Iterable} of the providers available for a given service.
@@ -50,9 +76,9 @@
     public static <S> Iterable<S> load(Class<S> service) {
         assert !service.getName().startsWith("jdk.vm.ci") : "JVMCI services must be loaded via " + Services.class.getName();
         if (Java8OrEarlier) {
-            return Services.load(service);
+            return load8(service);
         }
-        ServiceLoader<S> iterable = ServiceLoader.load(service);
+        Iterable<S> iterable = ServiceLoader.load(service);
         return new Iterable<S>() {
             @Override
             public Iterator<S> iterator() {
@@ -66,8 +92,8 @@
                     @Override
                     public S next() {
                         S provider = iterator.next();
-                        // Allow Graal extensions to access JVMCI assuming they have JVMCIPermission
-                        Services.exportJVMCITo(provider.getClass());
+                        // Allow Graal extensions to access JVMCI
+                        openJVMCITo(provider.getClass());
                         return provider;
                     }
 
@@ -81,6 +107,23 @@
     }
 
     /**
+     * {@code Services.load(Class)} is only defined in JVMCI-8.
+     */
+    private static volatile Method loadMethod;
+
+    @SuppressWarnings("unchecked")
+    private static <S> Iterable<S> load8(Class<S> service) throws InternalError {
+        try {
+            if (loadMethod == null) {
+                loadMethod = Services.class.getMethod("load", Class.class);
+            }
+            return (Iterable<S>) loadMethod.invoke(null, service);
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
      * Gets the provider for a given service for which at most one provider must be available.
      *
      * @param service the service whose provider is being requested
@@ -92,16 +135,14 @@
      */
     public static <S> S loadSingle(Class<S> service, boolean required) {
         assert !service.getName().startsWith("jdk.vm.ci") : "JVMCI services must be loaded via " + Services.class.getName();
-        if (Java8OrEarlier) {
-            return Services.loadSingle(service, required);
-        }
-        Iterable<S> providers = ServiceLoader.load(service);
+        Iterable<S> providers = load(service);
         S singleProvider = null;
         try {
             for (Iterator<S> it = providers.iterator(); it.hasNext();) {
                 singleProvider = it.next();
                 if (it.hasNext()) {
-                    throw new InternalError(String.format("Multiple %s providers found", service.getName()));
+                    S other = it.next();
+                    throw new InternalError(String.format("Multiple %s providers found: %s, %s", service.getName(), singleProvider.getClass().getName(), other.getClass().getName()));
                 }
             }
         } catch (ServiceConfigurationError e) {
@@ -111,9 +152,6 @@
             if (required) {
                 throw new InternalError(String.format("No provider for %s found", service.getName()));
             }
-        } else {
-            // Allow Graal extensions to access JVMCI assuming they have JVMCIPermission
-            Services.exportJVMCITo(singleProvider.getClass());
         }
         return singleProvider;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JDK9Method.java	Thu May 04 11:02:40 2017 +0100
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.serviceprovider;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Reflection based access to API introduced by JDK 9. This allows the API to be used in code that
+ * must be compiled on a JDK prior to 9.
+ */
+public final class JDK9Method {
+
+    private static int getJavaSpecificationVersion() {
+        String value = System.getProperty("java.specification.version");
+        if (value.startsWith("1.")) {
+            value = value.substring(2);
+        }
+        return Integer.parseInt(value);
+    }
+
+    /**
+     * The integer value corresponding to the value of the {@code java.specification.version} system
+     * property after any leading {@code "1."} has been stripped.
+     */
+    public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion();
+
+    public JDK9Method(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
+        try {
+            this.method = declaringClass.getMethod(name, parameterTypes);
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Determines if the Java runtime is version 8 or earlier.
+     */
+    public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8;
+
+    public final Method method;
+
+    public Class<?> getReturnType() {
+        return method.getReturnType();
+    }
+
+    /**
+     * {@code Class.getModule()}.
+     */
+    public static final JDK9Method getModule;
+
+    /**
+     * {@code java.lang.Module.getPackages()}.
+     */
+    public static final JDK9Method getPackages;
+
+    /**
+     * {@code java.lang.Module.getResourceAsStream(String)}.
+     */
+    public static final JDK9Method getResourceAsStream;
+
+    /**
+     * {@code java.lang.Module.addOpens(String, Module)}.
+     */
+    public static final JDK9Method addOpens;
+
+    /**
+     * {@code java.lang.Module.isOpen(String, Module)}.
+     */
+    public static final JDK9Method isOpenTo;
+
+    /**
+     * Invokes the static Module API method represented by this object.
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T invokeStatic(Object... args) {
+        checkAvailability();
+        assert Modifier.isStatic(method.getModifiers());
+        try {
+            return (T) method.invoke(null, args);
+        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Invokes the non-static Module API method represented by this object.
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T invoke(Object receiver, Object... args) {
+        checkAvailability();
+        assert !Modifier.isStatic(method.getModifiers());
+        try {
+            return (T) method.invoke(receiver, args);
+        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    private void checkAvailability() throws InternalError {
+        if (method == null) {
+            throw new InternalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION);
+        }
+    }
+
+    static {
+        if (JAVA_SPECIFICATION_VERSION >= 9) {
+            getModule = new JDK9Method(Class.class, "getModule");
+            Class<?> moduleClass = getModule.getReturnType();
+            getPackages = new JDK9Method(moduleClass, "getPackages");
+            addOpens = new JDK9Method(moduleClass, "addOpens", String.class, moduleClass);
+            getResourceAsStream = new JDK9Method(moduleClass, "getResourceAsStream", String.class);
+            isOpenTo = new JDK9Method(moduleClass, "isOpen", String.class, moduleClass);
+        } else {
+            JDK9Method unavailable = new JDK9Method();
+            getModule = unavailable;
+            getPackages = unavailable;
+            addOpens = unavailable;
+            getResourceAsStream = unavailable;
+            isOpenTo = unavailable;
+        }
+    }
+
+    private JDK9Method() {
+        method = null;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/JLModule.java	Tue May 02 08:50:05 2017 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/JLModule.java	Thu May 04 11:02:40 2017 +0100
@@ -96,6 +96,7 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
     public Set<String> getPackages() {
         try {
             return (Set<String>) getPackagesMethod.invoke(realModule);
--- a/src/share/vm/runtime/arguments.cpp	Tue May 02 08:50:05 2017 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Thu May 04 11:02:40 2017 +0100
@@ -2305,8 +2305,6 @@
   if (FLAG_SET_CMDLINE(bool, UseParallelGC, true) != Flag::SUCCESS) {
     return JNI_EINVAL;
   }
-  FLAG_SET_DEFAULT(ParallelGCThreads,
-          Abstract_VM_Version::parallel_worker_threads());
 
   // Encourage steady state memory management
   if (FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100) != Flag::SUCCESS) {
@@ -2517,6 +2515,9 @@
   status = status && check_jvmci_args_consistency();
 
   if (EnableJVMCI) {
+    PropertyList_unique_add(&_system_properties, "jdk.internal.vm.ci.enabled", "true",
+        AddProperty, UnwriteableProperty, InternalProperty);
+
     if (!ScavengeRootsInCode) {
       warning("forcing ScavengeRootsInCode non-zero because JVMCI is enabled");
       ScavengeRootsInCode = 1;
--- a/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java	Thu May 04 11:02:40 2017 +0100
@@ -30,7 +30,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.runtime
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=true
- *      -XX:+EnableJVMCI
+ *      -XX:+EnableJVMCI -Djvmci.Compiler=null
  *      compiler.jvmci.JVM_GetJVMCIRuntimeTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=false
@@ -39,7 +39,7 @@
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=true
  *      -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.threaded=true
- *      -XX:+EnableJVMCI
+ *      -XX:+EnableJVMCI -Djvmci.Compiler=null
  *      compiler.jvmci.JVM_GetJVMCIRuntimeTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=false
--- a/test/compiler/jvmci/TestJVMCIPrintProperties.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/TestJVMCIPrintProperties.java	Thu May 04 11:02:40 2017 +0100
@@ -36,11 +36,11 @@
     public static void main(String[] args) throws Exception {
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
             "-XX:+UnlockExperimentalVMOptions",
-            "-XX:+EnableJVMCI",
+            "-XX:+EnableJVMCI", "-Djvmci.Compiler=null",
             "-XX:+JVMCIPrintProperties");
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
         output.shouldContain("[JVMCI properties]"); // expected message
-        output.shouldContain("jvmci.Compiler = null"); // expected message
+        output.shouldContain("jvmci.Compiler := \"null\""); // expected message
         output.shouldContain("jvmci.InitTimer = false"); // expected message
         output.shouldContain("jvmci.PrintConfig = false"); // expected message
         output.shouldContain("jvmci.TraceMethodDataFilter = null"); // expected message
--- a/test/compiler/jvmci/compilerToVM/AsResolvedJavaMethodTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/AsResolvedJavaMethodTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,7 +34,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.code
  *          jdk.internal.vm.ci/jdk.vm.ci.meta
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.AsResolvedJavaMethodTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java	Thu May 04 11:02:40 2017 +0100
@@ -39,6 +39,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.DoNotInlineOrCompileTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java	Thu May 04 11:02:40 2017 +0100
@@ -36,6 +36,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.FindUniqueConcreteMethodTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,6 +34,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.code
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetBytecodeTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java	Thu May 04 11:02:40 2017 +0100
@@ -31,6 +31,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetClassInitializerTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -38,6 +38,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetConstantPoolTest
  */
 package compiler.jvmci.compilerToVM;
--- a/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,6 +34,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.code
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetExceptionTableTest
  */
 
@@ -137,4 +138,3 @@
         }
     }
 }
-
--- a/test/compiler/jvmci/compilerToVM/GetImplementorTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetImplementorTest.java	Thu May 04 11:02:40 2017 +0100
@@ -31,6 +31,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetImplementorTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java	Thu May 04 11:02:40 2017 +0100
@@ -35,6 +35,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.code
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetLineNumberTableTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java	Thu May 04 11:02:40 2017 +0100
@@ -38,6 +38,7 @@
  * @compile -g DummyClass.java
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetLocalVariableTableTest
  * @clean compiler.jvmci.compilerToVM.*
  */
--- a/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java	Thu May 04 11:02:40 2017 +0100
@@ -35,6 +35,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.meta
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetNextStackFrameTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Thu May 04 11:02:40 2017 +0100
@@ -38,6 +38,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Thu May 04 11:02:40 2017 +0100
@@ -44,7 +44,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *                   -XX:-UseCompressedOops
+ *                   -XX:-UseCompressedOops -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,6 +34,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.code
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetStackTraceElementTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetSymbolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetSymbolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -35,6 +35,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.meta
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                  compiler.jvmci.compilerToVM.GetSymbolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,6 +34,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.code
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.GetVtableIndexForInterfaceTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java	Thu May 04 11:02:40 2017 +0100
@@ -39,7 +39,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *                   -XX:-BackgroundCompilation
+ *                   -XX:-BackgroundCompilation -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.HasCompiledCodeForOSRTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java	Thu May 04 11:02:40 2017 +0100
@@ -31,7 +31,8 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *                  compiler.jvmci.compilerToVM.HasFinalizableSubclassTest
+ *                   -Djvmci.Compiler=null
+ *                   compiler.jvmci.compilerToVM.HasFinalizableSubclassTest
  */
 
 package compiler.jvmci.compilerToVM;
--- a/test/compiler/jvmci/compilerToVM/HasNeverInlineDirectiveTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/HasNeverInlineDirectiveTest.java	Thu May 04 11:02:40 2017 +0100
@@ -39,6 +39,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.HasNeverInlineDirectiveTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Thu May 04 11:02:40 2017 +0100
@@ -42,6 +42,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/IsCompilableTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/IsCompilableTest.java	Thu May 04 11:02:40 2017 +0100
@@ -39,10 +39,12 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.IsCompilableTest
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.IsCompilableTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/IsMatureVsReprofileTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/IsMatureVsReprofileTest.java	Thu May 04 11:02:40 2017 +0100
@@ -38,6 +38,7 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *     -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbatch
+ *     -Djvmci.Compiler=null
  *     compiler.jvmci.compilerToVM.IsMatureVsReprofileTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -42,6 +42,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.LookupKlassInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -40,6 +40,7 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.LookupKlassRefIndexInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -40,6 +40,7 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.LookupMethodInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -40,6 +40,7 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.LookupNameAndTypeRefIndexInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -41,6 +41,7 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.LookupNameInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -41,6 +41,7 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.LookupSignatureInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/LookupTypeTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/LookupTypeTest.java	Thu May 04 11:02:40 2017 +0100
@@ -31,6 +31,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.LookupTypeTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java	Thu May 04 11:02:40 2017 +0100
@@ -49,6 +49,7 @@
  *                   -XX:+DoEscapeAnalysis -XX:-UseCounterDecay
  *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst=true
  *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=false
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
  * @run main/othervm -Xmixed -Xbatch -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
@@ -60,6 +61,7 @@
  *                   -XX:+DoEscapeAnalysis -XX:-UseCounterDecay
  *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst=false
  *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=false
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
  * @run main/othervm -Xmixed -Xbatch -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
@@ -71,6 +73,7 @@
  *                   -XX:+DoEscapeAnalysis -XX:-UseCounterDecay
  *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst=true
  *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=true
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
  * @run main/othervm -Xmixed -Xbatch -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
@@ -82,6 +85,7 @@
  *                   -XX:+DoEscapeAnalysis -XX:-UseCounterDecay
  *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst=false
  *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=true
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java	Thu May 04 11:02:40 2017 +0100
@@ -35,6 +35,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.code
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.MethodIsIgnoredBySecurityStackWalkTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/ReadConfigurationTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/ReadConfigurationTest.java	Thu May 04 11:02:40 2017 +0100
@@ -32,6 +32,7 @@
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.ReadConfigurationTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.ReadConfigurationTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/ReprofileTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/ReprofileTest.java	Thu May 04 11:02:40 2017 +0100
@@ -40,7 +40,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *                   -Xmixed -Xbatch
+ *                   -Xmixed -Xbatch -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.ReprofileTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -40,6 +40,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.ResolveConstantInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -40,6 +40,7 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.ResolveFieldInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,6 +34,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.code
  * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.ResolveMethodTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -40,6 +40,7 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.ResolvePossiblyCachedConstantInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java	Thu May 04 11:02:40 2017 +0100
@@ -41,6 +41,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.ResolveTypeInPoolTest
  */
 
--- a/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java	Thu May 04 11:02:40 2017 +0100
@@ -39,6 +39,7 @@
  * @run main/othervm -Xbootclasspath/a:.
  *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null
  *                   compiler.jvmci.compilerToVM.ShouldInlineMethodTest
  */
 
--- a/test/compiler/jvmci/errors/TestInvalidCompilationResult.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/errors/TestInvalidCompilationResult.java	Thu May 04 11:02:40 2017 +0100
@@ -31,7 +31,8 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          jdk.internal.vm.ci/jdk.vm.ci.common
  * @compile CodeInstallerTest.java
- * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidCompilationResult
+ * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Djvmci.Compiler=null compiler.jvmci.errors.TestInvalidCompilationResult
  */
 
 package compiler.jvmci.errors;
--- a/test/compiler/jvmci/errors/TestInvalidDebugInfo.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/errors/TestInvalidDebugInfo.java	Thu May 04 11:02:40 2017 +0100
@@ -31,7 +31,8 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          jdk.internal.vm.ci/jdk.vm.ci.common
  * @compile CodeInstallerTest.java
- * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidDebugInfo
+ * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *              -Djvmci.Compiler=null compiler.jvmci.errors.TestInvalidDebugInfo
  */
 
 package compiler.jvmci.errors;
--- a/test/compiler/jvmci/errors/TestInvalidOopMap.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/errors/TestInvalidOopMap.java	Thu May 04 11:02:40 2017 +0100
@@ -31,7 +31,8 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          jdk.internal.vm.ci/jdk.vm.ci.common
  * @compile CodeInstallerTest.java
- * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidOopMap
+ * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *             -Djvmci.Compiler=null compiler.jvmci.errors.TestInvalidOopMap
  */
 
 package compiler.jvmci.errors;
--- a/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Thu May 04 11:02:40 2017 +0100
@@ -49,21 +49,14 @@
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *     -Xbootclasspath/a:. -Xmixed
  *     -XX:+UseJVMCICompiler -XX:-BootstrapJVMCI
- *     -Dcompiler.jvmci.events.JvmciNotifyInstallEventTest.failoninit=false
  *     compiler.jvmci.events.JvmciNotifyInstallEventTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
- *     -Djvmci.compiler=EmptyCompiler -Xbootclasspath/a:. -Xmixed
+ *     -Djvmci.Compiler=EmptyCompiler -Xbootclasspath/a:. -Xmixed
  *     -XX:+UseJVMCICompiler -XX:-BootstrapJVMCI
- *     -Dcompiler.jvmci.events.JvmciNotifyInstallEventTest.failoninit=false
  *     compiler.jvmci.events.JvmciNotifyInstallEventTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
- *     -Djvmci.compiler=EmptyCompiler -Xbootclasspath/a:. -Xmixed
+ *     -Djvmci.Compiler=EmptyCompiler -Xbootclasspath/a:. -Xmixed
  *     -XX:+UseJVMCICompiler -XX:-BootstrapJVMCI -XX:JVMCINMethodSizeLimit=0
- *     -Dcompiler.jvmci.events.JvmciNotifyInstallEventTest.failoninit=false
- *     compiler.jvmci.events.JvmciNotifyInstallEventTest
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-EnableJVMCI
- *     -Djvmci.compiler=EmptyCompiler -Xbootclasspath/a:. -Xmixed
- *     -Dcompiler.jvmci.events.JvmciNotifyInstallEventTest.failoninit=true
  *     compiler.jvmci.events.JvmciNotifyInstallEventTest
  */
 
@@ -91,8 +84,6 @@
 
 public class JvmciNotifyInstallEventTest extends JVMCIServiceLocator implements HotSpotVMEventListener {
     private static final String METHOD_NAME = "testMethod";
-    private static final boolean FAIL_ON_INIT = !Boolean.getBoolean(
-            "compiler.jvmci.events.JvmciNotifyInstallEventTest.failoninit");
     private static volatile int gotInstallNotification = 0;
 
     public static void main(String args[]) {
@@ -116,16 +107,9 @@
             codeCache = (HotSpotCodeCacheProvider) HotSpotJVMCIRuntime.runtime()
                     .getHostJVMCIBackend().getCodeCache();
         } catch (InternalError ie) {
-            if (FAIL_ON_INIT) {
-                throw new AssertionError(
-                        "Got unexpected InternalError trying to get code cache",
-                        ie);
-            }
             // passed
             return;
         }
-        Asserts.assertTrue(FAIL_ON_INIT,
-                    "Haven't caught InternalError in negative case");
         Method testMethod;
         try {
             testMethod = SimpleClass.class.getDeclaredMethod(METHOD_NAME);
--- a/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java	Thu May 04 11:02:40 2017 +0100
@@ -33,7 +33,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.amd64
  *          jdk.internal.vm.ci/jdk.vm.ci.sparc
  * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.code.test.DataPatchTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.DataPatchTest
  */
 
 package jdk.vm.ci.code.test;
--- a/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java	Thu May 04 11:02:40 2017 +0100
@@ -33,7 +33,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.amd64
  *          jdk.internal.vm.ci/jdk.vm.ci.sparc
  * @compile CodeInstallationTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.code.test.InterpreterFrameSizeTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.InterpreterFrameSizeTest
  */
 
 package jdk.vm.ci.code.test;
--- a/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,7 +34,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.amd64
  *          jdk.internal.vm.ci/jdk.vm.ci.sparc
  * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.code.test.MaxOopMapStackOffsetTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.MaxOopMapStackOffsetTest
  */
 
 package jdk.vm.ci.code.test;
--- a/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java	Thu May 04 11:02:40 2017 +0100
@@ -33,7 +33,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.amd64
  *          jdk.internal.vm.ci/jdk.vm.ci.sparc
  * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.code.test.SimpleCodeInstallationTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.SimpleCodeInstallationTest
  */
 
 package jdk.vm.ci.code.test;
--- a/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java	Thu May 04 11:02:40 2017 +0100
@@ -33,7 +33,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.amd64
  *          jdk.internal.vm.ci/jdk.vm.ci.sparc
  * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.code.test.SimpleDebugInfoTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.SimpleDebugInfoTest
  */
 
 package jdk.vm.ci.code.test;
--- a/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java	Thu May 04 11:02:40 2017 +0100
@@ -33,7 +33,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.amd64
  *          jdk.internal.vm.ci/jdk.vm.ci.sparc
  * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.code.test.VirtualObjectDebugInfoTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.VirtualObjectDebugInfoTest
  */
 
 package jdk.vm.ci.code.test;
--- a/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/HotSpotConstantReflectionProviderTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/HotSpotConstantReflectionProviderTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,7 +34,7 @@
  * @run driver ClassFileInstaller jdk.vm.ci.hotspot.test.DummyClass
  * @run testng/othervm/timeout=300 -Xbootclasspath/a:.
  *      -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *       jdk.vm.ci.hotspot.test.HotSpotConstantReflectionProviderTest
+ *      -Djvmci.Compiler=null jdk.vm.ci.hotspot.test.HotSpotConstantReflectionProviderTest
  */
 
 package jdk.vm.ci.hotspot.test;
--- a/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderTest.java	Thu May 04 11:02:40 2017 +0100
@@ -37,7 +37,7 @@
  * @run testng/othervm -Xbootclasspath/a:.
  *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *      -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      jdk.vm.ci.hotspot.test.MemoryAccessProviderTest
+ *      -Djvmci.Compiler=null jdk.vm.ci.hotspot.test.MemoryAccessProviderTest
  */
 
 package jdk.vm.ci.hotspot.test;
--- a/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MethodHandleAccessProviderTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MethodHandleAccessProviderTest.java	Thu May 04 11:02:40 2017 +0100
@@ -32,7 +32,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:+open
  * @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      jdk.vm.ci.hotspot.test.MethodHandleAccessProviderTest
+ *      -Djvmci.Compiler=null jdk.vm.ci.hotspot.test.MethodHandleAccessProviderTest
  */
 
 package jdk.vm.ci.hotspot.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java	Thu May 04 11:02:40 2017 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ConstantTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.ConstantTest
  */
 package jdk.vm.ci.runtime.test;
 
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java	Thu May 04 11:02:40 2017 +0100
@@ -29,8 +29,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          jdk.attach
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djdk.attach.allowAttachSelf
- *                   jdk.vm.ci.runtime.test.RedefineClassTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null -Djdk.attach.allowAttachSelf jdk.vm.ci.runtime.test.RedefineClassTest
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java	Thu May 04 11:02:40 2017 +0100
@@ -26,7 +26,7 @@
  * @requires vm.jvmci
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveConcreteMethodTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveConcreteMethodTest
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java	Thu May 04 11:02:40 2017 +0100
@@ -26,7 +26,7 @@
  * @requires vm.jvmci
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveMethodTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveMethodTest
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java	Thu May 04 11:02:40 2017 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestConstantReflectionProvider
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.TestConstantReflectionProvider
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java	Thu May 04 11:02:40 2017 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaField
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.TestJavaField
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java	Thu May 04 11:02:40 2017 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaMethod
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.TestJavaMethod
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java	Thu May 04 11:02:40 2017 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaType
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.TestJavaType
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java	Thu May 04 11:02:40 2017 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestMetaAccessProvider
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.TestMetaAccessProvider
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Thu May 04 11:02:40 2017 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaField
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.TestResolvedJavaField
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Thu May 04 11:02:40 2017 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaMethod
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.TestResolvedJavaMethod
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Thu May 04 11:02:40 2017 +0100
@@ -30,7 +30,7 @@
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          jdk.internal.vm.ci/jdk.vm.ci.common
  *          java.base/jdk.internal.misc
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaType
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.runtime.test.TestResolvedJavaType
  */
 
 package jdk.vm.ci.runtime.test;
--- a/test/compiler/jvmci/meta/StableFieldTest.java	Tue May 02 08:50:05 2017 +0100
+++ b/test/compiler/jvmci/meta/StableFieldTest.java	Thu May 04 11:02:40 2017 +0100
@@ -34,7 +34,7 @@
  *
  * @compile StableFieldTest.java
  * @run driver ClassFileInstaller compiler.jvmci.meta.StableFieldTest
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:. compiler.jvmci.meta.StableFieldTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null -Xbootclasspath/a:. compiler.jvmci.meta.StableFieldTest
  */
 
 package compiler.jvmci.meta;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/arguments/TestAggressiveHeap.java	Thu May 04 11:02:40 2017 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestAggressiveHeap
+ * @key gc
+ * @bug 8179084
+ * @requires vm.gc.Parallel
+ * @summary Test argument processing for -XX:+AggressiveHeap.
+ * @library /test/lib
+ * @modules java.base java.management
+ * @run driver TestAggressiveHeap
+ */
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestAggressiveHeap {
+
+    public static void main(String args[]) throws Exception {
+        if (canUseAggressiveHeapOption()) {
+            testFlag();
+        }
+    }
+
+    // Note: Not a normal boolean flag; -XX:-AggressiveHeap is invalid.
+    private static final String option = "-XX:+AggressiveHeap";
+
+    // Option requires at least 256M, else error during option processing.
+    private static final long minMemory = 256 * 1024 * 1024;
+
+    // bool UseParallelGC = true {product} {command line}
+    private static final String parallelGCPattern =
+        " *bool +UseParallelGC *= *true +\\{product\\} *\\{command line\\}";
+
+    private static void testFlag() throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            option, "-XX:+PrintFlagsFinal", "-version");
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+        output.shouldHaveExitValue(0);
+
+        String value = output.firstMatch(parallelGCPattern);
+        if (value == null) {
+            throw new RuntimeException(
+                option + " didn't set UseParallelGC as if from command line");
+        }
+    }
+
+    private static boolean haveRequiredMemory() throws Exception {
+        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+        ObjectName os = new ObjectName("java.lang", "type", "OperatingSystem");
+        Object attr = server.getAttribute(os, "TotalPhysicalMemorySize");
+        String value = attr.toString();
+        long memory = Long.parseLong(value);
+        return memory >= minMemory;
+    }
+
+    private static boolean canUseAggressiveHeapOption() throws Exception {
+        if (!haveRequiredMemory()) {
+            System.out.println(
+                "Skipping test of " + option + " : insufficient memory");
+            return false;
+        }
+        return true;
+    }
+}
+