changeset 22429:a1b0a76567c7

Select default compiler from jvmci.compiler system property.
author Roland Schatz <roland.schatz@oracle.com>
date Mon, 17 Aug 2015 18:32:44 +0200
parents ca5200277c37
children 0666b6a8f33b
files jvmci/jdk.internal.jvmci.compiler/src/jdk/internal/jvmci/compiler/Compiler.java jvmci/jdk.internal.jvmci.compiler/src/jdk/internal/jvmci/compiler/CompilerFactory.java jvmci/jdk.internal.jvmci.compiler/src/jdk/internal/jvmci/compiler/StartupEventListener.java jvmci/jdk.internal.jvmci.hotspot.amd64/src/jdk/internal/jvmci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIBackendFactory.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCICompilerConfig.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntimeProvider.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVMEventListener.java jvmci/jdk.internal.jvmci.runtime/src/jdk/internal/jvmci/runtime/JVMCI.java mx.jvmci/mx_jvmci.py mx.jvmci/suite.py src/share/vm/jvmci/jvmciRuntime.cpp src/share/vm/jvmci/jvmciRuntime.hpp src/share/vm/runtime/thread.cpp
diffstat 16 files changed, 290 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/jdk.internal.jvmci.compiler/src/jdk/internal/jvmci/compiler/Compiler.java	Tue Aug 11 15:17:53 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.compiler/src/jdk/internal/jvmci/compiler/Compiler.java	Mon Aug 17 18:32:44 2015 +0200
@@ -22,7 +22,6 @@
  */
 package jdk.internal.jvmci.compiler;
 
-import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.meta.*;
 import jdk.internal.jvmci.options.*;
 
@@ -37,5 +36,21 @@
     @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
     @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
 
-    CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean mustRecordMethodInlining);
+    /**
+     * Request the compilation of a method by this JVMCI compiler. The compiler should compile the
+     * method to machine code and install it in the code cache if the compilation is successful.
+     *
+     * @param method the method that should be compiled
+     * @param entryBCI the BCI at which to start compiling where -1 denotes a non-OSR compilation
+     *            request and all other values denote an OSR compilation request
+     * @param jvmciEnv pointer to native {@code JVMCIEnv} object
+     * @param id a unique identifier for this compilation
+     */
+    void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id);
+
+    /**
+     * Notifies this JVMCI compiler that the VM is running in CompileTheWorld mode and it should now
+     * perform its version of CompileTheWorld.
+     */
+    void compileTheWorld() throws Throwable;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.compiler/src/jdk/internal/jvmci/compiler/CompilerFactory.java	Mon Aug 17 18:32:44 2015 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 2015, 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.internal.jvmci.compiler;
+
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.runtime.*;
+
+/**
+ * Factory for a JVMCI compiler.
+ */
+public interface CompilerFactory {
+
+    /**
+     * Get the name of this compiler. The compiler will be selected when the jvmci.compiler system
+     * property is equal to this name.
+     */
+    String getCompilerName();
+
+    /**
+     * Initialize an {@link Architecture}. The compiler has the opportunity to extend the
+     * {@link Architecture} description with a custom subclass.
+     */
+    Architecture initializeArchitecture(Architecture arch);
+
+    /**
+     * Create a new instance of the {@link Compiler}.
+     */
+    Compiler createCompiler(JVMCIRuntime runtime);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.compiler/src/jdk/internal/jvmci/compiler/StartupEventListener.java	Mon Aug 17 18:32:44 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, 2015, 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.internal.jvmci.compiler;
+
+public interface StartupEventListener {
+
+    /**
+     * This method is called before any of the {@link CompilerFactory} methods.
+     */
+    void beforeJVMCIStartup();
+}
--- a/jvmci/jdk.internal.jvmci.hotspot.amd64/src/jdk/internal/jvmci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Tue Aug 11 15:17:53 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot.amd64/src/jdk/internal/jvmci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Mon Aug 17 18:32:44 2015 +0200
@@ -28,6 +28,7 @@
 
 import jdk.internal.jvmci.amd64.*;
 import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.compiler.*;
 import jdk.internal.jvmci.hotspot.*;
 import jdk.internal.jvmci.inittimer.*;
 import jdk.internal.jvmci.meta.*;
@@ -37,10 +38,6 @@
 @ServiceProvider(HotSpotJVMCIBackendFactory.class)
 public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
 
-    protected Architecture createArchitecture(HotSpotVMConfig config) {
-        return new AMD64(computeFeatures(config), computeFlags(config));
-    }
-
     protected EnumSet<AMD64.CPUFeature> computeFeatures(HotSpotVMConfig config) {
         // Configure the feature set using the HotSpot flag settings.
         EnumSet<AMD64.CPUFeature> features = EnumSet.noneOf(AMD64.CPUFeature.class);
@@ -100,11 +97,12 @@
         return flags;
     }
 
-    protected TargetDescription createTarget(HotSpotVMConfig config) {
+    protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = true;
-        return new TargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        Architecture arch = new AMD64(computeFeatures(config), computeFlags(config));
+        return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
     protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) {
@@ -123,19 +121,20 @@
         return new HotSpotMetaAccessProvider(runtime);
     }
 
+    @Override
     public String getArchitecture() {
         return "AMD64";
     }
 
     @Override
     public String toString() {
-        return getJVMCIRuntimeName() + ":" + getArchitecture();
+        return "JVMCIBackend:" + getArchitecture();
     }
 
-    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
+    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) {
 
         assert host == null;
-        TargetDescription target = createTarget(runtime.getConfig());
+        TargetDescription target = createTarget(runtime.getConfig(), compilerFactory);
 
         RegisterConfig regConfig;
         HotSpotCodeCacheProvider codeCache;
@@ -163,8 +162,4 @@
     protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection) {
         return new JVMCIBackend(metaAccess, codeCache, constantReflection);
     }
-
-    public String getJVMCIRuntimeName() {
-        return "basic";
-    }
 }
--- a/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Tue Aug 11 15:17:53 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Mon Aug 17 18:32:44 2015 +0200
@@ -27,6 +27,7 @@
 import java.util.*;
 
 import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.compiler.*;
 import jdk.internal.jvmci.hotspot.*;
 import jdk.internal.jvmci.inittimer.*;
 import jdk.internal.jvmci.runtime.*;
@@ -37,15 +38,12 @@
 @ServiceProvider(HotSpotJVMCIBackendFactory.class)
 public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
 
-    protected Architecture createArchitecture(HotSpotVMConfig config) {
-        return new SPARC(computeFeatures(config));
-    }
-
-    protected TargetDescription createTarget(HotSpotVMConfig config) {
+    protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = false;
-        return new TargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        Architecture arch = new SPARC(computeFeatures(config));
+        return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
     protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
@@ -72,18 +70,19 @@
         return features;
     }
 
+    @Override
     public String getArchitecture() {
         return "SPARC";
     }
 
     @Override
     public String toString() {
-        return getJVMCIRuntimeName() + ":" + getArchitecture();
+        return "JVMCIBackend:" + getArchitecture();
     }
 
-    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
+    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) {
         assert host == null;
-        TargetDescription target = createTarget(runtime.getConfig());
+        TargetDescription target = createTarget(runtime.getConfig(), compilerFactory);
 
         HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
         RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target, runtime.getConfig());
@@ -97,8 +96,4 @@
     protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection) {
         return new JVMCIBackend(metaAccess, codeCache, constantReflection);
     }
-
-    public String getJVMCIRuntimeName() {
-        return "basic";
-    }
 }
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIBackendFactory.java	Tue Aug 11 15:17:53 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIBackendFactory.java	Mon Aug 17 18:32:44 2015 +0200
@@ -22,16 +22,15 @@
  */
 package jdk.internal.jvmci.hotspot;
 
+import jdk.internal.jvmci.compiler.*;
 import jdk.internal.jvmci.runtime.*;
 
 public interface HotSpotJVMCIBackendFactory {
 
-    JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host);
+    JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host);
 
     /**
      * Gets the CPU architecture of this backend.
      */
     String getArchitecture();
-
-    String getJVMCIRuntimeName();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCICompilerConfig.java	Mon Aug 17 18:32:44 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 2015, 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.internal.jvmci.hotspot;
+
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.compiler.*;
+import jdk.internal.jvmci.compiler.Compiler;
+import jdk.internal.jvmci.meta.*;
+import jdk.internal.jvmci.runtime.*;
+import jdk.internal.jvmci.service.*;
+
+final class HotSpotJVMCICompilerConfig {
+
+    private static class DummyCompilerFactory implements CompilerFactory, Compiler {
+
+        public void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+            throw new JVMCIError("no JVMCI compiler selected");
+        }
+
+        public void compileTheWorld() throws Throwable {
+            throw new JVMCIError("no JVMCI compiler selected");
+        }
+
+        public String getCompilerName() {
+            return "<none>";
+        }
+
+        public Architecture initializeArchitecture(Architecture arch) {
+            return arch;
+        }
+
+        public Compiler createCompiler(JVMCIRuntime runtime) {
+            return this;
+        }
+    }
+
+    private static CompilerFactory compilerFactory;
+
+    /**
+     * Called from the VM.
+     */
+    static Boolean selectCompiler(String compilerName) {
+        for (CompilerFactory factory : Services.load(CompilerFactory.class)) {
+            if (factory.getCompilerName().equals(compilerName)) {
+                compilerFactory = factory;
+                return Boolean.TRUE;
+            }
+        }
+
+        throw new JVMCIError("JVMCI compiler '%s' not found", compilerName);
+    }
+
+    static CompilerFactory getCompilerFactory() {
+        if (compilerFactory == null) {
+            compilerFactory = new DummyCompilerFactory();
+        }
+        return compilerFactory;
+    }
+}
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java	Tue Aug 11 15:17:53 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java	Mon Aug 17 18:32:44 2015 +0200
@@ -28,6 +28,8 @@
 
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.compiler.*;
+import jdk.internal.jvmci.compiler.Compiler;
 import jdk.internal.jvmci.inittimer.*;
 import jdk.internal.jvmci.meta.*;
 import jdk.internal.jvmci.options.*;
@@ -42,6 +44,12 @@
 
     static {
         try (InitTimer t0 = timer("HotSpotJVMCIRuntime.<clinit>")) {
+            try (InitTimer t = timer("StartupEventListener.beforeJVMCIStartup")) {
+                for (StartupEventListener l : Services.load(StartupEventListener.class)) {
+                    l.beforeJVMCIStartup();
+                }
+            }
+
             try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
                 instance = new HotSpotJVMCIRuntime();
             }
@@ -72,6 +80,8 @@
         // proxied methods. Some of these static initializers (e.g. in
         // HotSpotMethodData) rely on the static 'instance' field being set
         // to retrieve configuration details.
+        compiler = HotSpotJVMCICompilerConfig.getCompilerFactory().createCompiler(this);
+
         CompilerToVM toVM = this.compilerToVm;
 
         for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
@@ -84,62 +94,19 @@
     public static class Options {
 
         // @formatter:off
-        @Option(help = "The JVMCI runtime configuration to use", type = OptionType.Expert)
-        public static final OptionValue<String> JVMCIRuntime = new OptionValue<>("");
-
         @Option(help = "File to which logging is sent.  A %p in the name will be replaced with a string identifying the process, usually the process id.", type = OptionType.Expert)
         public static final PrintStreamOption LogFile = new PrintStreamOption();
         // @formatter:on
     }
 
     public static HotSpotJVMCIBackendFactory findFactory(String architecture) {
-        HotSpotJVMCIBackendFactory basic = null;
-        HotSpotJVMCIBackendFactory selected = null;
-        HotSpotJVMCIBackendFactory nonBasic = null;
-        int nonBasicCount = 0;
-
         for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) {
             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
-                if (factory.getJVMCIRuntimeName().equals(Options.JVMCIRuntime.getValue())) {
-                    assert selected == null || checkFactoryOverriding(selected, factory);
-                    selected = factory;
-                }
-                if (factory.getJVMCIRuntimeName().equals("basic")) {
-                    assert basic == null || checkFactoryOverriding(basic, factory);
-                    basic = factory;
-                } else {
-                    nonBasic = factory;
-                    nonBasicCount++;
-                }
+                return factory;
             }
         }
 
-        if (selected != null) {
-            return selected;
-        } else {
-            if (!Options.JVMCIRuntime.getValue().equals("")) {
-                // Fail fast if a non-default value for JVMCIRuntime was specified
-                // and the corresponding factory is not available
-                throw new JVMCIError("Specified runtime \"%s\" not available for the %s architecture", Options.JVMCIRuntime.getValue(), architecture);
-            } else if (nonBasicCount == 1) {
-                // If there is exactly one non-basic runtime, select this one.
-                return nonBasic;
-            } else {
-                return basic;
-            }
-        }
-    }
-
-    /**
-     * Checks that a factory overriding is valid. A factory B can only override/replace a factory A
-     * if the B.getClass() is a subclass of A.getClass(). This models the assumption that B is
-     * extends the behavior of A and has therefore understood the behavior expected of A.
-     *
-     * @param baseFactory
-     * @param overridingFactory
-     */
-    private static boolean checkFactoryOverriding(HotSpotJVMCIBackendFactory baseFactory, HotSpotJVMCIBackendFactory overridingFactory) {
-        return baseFactory.getClass().isAssignableFrom(overridingFactory.getClass());
+        throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
     }
 
     /**
@@ -154,6 +121,7 @@
     protected final HotSpotVMConfig config;
     private final JVMCIBackend hostBackend;
 
+    private Compiler compiler;
     protected final JVMCIMetaAccessContext metaAccessContext;
 
     private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
@@ -161,8 +129,7 @@
     private final Iterable<HotSpotVMEventListener> vmEventListeners;
 
     private HotSpotJVMCIRuntime() {
-        CompilerToVM toVM = new CompilerToVMImpl();
-        compilerToVm = toVM;
+        compilerToVm = new CompilerToVMImpl();
         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
             config = new HotSpotVMConfig(compilerToVm);
         }
@@ -173,16 +140,14 @@
         try (InitTimer t = timer("find factory:", hostArchitecture)) {
             factory = findFactory(hostArchitecture);
         }
+
+        CompilerFactory compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
+
         try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
-            hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
+            hostBackend = registerBackend(factory.createJVMCIBackend(this, compilerFactory, null));
         }
 
-        Iterable<HotSpotVMEventListener> listeners = Services.load(HotSpotVMEventListener.class);
-        if (!listeners.iterator().hasNext()) {
-            listeners = Arrays.asList(new HotSpotVMEventListener() {
-            });
-        }
-        vmEventListeners = listeners;
+        vmEventListeners = Services.load(HotSpotVMEventListener.class);
 
         JVMCIMetaAccessContext context = null;
         for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
@@ -229,6 +194,10 @@
         return metaAccessContext;
     }
 
+    public Compiler getCompiler() {
+        return compiler;
+    }
+
     public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
         Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
         // If the name represents a primitive type we can short-circuit the lookup.
@@ -266,9 +235,8 @@
      */
     @SuppressWarnings({"unused"})
     private void compileMetaspaceMethod(long metaspaceMethod, int entryBCI, long jvmciEnv, int id) {
-        for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
-            vmEventListener.compileMetaspaceMethod(metaspaceMethod, entryBCI, jvmciEnv, id);
-        }
+        HotSpotResolvedJavaMethod method = HotSpotResolvedJavaMethodImpl.fromMetaspace(metaspaceMethod);
+        compiler.compileMethod(method, entryBCI, jvmciEnv, id);
     }
 
     /**
@@ -276,9 +244,7 @@
      */
     @SuppressWarnings({"unused"})
     private void compileTheWorld() throws Throwable {
-        for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
-            vmEventListener.notifyCompileTheWorld();
-        }
+        compiler.compileTheWorld();
     }
 
     /**
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntimeProvider.java	Tue Aug 11 15:17:53 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntimeProvider.java	Mon Aug 17 18:32:44 2015 +0200
@@ -23,6 +23,7 @@
 package jdk.internal.jvmci.hotspot;
 
 import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.compiler.Compiler;
 import jdk.internal.jvmci.meta.*;
 import jdk.internal.jvmci.runtime.*;
 import sun.misc.*;
@@ -38,6 +39,8 @@
 
     CompilerToVM getCompilerToVM();
 
+    Compiler getCompiler();
+
     /**
      * Converts a name to a Java type. This method attempts to resolve {@code name} to a
      * {@link ResolvedJavaType}.
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVMEventListener.java	Tue Aug 11 15:17:53 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVMEventListener.java	Mon Aug 17 18:32:44 2015 +0200
@@ -30,26 +30,6 @@
 public interface HotSpotVMEventListener {
 
     /**
-     * Compiles a method to machine code and installs it in the code cache if the compilation is
-     * successful.
-     *
-     * @param metaspaceMethod the address of a Method metaspace object
-     * @param entryBCI the BCI at which to start compiling where -1 denotes a non-OSR compilation
-     *            request and all other values denote an OSR compilation request
-     * @param jvmciEnv pointer to native {@code JVMCIEnv} object
-     * @param id a unique identifier for this compilation
-     */
-    default void compileMetaspaceMethod(long metaspaceMethod, int entryBCI, long jvmciEnv, int id) {
-    }
-
-    /**
-     * Notifies this client that HotSpot is running in CompileTheWorld mode and the JVMCI compiler
-     * should now perform its version of CompileTheWorld.
-     */
-    default void notifyCompileTheWorld() throws Throwable {
-    }
-
-    /**
      * Notifies this client that the VM is shutting down.
      */
     default void notifyShutdown() {
--- a/jvmci/jdk.internal.jvmci.runtime/src/jdk/internal/jvmci/runtime/JVMCI.java	Tue Aug 11 15:17:53 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.runtime/src/jdk/internal/jvmci/runtime/JVMCI.java	Mon Aug 17 18:32:44 2015 +0200
@@ -30,6 +30,10 @@
 
     private static native JVMCIRuntime initializeRuntime();
 
+    public static void initialize() {
+        // force static initializer
+    }
+
     /**
      * Gets the singleton {@link JVMCIRuntime} instance available to the application.
      *
--- a/mx.jvmci/mx_jvmci.py	Tue Aug 11 15:17:53 2015 +0200
+++ b/mx.jvmci/mx_jvmci.py	Mon Aug 17 18:32:44 2015 +0200
@@ -126,8 +126,9 @@
         return join('jre', 'lib')
 
 class JvmciJDKDeployedDist(JarJDKDeployedDist):
-    def __init__(self, name, partOfHotSpot=False):
+    def __init__(self, name, partOfHotSpot=False, compilers=False):
         JarJDKDeployedDist.__init__(self, name, partOfHotSpot)
+        self._compilers = compilers
 
     def targetDir(self):
         return join('jre', 'lib', 'jvmci')
@@ -135,6 +136,8 @@
     def deploy(self, jdkDir):
         JarJDKDeployedDist.deploy(self, jdkDir)
         _updateJVMCIFiles(jdkDir)
+        if self._compilers:
+            _updateJVMCIProperties(jdkDir, self._compilers)
 
 def _exe(l):
     return mx.exe_suffix(l)
@@ -619,6 +622,32 @@
     jreJVMCIServicesDir = join(jreJVMCIDir, 'services')
     _extractJVMCIFiles(_getJdkDeployedJars(jdkDir), jvmciJars, jreJVMCIServicesDir, obsoleteCheck)
 
+def _updateJVMCIProperties(jdkDir, compilers):
+    jvmciProperties = join(jdkDir, 'jre', 'lib', 'jvmci', 'jvmci.properties')
+    if not exists(jvmciProperties):
+        with open(jvmciProperties, 'w') as fp:
+            for compiler in compilers:
+                print >> fp, "jvmci.compiler=" + compiler
+    else:
+        oldCompilers = []
+        with open(jvmciProperties) as fp:
+            for line in fp:
+                if line.startswith('jvmci.compiler='):
+                    oldCompilers += [line.strip().split('=')[1]]
+        changed = False
+        newCompilers = []
+        for c in compilers:
+            if not c in oldCompilers:
+                changed = True
+                newCompilers += [c]
+        if changed:
+            with open(jvmciProperties, 'w') as fp:
+                # prepend new compilers, since the first property wins
+                for c in newCompilers:
+                    print >> fp, "jvmci.compiler=" + c
+                for c in oldCompilers:
+                    print >> fp, "jvmci.compiler=" + c
+
 def _installDistInJdks(deployableDist):
     """
     Installs the jar(s) for a given Distribution into all existing JVMCI JDKs
--- a/mx.jvmci/suite.py	Tue Aug 11 15:17:53 2015 +0200
+++ b/mx.jvmci/suite.py	Mon Aug 17 18:32:44 2015 +0200
@@ -154,7 +154,7 @@
       "sourceDirs" : ["src"],
       "dependencies" : [
         "jdk.internal.jvmci.options",
-        "jdk.internal.jvmci.code",
+        "jdk.internal.jvmci.runtime",
       ],
       "checkstyle" : "jdk.internal.jvmci.service",
       "annotationProcessors" : ["JVMCI_OPTIONS_PROCESSOR"],
@@ -210,16 +210,13 @@
       "sourceDirs" : ["src"],
       "dependencies" : [
         "jdk.internal.jvmci.hotspotvmconfig",
-        "jdk.internal.jvmci.runtime",
+        "jdk.internal.jvmci.compiler",
         "jdk.internal.jvmci.common",
-        "jdk.internal.jvmci.options",
         "jdk.internal.jvmci.service",
-        "jdk.internal.jvmci.runtime",
       ],
       "annotationProcessors" : [
         "JVMCI_HOTSPOTVMCONFIG_PROCESSOR",
         "JVMCI_OPTIONS_PROCESSOR",
-        "JVMCI_SERVICE_PROCESSOR",
       ],
       "checkstyle" : "jdk.internal.jvmci.service",
       "javaCompliance" : "1.8",
--- a/src/share/vm/jvmci/jvmciRuntime.cpp	Tue Aug 11 15:17:53 2015 +0200
+++ b/src/share/vm/jvmci/jvmciRuntime.cpp	Mon Aug 17 18:32:44 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, 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
@@ -44,6 +44,7 @@
 
 jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
 bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false;
+const char* JVMCIRuntime::_compiler = NULL;
 const char* JVMCIRuntime::_options = NULL;
 bool JVMCIRuntime::_shutdown_called = false;
 
@@ -682,6 +683,15 @@
                       "(Ljava/lang/String;)Ljava/lang/Boolean;", &args);
     }
 
+    if (_compiler != NULL) {
+      JavaCallArguments args;
+      oop compiler = java_lang_String::create_oop_from_str(_compiler, CHECK_ABORT);
+      args.push_oop(compiler);
+      callInitializer("jdk/internal/jvmci/hotspot/HotSpotJVMCICompilerConfig",
+                      "selectCompiler",
+                      "(Ljava/lang/String;)Ljava/lang/Boolean;", &args);
+    }
+
     Handle result = callInitializer("jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime", "runtime",
                                     "()Ljdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime;");
     _HotSpotJVMCIRuntime_initialized = true;
@@ -807,6 +817,12 @@
   } \
   (void)(0
 
+void JVMCIRuntime::save_compiler(const char* compiler) {
+  assert(compiler != NULL, "npe");
+  assert(_compiler == NULL, "cannot reassign JVMCI compiler");
+  _compiler = compiler;
+}
+
 void JVMCIRuntime::save_options(const char* options) {
   assert(options != NULL, "npe");
   assert(_options == NULL, "cannot reassign JVMCI options");
--- a/src/share/vm/jvmci/jvmciRuntime.hpp	Tue Aug 11 15:17:53 2015 +0200
+++ b/src/share/vm/jvmci/jvmciRuntime.hpp	Mon Aug 17 18:32:44 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, 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
@@ -58,6 +58,7 @@
  private:
   static jobject _HotSpotJVMCIRuntime_instance;
   static bool _HotSpotJVMCIRuntime_initialized;
+  static const char* _compiler;
   static const char* _options;
 
   static bool _shutdown_called;
@@ -77,6 +78,12 @@
   static void parse_properties(SystemProperty** plist);
 
   /**
+   * Saves the value of the "jvmci.compiler" system property for processing
+   * when JVMCI is initialized.
+   */
+  static void save_compiler(const char* compiler);
+
+  /**
    * Saves the value of the "jvmci.options" system property for processing
    * when JVMCI is initialized.
    */
--- a/src/share/vm/runtime/thread.cpp	Tue Aug 11 15:17:53 2015 +0200
+++ b/src/share/vm/runtime/thread.cpp	Mon Aug 17 18:32:44 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -3700,6 +3700,10 @@
   }
 
 #if INCLUDE_JVMCI
+  const char* jvmciCompiler = Arguments::PropertyList_get_value(Arguments::system_properties(), "jvmci.compiler");
+  if (jvmciCompiler != NULL) {
+    JVMCIRuntime::save_compiler(jvmciCompiler);
+  }
   const char* jvmciOptions = Arguments::PropertyList_get_value(Arguments::system_properties(), "jvmci.options");
   if (jvmciOptions != NULL) {
     JVMCIRuntime::save_options(jvmciOptions);