changeset 22398:4f6caa445b92

moved JVMCI option parsing back into Java
author Doug Simon <doug.simon@oracle.com>
date Tue, 04 Aug 2015 00:47:34 +0200
parents 7202e96981c6
children fb3940232214
files 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/CompilerToVMImpl.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotCompiledNmethod.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotInstalledCode.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotObjectConstantImpl.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotOptions.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/InitTimer.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/SuppressFBWarnings.java jvmci/jdk.internal.jvmci.inittimer/src/jdk/internal/jvmci/inittimer/InitTimer.java jvmci/jdk.internal.jvmci.inittimer/src/jdk/internal/jvmci/inittimer/SuppressFBWarnings.java jvmci/jdk.internal.jvmci.options.processor/src/jdk/internal/jvmci/options/processor/OptionProcessor.java jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/JVMCIJarsOptionDescriptorsProvider.java jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionDescriptors.java jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionUtils.java jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/Options.java jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionsLoader.java jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionsParser.java make/defs.make make/jvmci.make mx.jvmci/mx_jvmci.py mx.jvmci/mx_jvmci_makefile.py mx.jvmci/suite.py src/share/vm/jvmci/jvmciHashtable.cpp src/share/vm/jvmci/jvmciHashtable.hpp src/share/vm/jvmci/jvmciOptions.cpp src/share/vm/jvmci/jvmciOptions.hpp src/share/vm/jvmci/jvmciRuntime.cpp src/share/vm/jvmci/jvmciRuntime.hpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/arguments.hpp src/share/vm/runtime/thread.cpp
diffstat 33 files changed, 697 insertions(+), 1409 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/jdk.internal.jvmci.hotspot.amd64/src/jdk/internal/jvmci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot.amd64/src/jdk/internal/jvmci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Tue Aug 04 00:47:34 2015 +0200
@@ -22,13 +22,14 @@
  */
 package jdk.internal.jvmci.hotspot.amd64;
 
-import static jdk.internal.jvmci.hotspot.InitTimer.*;
+import static jdk.internal.jvmci.inittimer.InitTimer.*;
 
 import java.util.*;
 
 import jdk.internal.jvmci.amd64.*;
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.hotspot.*;
+import jdk.internal.jvmci.inittimer.*;
 import jdk.internal.jvmci.meta.*;
 import jdk.internal.jvmci.runtime.*;
 import jdk.internal.jvmci.service.*;
--- a/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Tue Aug 04 00:47:34 2015 +0200
@@ -22,16 +22,17 @@
  */
 package jdk.internal.jvmci.hotspot.sparc;
 
-import static jdk.internal.jvmci.hotspot.InitTimer.*;
+import static jdk.internal.jvmci.inittimer.InitTimer.*;
 
 import java.util.*;
 
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.hotspot.*;
+import jdk.internal.jvmci.inittimer.*;
 import jdk.internal.jvmci.runtime.*;
 import jdk.internal.jvmci.service.*;
 import jdk.internal.jvmci.sparc.*;
-import jdk.internal.jvmci.sparc.SPARC.*;
+import jdk.internal.jvmci.sparc.SPARC.CPUFeature;
 
 @ServiceProvider(HotSpotJVMCIBackendFactory.class)
 public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/CompilerToVMImpl.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/CompilerToVMImpl.java	Tue Aug 04 00:47:34 2015 +0200
@@ -23,9 +23,10 @@
 
 package jdk.internal.jvmci.hotspot;
 
-import static jdk.internal.jvmci.hotspot.InitTimer.*;
+import static jdk.internal.jvmci.inittimer.InitTimer.*;
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.inittimer.*;
 import jdk.internal.jvmci.meta.*;
 
 /**
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotCompiledNmethod.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotCompiledNmethod.java	Tue Aug 04 00:47:34 2015 +0200
@@ -23,6 +23,7 @@
 package jdk.internal.jvmci.hotspot;
 
 import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.inittimer.*;
 
 /**
  * {@link HotSpotCompiledCode} destined for installation as an nmethod.
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotInstalledCode.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotInstalledCode.java	Tue Aug 04 00:47:34 2015 +0200
@@ -24,6 +24,7 @@
 
 import static jdk.internal.jvmci.common.UnsafeAccess.*;
 import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.inittimer.*;
 import sun.misc.*;
 
 /**
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java	Tue Aug 04 00:47:34 2015 +0200
@@ -23,12 +23,13 @@
 package jdk.internal.jvmci.hotspot;
 
 import static jdk.internal.jvmci.common.UnsafeAccess.*;
-import static jdk.internal.jvmci.hotspot.InitTimer.*;
+import static jdk.internal.jvmci.inittimer.InitTimer.*;
 
 import java.util.*;
 
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.inittimer.*;
 import jdk.internal.jvmci.meta.*;
 import jdk.internal.jvmci.options.*;
 import jdk.internal.jvmci.runtime.*;
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotObjectConstantImpl.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotObjectConstantImpl.java	Tue Aug 04 00:47:34 2015 +0200
@@ -26,6 +26,7 @@
 
 import java.lang.invoke.*;
 
+import jdk.internal.jvmci.inittimer.*;
 import jdk.internal.jvmci.meta.*;
 
 /**
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotOptions.java	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2011, 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 java.util.*;
-
-import jdk.internal.jvmci.options.*;
-
-//JaCoCo Exclude
-
-/**
- * Sets JVMCI options from the HotSpot command line. Such options are distinguished by the
- * {@link #JVMCI_OPTION_PREFIX} prefix.
- */
-public class HotSpotOptions {
-
-    private static final String JVMCI_OPTION_PREFIX = "-G:";
-
-    /**
-     * Called from VM.
-     */
-    static void printFlags() {
-        SortedMap<String, OptionDescriptor> options = new TreeMap<>();
-
-        for (Options opts : ServiceLoader.load(Options.class, HotSpotOptions.class.getClassLoader())) {
-            for (OptionDescriptor desc : opts) {
-                String name = desc.getName();
-                OptionDescriptor existing = options.put(name, desc);
-                assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
-            }
-        }
-
-        OptionUtils.printFlags(options, JVMCI_OPTION_PREFIX);
-    }
-}
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/InitTimer.java	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2014, 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;
-
-/**
- * A facility for timing a step in the runtime initialization sequence. This must be independent
- * from all other JVMCI code so as to not perturb the initialization sequence.
- */
-public final class InitTimer implements AutoCloseable {
-    final String name;
-    final long start;
-
-    private InitTimer(String name) {
-        this.name = name;
-        this.start = System.currentTimeMillis();
-        System.out.println("START: " + SPACES.substring(0, timerDepth * 2) + name);
-        assert Thread.currentThread() == initializingThread : Thread.currentThread() + " != " + initializingThread;
-        timerDepth++;
-    }
-
-    @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "only the initializing thread accesses this field")
-    public void close() {
-        final long end = System.currentTimeMillis();
-        timerDepth--;
-        System.out.println(" DONE: " + SPACES.substring(0, timerDepth * 2) + name + " [" + (end - start) + " ms]");
-    }
-
-    public static InitTimer timer(String name) {
-        return ENABLED ? new InitTimer(name) : null;
-    }
-
-    public static InitTimer timer(String name, Object suffix) {
-        return ENABLED ? new InitTimer(name + suffix) : null;
-    }
-
-    /**
-     * Specifies if initialization timing is enabled. This can only be set via a system property as
-     * the timing facility is used to time initialization of {@link HotSpotOptions}.
-     */
-    private static final boolean ENABLED = Boolean.getBoolean("jvmci.runtime.TimeInit");
-
-    public static int timerDepth = 0;
-    public static final String SPACES = "                                            ";
-
-    /**
-     * Used to assert the invariant that all initialization happens on the same thread.
-     */
-    public static final Thread initializingThread;
-    static {
-        if (ENABLED) {
-            initializingThread = Thread.currentThread();
-            System.out.println("INITIALIZING THREAD: " + initializingThread);
-        } else {
-            initializingThread = null;
-        }
-    }
-}
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/SuppressFBWarnings.java	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014, 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;
-
-/**
- * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
- */
-public @interface SuppressFBWarnings {
-    /**
-     * The set of FindBugs <a
-     * href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
-     * suppressed in annotated element. The value can be a bug category, kind or pattern.
-     */
-    String[] value();
-
-    /**
-     * Reason why the warning is suppressed.
-     */
-    String justification();
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.inittimer/src/jdk/internal/jvmci/inittimer/InitTimer.java	Tue Aug 04 00:47:34 2015 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, 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.inittimer;
+
+/**
+ * A facility for timing a step in the runtime initialization sequence. This is independent from all
+ * other JVMCI code so as to not perturb the initialization sequence. It is enabled by setting the
+ * {@code "jvmci.inittimer"} system property to {@code "true"}.
+ */
+public final class InitTimer implements AutoCloseable {
+    final String name;
+    final long start;
+
+    private InitTimer(String name) {
+        this.name = name;
+        this.start = System.currentTimeMillis();
+        System.out.println("START: " + SPACES.substring(0, timerDepth * 2) + name);
+        assert Thread.currentThread() == initializingThread : Thread.currentThread() + " != " + initializingThread;
+        timerDepth++;
+    }
+
+    @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "only the initializing thread accesses this field")
+    public void close() {
+        final long end = System.currentTimeMillis();
+        timerDepth--;
+        System.out.println(" DONE: " + SPACES.substring(0, timerDepth * 2) + name + " [" + (end - start) + " ms]");
+    }
+
+    public static InitTimer timer(String name) {
+        return ENABLED ? new InitTimer(name) : null;
+    }
+
+    public static InitTimer timer(String name, Object suffix) {
+        return ENABLED ? new InitTimer(name + suffix) : null;
+    }
+
+    /**
+     * Specifies if initialization timing is enabled.
+     */
+    private static final boolean ENABLED = Boolean.getBoolean("jvmci.inittimer") || Boolean.getBoolean("jvmci.runtime.TimeInit");
+
+    public static int timerDepth = 0;
+    public static final String SPACES = "                                            ";
+
+    /**
+     * Used to assert the invariant that all initialization happens on the same thread.
+     */
+    public static final Thread initializingThread;
+    static {
+        if (ENABLED) {
+            initializingThread = Thread.currentThread();
+            System.out.println("INITIALIZING THREAD: " + initializingThread);
+        } else {
+            initializingThread = null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.inittimer/src/jdk/internal/jvmci/inittimer/SuppressFBWarnings.java	Tue Aug 04 00:47:34 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 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.inittimer;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+public @interface SuppressFBWarnings {
+    /**
+     * The set of FindBugs <a
+     * href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+     * suppressed in annotated element. The value can be a bug category, kind or pattern.
+     */
+    String[] value();
+
+    /**
+     * Reason why the warning is suppressed.
+     */
+    String justification();
+}
--- a/jvmci/jdk.internal.jvmci.options.processor/src/jdk/internal/jvmci/options/processor/OptionProcessor.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.options.processor/src/jdk/internal/jvmci/options/processor/OptionProcessor.java	Tue Aug 04 00:47:34 2015 +0200
@@ -36,21 +36,10 @@
 import jdk.internal.jvmci.options.*;
 
 /**
- * Processes static fields annotated with {@link Option}. An {@link Options} service is generated
- * for each top level class containing at least one such field. The name of the generated class for
- * top level class {@code com.foo.Bar} is {@code com.foo.Bar_Options}.
- *
- * The build system is expected to create the appropriate entries in {@code META-INF/services/} such
- * that these service objects can be retrieved as follows:
- *
- * <pre>
- * ServiceLoader&lt;Options&gt; sl = ServiceLoader.load(Options.class);
- * for (Options opts : sl) {
- *     for (OptionDescriptor desc : sl) {
- *         // use desc
- *     }
- * }
- * </pre>
+ * Processes static fields annotated with {@link Option}. An {@link OptionDescriptors}
+ * implementation is generated for each top level class containing at least one such field. The name
+ * of the generated class for top level class {@code com.foo.Bar} is
+ * {@code com.foo.Bar_OptionDescriptors}.
  */
 @SupportedAnnotationTypes({"jdk.internal.jvmci.options.Option"})
 public class OptionProcessor extends AbstractProcessor {
@@ -152,9 +141,13 @@
     private void createFiles(OptionsInfo info) {
         String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString();
         Name topDeclaringClass = info.topDeclaringType.getSimpleName();
+        Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]);
 
-        String optionsClassName = topDeclaringClass + "_" + Options.class.getSimpleName();
-        Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]);
+        createOptionsDescriptorsFile(info, pkg, topDeclaringClass, originatingElements);
+    }
+
+    private void createOptionsDescriptorsFile(OptionsInfo info, String pkg, Name topDeclaringClass, Element[] originatingElements) {
+        String optionsClassName = topDeclaringClass + "_" + OptionDescriptors.class.getSimpleName();
 
         Filer filer = processingEnv.getFiler();
         try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) {
@@ -165,18 +158,52 @@
             out.println("package " + pkg + ";");
             out.println("");
             out.println("import java.util.*;");
-            out.println("import " + Options.class.getPackage().getName() + ".*;");
+            out.println("import " + OptionDescriptors.class.getPackage().getName() + ".*;");
             out.println("");
-            out.println("public class " + optionsClassName + " implements " + Options.class.getSimpleName() + " {");
-            out.println("    @Override");
+            out.println("public class " + optionsClassName + " implements " + OptionDescriptors.class.getSimpleName() + " {");
+
             String desc = OptionDescriptor.class.getSimpleName();
-            out.println("    public Iterator<" + desc + "> iterator() {");
-            out.println("        // CheckStyle: stop line length check");
-            out.println("        List<" + desc + "> options = Arrays.asList(");
 
             boolean needPrivateFieldAccessor = false;
             int i = 0;
             Collections.sort(info.options);
+
+            out.println("    @Override");
+            out.println("    public OptionDescriptor get(String value) {");
+            out.println("        // CheckStyle: stop line length check");
+            if (info.options.size() == 1) {
+                out.println("        if (value.equals(\"" + info.options.get(0).name + "\")) {");
+            } else {
+                out.println("        switch (value) {");
+            }
+            for (OptionInfo option : info.options) {
+                String name = option.name;
+                String optionValue;
+                if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
+                    needPrivateFieldAccessor = true;
+                    optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")";
+                } else {
+                    optionValue = option.declaringClass + "." + option.field.getSimpleName();
+                }
+                String type = option.type;
+                String help = option.help;
+                String declaringClass = option.declaringClass;
+                Name fieldName = option.field.getSimpleName();
+                if (info.options.size() == 1) {
+                    out.printf("            return new %s(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
+                } else {
+                    out.printf("            case \"" + name + "\": return new %s(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
+                }
+            }
+            out.println("        }");
+            out.println("        // CheckStyle: resume line length check");
+            out.println("        return null;");
+            out.println("    }");
+            out.println();
+            out.println("    @Override");
+            out.println("    public Iterator<" + desc + "> iterator() {");
+            out.println("        // CheckStyle: stop line length check");
+            out.println("        List<" + desc + "> options = Arrays.asList(");
             for (OptionInfo option : info.options) {
                 String optionValue;
                 if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
@@ -213,59 +240,19 @@
         }
 
         try {
-            createOptionsFile(info, pkg, topDeclaringClass.toString(), originatingElements);
+            createOptionsFile(pkg, topDeclaringClass.toString(), originatingElements);
         } catch (IOException e) {
             processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType);
         }
     }
 
-    private void createOptionsFile(OptionsInfo info, String pkg, String relativeName, Element... originatingElements) throws IOException {
+    private void createOptionsFile(String pkg, String relativeName, Element... originatingElements) throws IOException {
         String filename = "META-INF/jvmci.options/" + pkg + "." + relativeName;
         FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements);
         PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"));
-        Types types = processingEnv.getTypeUtils();
-        for (OptionInfo option : info.options) {
-            String help = option.help;
-            if (help.indexOf('\t') >= 0 || help.indexOf('\r') >= 0 || help.indexOf('\n') >= 0) {
-                processingEnv.getMessager().printMessage(Kind.WARNING, "Option help should not contain '\\t', '\\r' or '\\n'", option.field);
-                help = help.replace('\t', ' ').replace('\n', ' ').replace('\r', ' ');
-            }
-            try {
-                char optionTypeToChar = optionTypeToChar(option);
-                String fqDeclaringClass = className(types.erasure(option.field.getEnclosingElement().asType()));
-                String fqFieldType = className(types.erasure(option.field.asType()));
-                writer.printf("%s\t%s\t%s\t%s\t%s%n", option.name, optionTypeToChar, help, fqDeclaringClass, fqFieldType);
-            } catch (IllegalArgumentException iae) {
-            }
-        }
         writer.close();
     }
 
-    private String className(TypeMirror t) {
-        DeclaredType dt = (DeclaredType) t;
-        return processingEnv.getElementUtils().getBinaryName((TypeElement) dt.asElement()).toString();
-    }
-
-    private char optionTypeToChar(OptionInfo option) {
-        switch (option.type) {
-            case "Boolean":
-                return 'z';
-            case "Integer":
-                return 'i';
-            case "Long":
-                return 'j';
-            case "Float":
-                return 'f';
-            case "Double":
-                return 'd';
-            case "String":
-                return 's';
-            default:
-                processingEnv.getMessager().printMessage(Kind.ERROR, "Unsupported option type: " + option.type, option.field);
-                throw new IllegalArgumentException();
-        }
-    }
-
     protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) {
         try {
             // Ensure Unix line endings to comply with code style guide checked by Checkstyle
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/JVMCIJarsOptionDescriptorsProvider.java	Tue Aug 04 00:47:34 2015 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014, 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.options;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.zip.*;
+
+import jdk.internal.jvmci.options.OptionsParser.*;
+
+/**
+ * Access to the {@link OptionDescriptors} declared by
+ * {@code META-INF/services/jdk.internal.jvmci.options.OptionDescriptors} files in
+ * {@code <jre>/lib/jvmci/*.jar}.
+ */
+class JVMCIJarsOptionDescriptorsProvider implements OptionDescriptorsProvider {
+
+    static final String OptionDescriptorsServiceFile = "META-INF/services/" + OptionDescriptors.class.getName();
+
+    private final Iterator<File> jars;
+    private final List<OptionDescriptors> optionsDescriptorsList;
+
+    JVMCIJarsOptionDescriptorsProvider() {
+        List<File> jarsList = findJVMCIJars();
+        this.jars = jarsList.iterator();
+        this.optionsDescriptorsList = new ArrayList<>(jarsList.size() * 3);
+    }
+
+    /**
+     * Finds the list of JVMCI jars.
+     */
+    private static List<File> findJVMCIJars() {
+        File javaHome = new File(System.getProperty("java.home"));
+        File lib = new File(javaHome, "lib");
+        File jvmci = new File(lib, "jvmci");
+        if (!jvmci.exists()) {
+            throw new InternalError(jvmci + " does not exist");
+        }
+
+        List<File> jarFiles = new ArrayList<>();
+        for (String fileName : jvmci.list()) {
+            if (fileName.endsWith(".jar")) {
+                File file = new File(jvmci, fileName);
+                if (file.isDirectory()) {
+                    continue;
+                }
+                jarFiles.add(file);
+            }
+        }
+        return jarFiles;
+    }
+
+    public OptionDescriptor get(String name) {
+        // Look up loaded option descriptors first
+        for (OptionDescriptors optionDescriptors : optionsDescriptorsList) {
+            OptionDescriptor desc = optionDescriptors.get(name);
+            if (desc != null) {
+                return desc;
+            }
+        }
+        while (jars.hasNext()) {
+            File path = jars.next();
+            try (JarFile jar = new JarFile(path)) {
+                ZipEntry entry = jar.getEntry(OptionDescriptorsServiceFile);
+                if (entry != null) {
+                    BufferedReader br = new BufferedReader(new InputStreamReader(jar.getInputStream(entry)));
+                    String line = null;
+                    OptionDescriptor desc = null;
+                    while ((line = br.readLine()) != null) {
+                        OptionDescriptors options;
+                        try {
+                            options = (OptionDescriptors) Class.forName(line).newInstance();
+                            optionsDescriptorsList.add(options);
+                            if (desc == null) {
+                                desc = options.get(name);
+                            }
+                        } catch (Exception e) {
+                            throw new InternalError("Error instantiating class " + line + " read from " + path, e);
+                        }
+                    }
+                    if (desc != null) {
+                        return desc;
+                    }
+                }
+            } catch (IOException e) {
+                throw new InternalError("Error reading " + path, e);
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionDescriptors.java	Tue Aug 04 00:47:34 2015 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 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.options;
+
+/**
+ * An interface to a set of {@link OptionDescriptor}s.
+ */
+public interface OptionDescriptors extends Iterable<OptionDescriptor> {
+    /**
+     * Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option
+     * descriptor set doesn't contain a matching option.
+     */
+    OptionDescriptor get(String value);
+}
--- a/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionUtils.java	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2014, 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.options;
-
-import java.util.*;
-
-public class OptionUtils {
-
-    public interface OptionConsumer {
-        void set(OptionDescriptor desc, Object value);
-    }
-
-    /**
-     * Parses a given option value specification.
-     *
-     * @param option the specification of an option and its value
-     * @param setter the object to notify of the parsed option and value.
-     */
-    public static void parseOption(String option, OptionConsumer setter) {
-        SortedMap<String, OptionDescriptor> options = OptionsLoader.options;
-        Objects.requireNonNull(setter);
-        if (option.length() == 0) {
-            return;
-        }
-
-        Object value = null;
-        String optionName = null;
-        String valueString = null;
-
-        char first = option.charAt(0);
-        if (first == '+' || first == '-') {
-            optionName = option.substring(1);
-            value = (first == '+');
-        } else {
-            int index = option.indexOf('=');
-            if (index == -1) {
-                optionName = option;
-                valueString = null;
-            } else {
-                optionName = option.substring(0, index);
-                valueString = option.substring(index + 1);
-            }
-        }
-
-        OptionDescriptor desc = options.get(optionName);
-        if (desc == null) {
-            throw new IllegalArgumentException("Option '" + optionName + "' not found");
-        }
-
-        Class<?> optionType = desc.getType();
-
-        if (value == null) {
-            if (optionType == Boolean.TYPE || optionType == Boolean.class) {
-                throw new IllegalArgumentException("Boolean option '" + optionName + "' must use +/- prefix");
-            }
-
-            if (valueString == null) {
-                throw new IllegalArgumentException("Missing value for non-boolean option '" + optionName + "' must use " + optionName + "=<value> format");
-            }
-
-            if (optionType == Float.class) {
-                value = Float.parseFloat(valueString);
-            } else if (optionType == Double.class) {
-                value = Double.parseDouble(valueString);
-            } else if (optionType == Integer.class) {
-                value = Integer.valueOf((int) parseLong(valueString));
-            } else if (optionType == Long.class) {
-                value = Long.valueOf(parseLong(valueString));
-            } else if (optionType == String.class) {
-                value = valueString;
-            } else {
-                throw new IllegalArgumentException("Wrong value for option '" + optionName + "'");
-            }
-        } else {
-            if (optionType != Boolean.class) {
-                throw new IllegalArgumentException("Non-boolean option '" + optionName + "' can not use +/- prefix. Use " + optionName + "=<value> format");
-            }
-        }
-
-        setter.set(desc, value);
-    }
-
-    private static long parseLong(String v) {
-        String valueString = v.toLowerCase();
-        long scale = 1;
-        if (valueString.endsWith("k")) {
-            scale = 1024L;
-        } else if (valueString.endsWith("m")) {
-            scale = 1024L * 1024L;
-        } else if (valueString.endsWith("g")) {
-            scale = 1024L * 1024L * 1024L;
-        } else if (valueString.endsWith("t")) {
-            scale = 1024L * 1024L * 1024L * 1024L;
-        }
-
-        if (scale != 1) {
-            /* Remove trailing scale character. */
-            valueString = valueString.substring(0, valueString.length() - 1);
-        }
-
-        return Long.parseLong(valueString) * scale;
-    }
-
-    /**
-     * Wraps some given text to one or more lines of a given maximum width.
-     *
-     * @param text text to wrap
-     * @param width maximum width of an output line, exception for words in {@code text} longer than
-     *            this value
-     * @return {@code text} broken into lines
-     */
-    private static List<String> wrap(String text, int width) {
-        List<String> lines = Collections.singletonList(text);
-        if (text.length() > width) {
-            String[] chunks = text.split("\\s+");
-            lines = new ArrayList<>();
-            StringBuilder line = new StringBuilder();
-            for (String chunk : chunks) {
-                if (line.length() + chunk.length() > width) {
-                    lines.add(line.toString());
-                    line.setLength(0);
-                }
-                if (line.length() != 0) {
-                    line.append(' ');
-                }
-                String[] embeddedLines = chunk.split("%n", -2);
-                if (embeddedLines.length == 1) {
-                    line.append(chunk);
-                } else {
-                    for (int i = 0; i < embeddedLines.length; i++) {
-                        line.append(embeddedLines[i]);
-                        if (i < embeddedLines.length - 1) {
-                            lines.add(line.toString());
-                            line.setLength(0);
-                        }
-                    }
-                }
-            }
-            if (line.length() != 0) {
-                lines.add(line.toString());
-            }
-        }
-        return lines;
-    }
-
-    public static void printFlags(SortedMap<String, OptionDescriptor> options, String prefix) {
-        System.out.println("[List of " + prefix + " options]");
-        SortedMap<String, OptionDescriptor> sortedOptions = options;
-        for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
-            e.getKey();
-            OptionDescriptor desc = e.getValue();
-            Object value = desc.getOptionValue().getValue();
-            List<String> helpLines = wrap(desc.getHelp(), 70);
-            System.out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
-            for (int i = 1; i < helpLines.size(); i++) {
-                System.out.println(String.format("%67s %s", " ", helpLines.get(i)));
-            }
-        }
-
-        System.exit(0);
-    }
-}
--- a/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/Options.java	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2013, 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.options;
-
-import java.util.*;
-
-/**
- * A {@linkplain ServiceLoader service} for accessing a set of {@link OptionDescriptor}s.
- */
-public interface Options extends Iterable<OptionDescriptor> {
-}
--- a/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionsLoader.java	Mon Aug 03 15:19:14 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionsLoader.java	Tue Aug 04 00:47:34 2015 +0200
@@ -34,7 +34,7 @@
      * Initializes {@link #options} from {@link Options} services.
      */
     static {
-        for (Options opts : ServiceLoader.load(Options.class, OptionsLoader.class.getClassLoader())) {
+        for (OptionDescriptors opts : ServiceLoader.load(OptionDescriptors.class, OptionsLoader.class.getClassLoader())) {
             for (OptionDescriptor desc : opts) {
                 String name = desc.getName();
                 OptionDescriptor existing = options.put(name, desc);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionsParser.java	Tue Aug 04 00:47:34 2015 +0200
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2014, 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.options;
+
+import static jdk.internal.jvmci.inittimer.InitTimer.*;
+
+import java.util.*;
+
+import jdk.internal.jvmci.inittimer.*;
+
+/**
+ *
+ * @author dsimon
+ *
+ */
+public class OptionsParser {
+
+    /**
+     * A service for looking up {@link OptionDescriptor}s.
+     */
+    public interface OptionDescriptorsProvider {
+        /**
+         * Gets the {@link OptionDescriptor} matching a given option {@linkplain Option#name() name}
+         * or null if no option of that name is provided by this object.
+         */
+        OptionDescriptor get(String name);
+    }
+
+    public interface OptionConsumer {
+        void set(OptionDescriptor desc, Object value);
+    }
+
+    /**
+     * Finds the index of the next character in {@code s} starting at {@code from} that is a space
+     * iff {@code spaces == true}.
+     */
+    private static int skip(String s, int from, boolean spaces) {
+        for (int i = from; i < s.length(); i++) {
+            if ((s.charAt(i) != ' ') == spaces) {
+                return i;
+            }
+        }
+        return s.length();
+    }
+
+    /**
+     * Parses the set of space separated JVMCI options in {@code options}.
+     *
+     * Called from VM. This method has an object return type to allow it to be called with a VM
+     * utility function used to call other static initialization methods.
+     *
+     * @param options space separated set of JVMCI options to parse
+     */
+    public static Boolean parseOptionsFromVM(String options) {
+        try (InitTimer t = timer("ParseOptions")) {
+            JVMCIJarsOptionDescriptorsProvider odp = new JVMCIJarsOptionDescriptorsProvider();
+            assert options != null;
+            int index = skip(options, 0, true);
+            while (index < options.length()) {
+                int end = skip(options, index, false);
+                String option = options.substring(index, end);
+                parseOption(option, null, odp);
+                index = skip(options, end, true);
+            }
+        }
+        return Boolean.TRUE;
+    }
+
+    /**
+     * Parses a given option value specification.
+     *
+     * @param option the specification of an option and its value
+     * @param setter the object to notify of the parsed option and value
+     * @throws IllegalArgumentException if there's a problem parsing {@code option}
+     */
+    public static void parseOption(String option, OptionConsumer setter, OptionDescriptorsProvider odp) {
+        if (option.length() == 0) {
+            return;
+        }
+
+        Object value = null;
+        String optionName = null;
+        String valueString = null;
+
+        char first = option.charAt(0);
+        if (first == '+' || first == '-') {
+            optionName = option.substring(1);
+            value = (first == '+');
+        } else {
+            int index = option.indexOf('=');
+            if (index == -1) {
+                optionName = option;
+                valueString = null;
+            } else {
+                optionName = option.substring(0, index);
+                valueString = option.substring(index + 1);
+            }
+        }
+
+        OptionDescriptor desc = odp == null ? OptionsLoader.options.get(optionName) : odp.get(optionName);
+        if (desc == null && value != null) {
+            int index = option.indexOf('=');
+            if (index != -1) {
+                optionName = option.substring(1, index);
+                desc = odp == null ? OptionsLoader.options.get(optionName) : odp.get(optionName);
+            }
+        }
+        if (desc == null) {
+            List<OptionDescriptor> matches = fuzzyMatch(optionName);
+            Formatter msg = new Formatter();
+            msg.format("Could not find option %s", optionName);
+            if (!matches.isEmpty()) {
+                msg.format("%nDid you mean one of the following?");
+                for (OptionDescriptor match : matches) {
+                    boolean isBoolean = match.getType() == Boolean.class;
+                    msg.format("%n    %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=<value>");
+                }
+            }
+            throw new IllegalArgumentException(msg.toString());
+        }
+
+        Class<?> optionType = desc.getType();
+
+        if (value == null) {
+            if (optionType == Boolean.TYPE || optionType == Boolean.class) {
+                throw new IllegalArgumentException("Boolean option '" + optionName + "' must use +/- prefix");
+            }
+
+            if (valueString == null) {
+                throw new IllegalArgumentException("Missing value for non-boolean option '" + optionName + "' must use " + optionName + "=<value> format");
+            }
+
+            if (optionType == Float.class) {
+                value = Float.parseFloat(valueString);
+            } else if (optionType == Double.class) {
+                value = Double.parseDouble(valueString);
+            } else if (optionType == Integer.class) {
+                value = Integer.valueOf((int) parseLong(valueString));
+            } else if (optionType == Long.class) {
+                value = Long.valueOf(parseLong(valueString));
+            } else if (optionType == String.class) {
+                value = valueString;
+            } else {
+                throw new IllegalArgumentException("Wrong value for option '" + optionName + "'");
+            }
+        } else {
+            if (optionType != Boolean.class) {
+                throw new IllegalArgumentException("Non-boolean option '" + optionName + "' can not use +/- prefix. Use " + optionName + "=<value> format");
+            }
+        }
+        if (setter == null) {
+            desc.getOptionValue().setValue(value);
+        } else {
+            setter.set(desc, value);
+        }
+    }
+
+    private static long parseLong(String v) {
+        String valueString = v.toLowerCase();
+        long scale = 1;
+        if (valueString.endsWith("k")) {
+            scale = 1024L;
+        } else if (valueString.endsWith("m")) {
+            scale = 1024L * 1024L;
+        } else if (valueString.endsWith("g")) {
+            scale = 1024L * 1024L * 1024L;
+        } else if (valueString.endsWith("t")) {
+            scale = 1024L * 1024L * 1024L * 1024L;
+        }
+
+        if (scale != 1) {
+            /* Remove trailing scale character. */
+            valueString = valueString.substring(0, valueString.length() - 1);
+        }
+
+        return Long.parseLong(valueString) * scale;
+    }
+
+    /**
+     * Wraps some given text to one or more lines of a given maximum width.
+     *
+     * @param text text to wrap
+     * @param width maximum width of an output line, exception for words in {@code text} longer than
+     *            this value
+     * @return {@code text} broken into lines
+     */
+    private static List<String> wrap(String text, int width) {
+        List<String> lines = Collections.singletonList(text);
+        if (text.length() > width) {
+            String[] chunks = text.split("\\s+");
+            lines = new ArrayList<>();
+            StringBuilder line = new StringBuilder();
+            for (String chunk : chunks) {
+                if (line.length() + chunk.length() > width) {
+                    lines.add(line.toString());
+                    line.setLength(0);
+                }
+                if (line.length() != 0) {
+                    line.append(' ');
+                }
+                String[] embeddedLines = chunk.split("%n", -2);
+                if (embeddedLines.length == 1) {
+                    line.append(chunk);
+                } else {
+                    for (int i = 0; i < embeddedLines.length; i++) {
+                        line.append(embeddedLines[i]);
+                        if (i < embeddedLines.length - 1) {
+                            lines.add(line.toString());
+                            line.setLength(0);
+                        }
+                    }
+                }
+            }
+            if (line.length() != 0) {
+                lines.add(line.toString());
+            }
+        }
+        return lines;
+    }
+
+    public static void printFlags(SortedMap<String, OptionDescriptor> options, String prefix) {
+        System.out.println("[List of " + prefix + " options]");
+        SortedMap<String, OptionDescriptor> sortedOptions = options;
+        for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
+            e.getKey();
+            OptionDescriptor desc = e.getValue();
+            Object value = desc.getOptionValue().getValue();
+            List<String> helpLines = wrap(desc.getHelp(), 70);
+            System.out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
+            for (int i = 1; i < helpLines.size(); i++) {
+                System.out.println(String.format("%67s %s", " ", helpLines.get(i)));
+            }
+        }
+
+        System.exit(0);
+    }
+
+    /**
+     * Compute string similarity based on Dice's coefficient.
+     *
+     * Ported from str_similar() in globals.cpp.
+     */
+    static float stringSimiliarity(String str1, String str2) {
+        int hit = 0;
+        for (int i = 0; i < str1.length() - 1; ++i) {
+            for (int j = 0; j < str2.length() - 1; ++j) {
+                if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) {
+                    ++hit;
+                    break;
+                }
+            }
+        }
+        return 2.0f * hit / (str1.length() + str2.length());
+    }
+
+    private static final float FUZZY_MATCH_THRESHOLD = 0.7F;
+
+    /**
+     * Returns the set of options that fuzzy match a given option name.
+     */
+    private static List<OptionDescriptor> fuzzyMatch(String optionName) {
+        List<OptionDescriptor> matches = new ArrayList<>();
+        for (Map.Entry<String, OptionDescriptor> e : OptionsLoader.options.entrySet()) {
+            float score = stringSimiliarity(e.getKey(), optionName);
+            if (score >= FUZZY_MATCH_THRESHOLD) {
+                matches.add(e.getValue());
+            }
+        }
+        return matches;
+    }
+}
--- a/make/defs.make	Mon Aug 03 15:19:14 2015 +0200
+++ b/make/defs.make	Tue Aug 04 00:47:34 2015 +0200
@@ -348,7 +348,6 @@
 EXPORT_JRE_LIB_EXT_DIR = $(EXPORT_JRE_LIB_DIR)/ext
 EXPORT_JRE_LIB_JVMCI_DIR = $(EXPORT_JRE_LIB_DIR)/jvmci
 EXPORT_JRE_LIB_JVMCI_SERVICES_DIR = $(EXPORT_JRE_LIB_JVMCI_DIR)/services
-EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR = $(EXPORT_JRE_LIB_JVMCI_DIR)/options
 EXPORT_JRE_LIB_ARCH_DIR = $(EXPORT_JRE_LIB_DIR)/$(LIBARCH)
 
 # non-universal macosx builds need to appear universal
@@ -374,13 +373,6 @@
 CONDITIONAL_EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/jdk.internal.jvmci.hotspot.events.EventProvider
 endif
 
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.compiler.Compiler
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotConstantPool
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotConstantReflectionProvider
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotResolvedJavaFieldImpl
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/jdk.internal.jvmci.hotspot.HotSpotResolvedJavaMethodImpl
-
 # The use of CONDITIONAL_EXPORT_LIST is for the checking
 # done by verify_defs_make in jvmci.make
 EXPORT_LIST += $(CONDITIONAL_EXPORT_LIST)
--- a/make/jvmci.make	Mon Aug 03 15:19:14 2015 +0200
+++ b/make/jvmci.make	Tue Aug 04 00:47:34 2015 +0200
@@ -53,18 +53,17 @@
     $(eval options := $(1)/$(OPTIONS_INF))
     $(eval services := $(1)/META-INF/services)
     $(QUIETLY) test -d $(services) || mkdir -p $(services)
-    $(QUIETLY) test ! -d $(options) || (cd $(options) && for i in $$(ls); do echo $${i}_Options >> $(abspath $(services))/jdk.internal.jvmci.options.Options; done)
+    $(QUIETLY) test ! -d $(options) || (cd $(options) && for i in $$(ls); do echo $${i}_OptionDescriptors >> $(abspath $(services))/jdk.internal.jvmci.options.Options; done)
 endef
 
-# Extracts META-INF/jvmci.services and META-INF/jvmci.options of a JAR file into a given directory
+# Extracts META-INF/jvmci.services from a JAR file into a given directory
 # Arguments:
 #  1: JAR file to extract
 #  2: target directory (which already exists)
 define extract
     $(eval TMP := $(shell mktemp -d $(TARGET)/tmp_XXXXX))
     $(QUIETLY) cd $(TMP) && $(JAR) xf $(abspath $(1)) && \
-        ((test ! -d .$(SERVICES_INF) || cp -r .$(SERVICES_INF) $(abspath $(2))) && \
-         (test ! -d .$(OPTIONS_INF) || cp -r .$(OPTIONS_INF) $(abspath $(2))));
+         (test ! -d .$(SERVICES_INF) || cp -r .$(SERVICES_INF) $(abspath $(2)));
     $(QUIETLY) rm -r $(TMP);
     $(QUIETLY) cp $(1) $(2)
 endef
@@ -87,11 +86,11 @@
     $(QUIETLY) rm -r $(TMP)
 endef
 
-# Verifies that make/defs.make contains an appropriate line for each JVMCI service or option
-# and that only existing JVMCI services and options are exported.
+# Verifies that make/defs.make contains an appropriate line for each JVMCI service
+# and that only existing JVMCI services are exported.
 # Arguments:
-#  1: list of service or option files
-#  2: variable name for directory of service or option files
+#  1: list of service files
+#  2: variable name for directory of service files
 define verify_defs_make
     $(eval defs := make/defs.make)
     $(eval uncondPattern := EXPORT_LIST += $$$$($(2))/)
@@ -110,7 +109,6 @@
 
 export: all
 	$(call verify_defs_make,$(notdir $(wildcard $(SHARED_DIR)/jvmci.services/*)),EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)
-	$(call verify_defs_make,$(notdir $(wildcard $(SHARED_DIR)/jvmci.options/*)),EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)
 .PHONY: export
 
 clean:
@@ -128,7 +126,8 @@
 
 EXPORTED_FILES += $(JVMCI_SERVICE_JAR)
 
-JVMCI_OPTIONS_SRC = $(shell find jvmci/jdk.internal.jvmci.options/src -type f 2> /dev/null)
+JVMCI_OPTIONS_SRC = $(shell find jvmci/jdk.internal.jvmci.inittimer/src -type f 2> /dev/null)
+JVMCI_OPTIONS_SRC += $(shell find jvmci/jdk.internal.jvmci.options/src -type f 2> /dev/null)
 
 JVMCI_OPTIONS_JAR = $(TARGET)/jvmci-options.jar
 
--- a/mx.jvmci/mx_jvmci.py	Mon Aug 03 15:19:14 2015 +0200
+++ b/mx.jvmci/mx_jvmci.py	Tue Aug 04 00:47:34 2015 +0200
@@ -1058,6 +1058,24 @@
     exe = join(jdk, 'bin', mx.exe_suffix('java'))
     pfx = _vm_prefix.split() if _vm_prefix is not None else []
 
+    # Support for legacy -G: options
+    jvmciArgs = []
+    nonJvmciArgs = []
+    existingJvmciOptionsProperty = None
+    for a in args:
+        if a.startswith('-G:'):
+            jvmciArg = a[len('-G:'):]
+            assert ' ' not in jvmciArg, 'space not supported in JVMCI arg: ' + a
+            jvmciArgs.append(a[len('-G:'):])
+        else:
+            if a.startswith('-Djvmci.options=') or a == '-Djvmci.options':
+                existingJvmciOptionsProperty = a
+            nonJvmciArgs.append(a)
+    if jvmciArgs:
+        if existingJvmciOptionsProperty:
+            mx.abort('defining jvmci.option property is incompatible with defining one or more -G: options: ' + existingJvmciOptionsProperty)
+        args = ['-Djvmci.options=' + ' '.join(jvmciArgs)] + nonJvmciArgs
+
     if '-version' in args:
         ignoredArgs = args[args.index('-version') + 1:]
         if  len(ignoredArgs) > 0:
@@ -1696,9 +1714,9 @@
             # jdk.internal.jvmci.options.Options service created by
             # jdk.internal.jvmci.options.processor.OptionProcessor.
             optionsOwner = arcname[len('META-INF/jvmci.options/'):]
-            provider = optionsOwner + '_Options'
+            provider = optionsOwner + '_OptionDescriptors'
             self.expectedOptionsProviders.add(provider.replace('.', '/') + '.class')
-            self.services.setdefault('jdk.internal.jvmci.options.Options', []).append(provider)
+            self.services.setdefault('jdk.internal.jvmci.options.OptionDescriptors', []).append(provider)
         return False
 
     def __addsrc__(self, arcname, contents):
--- a/mx.jvmci/mx_jvmci_makefile.py	Mon Aug 03 15:19:14 2015 +0200
+++ b/mx.jvmci/mx_jvmci_makefile.py	Tue Aug 04 00:47:34 2015 +0200
@@ -186,18 +186,17 @@
     $(eval options := $(1)/$(OPTIONS_INF))
     $(eval services := $(1)/META-INF/services)
     $(QUIETLY) test -d $(services) || mkdir -p $(services)
-    $(QUIETLY) test ! -d $(options) || (cd $(options) && for i in $$(ls); do echo $${i}_Options >> $(abspath $(services))/jdk.internal.jvmci.options.Options; done)
+    $(QUIETLY) test ! -d $(options) || (cd $(options) && for i in $$(ls); do echo $${i}_OptionDescriptors >> $(abspath $(services))/jdk.internal.jvmci.options.Options; done)
 endef
 
-# Extracts META-INF/jvmci.services and META-INF/jvmci.options of a JAR file into a given directory
+# Extracts META-INF/jvmci.services from a JAR file into a given directory
 # Arguments:
 #  1: JAR file to extract
 #  2: target directory (which already exists)
 define extract
     $(eval TMP := $(shell mktemp -d $(TARGET)/tmp_XXXXX))
     $(QUIETLY) cd $(TMP) && $(JAR) xf $(abspath $(1)) && \\
-        ((test ! -d .$(SERVICES_INF) || cp -r .$(SERVICES_INF) $(abspath $(2))) && \\
-         (test ! -d .$(OPTIONS_INF) || cp -r .$(OPTIONS_INF) $(abspath $(2))));
+         (test ! -d .$(SERVICES_INF) || cp -r .$(SERVICES_INF) $(abspath $(2)));
     $(QUIETLY) rm -r $(TMP);
     $(QUIETLY) cp $(1) $(2)
 endef
@@ -220,11 +219,11 @@
     $(QUIETLY) rm -r $(TMP)
 endef
 
-# Verifies that make/defs.make contains an appropriate line for each JVMCI service or option
-# and that only existing JVMCI services and options are exported.
+# Verifies that make/defs.make contains an appropriate line for each JVMCI service
+# and that only existing JVMCI services are exported.
 # Arguments:
-#  1: list of service or option files
-#  2: variable name for directory of service or option files
+#  1: list of service files
+#  2: variable name for directory of service files
 define verify_defs_make
     $(eval defs := make/defs.make)
     $(eval uncondPattern := EXPORT_LIST += $$$$($(2))/)
@@ -243,7 +242,6 @@
 
 export: all
 \t$(call verify_defs_make,$(notdir $(wildcard $(SHARED_DIR)/jvmci.services/*)),EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)
-\t$(call verify_defs_make,$(notdir $(wildcard $(SHARED_DIR)/jvmci.options/*)),EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)
 .PHONY: export
 
 clean:
--- a/mx.jvmci/suite.py	Mon Aug 03 15:19:14 2015 +0200
+++ b/mx.jvmci/suite.py	Tue Aug 04 00:47:34 2015 +0200
@@ -110,10 +110,19 @@
       "workingSets" : "API,JVMCI",
     },
 
+    "jdk.internal.jvmci.inittimer" : {
+      "subDir" : "jvmci",
+      "sourceDirs" : ["src"],
+      "checkstyle" : "jdk.internal.jvmci.service",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI",
+    },
+
     "jdk.internal.jvmci.options" : {
       "subDir" : "jvmci",
       "sourceDirs" : ["src"],
       "checkstyle" : "jdk.internal.jvmci.service",
+      "dependencies" : ["jdk.internal.jvmci.inittimer"],
       "javaCompliance" : "1.8",
       "workingSets" : "JVMCI",
     },
@@ -341,6 +350,7 @@
       "subDir" : "jvmci",
       "sourcesPath" : "build/jvmci-api.src.zip",
       "dependencies" : [
+        "jdk.internal.jvmci.inittimer",
         "jdk.internal.jvmci.runtime",
         "jdk.internal.jvmci.common",
         "jdk.internal.jvmci.compiler",
--- a/src/share/vm/jvmci/jvmciHashtable.cpp	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-#include "precompiled.hpp"
-#include "jvmci/jvmciHashtable.hpp"
-
-template<class K, class V> bool JVMCIHashtable<K,V>::add(V value, bool replace) {
-  K key = get_key(value);
-  unsigned int hash = compute_hash(key);
-  unsigned int index = hash_to_index(hash);
-  for (JVMCIHashtableEntry<V>* e = bucket(index); e != NULL; e = e->next()) {
-    if (key_equals(get_key(e->literal_addr()), key)) {
-      if (replace) {
-        e->set_literal(value);
-      }
-      return false;
-    }
-  }
-  JVMCIHashtableEntry<V>* e = new JVMCIHashtableEntry<V>(value);
-  e->set_next(_buckets[index]);
-  _buckets[index] = e;
-  ++_number_of_entries;
-  return true;
-}
-
-template<class K, class V> V* JVMCIHashtable<K,V>::get(K key) {
-  unsigned int index = index_for(key);
-  for (JVMCIHashtableEntry<V>* e = bucket(index); e != NULL; e = e->next()) {
-    if (key_equals(get_key(e->literal_addr()), key)) {
-      return e->literal_addr();
-    }
-  }
-  return NULL;
-}
-
-template<class K, class V> void JVMCIHashtable<K, V>::for_each(ValueClosure<V>* closure) {
-  for (size_t i = 0; i < table_size(); ++i) {
-    for (JVMCIHashtableEntry<V>* e = bucket((int)i); e != NULL && !closure->is_aborted(); e = e->next()) {
-      closure->do_value(e->literal_addr());
-    }
-  }
-}
-
-template<class K, class V> JVMCIHashtable<K,V>::~JVMCIHashtable() {
-  for (size_t i = 0; i < table_size(); ++i) {
-    JVMCIHashtableEntry<V>* e = bucket((int)i);
-    while (e != NULL) {
-      JVMCIHashtableEntry<V>* current = e;
-      e = e->next();
-      delete current;
-    }
-  }
-  FREE_C_HEAP_ARRAY(JVMCIHashtableEntry*, _buckets, mtCompiler);
-}
-
-// Instantiation
-#include "jvmci/jvmciOptions.hpp"
-template class JVMCIHashtable<const char*, OptionDesc>;
-template class JVMCIHashtable<const char*, OptionValue>;
--- a/src/share/vm/jvmci/jvmciHashtable.hpp	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-#ifndef SHARE_VM_JVMCI_JVMCI_HASHTABLE_HPP
-#define SHARE_VM_JVMCI_JVMCI_HASHTABLE_HPP
-
-#include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-
-// based on hashtable.hpp
-
-template <class T> class JVMCIHashtableEntry : public CHeapObj<mtCompiler> {
-  friend class VMStructs;
-private:
-  T               _literal;       // ref to item in table.
-  JVMCIHashtableEntry*  _next;          // Link to next element in the linked list for this bucket
-
-public:
-  JVMCIHashtableEntry(T literal) :  _literal(literal), _next(NULL) {}
-
-  T literal() {
-    return _literal;
-  }
-
-  void set_literal(T value) {
-    _literal = value;
-  }
-
-  T* literal_addr() {
-    return &_literal;
-  }
-
-  JVMCIHashtableEntry* next() const {
-    return _next;
-  }
-
-  void set_next(JVMCIHashtableEntry* next) {
-    _next = next;
-  }
-};
-
-template <class V>
-class ValueClosure : public StackObj {
-  bool _abort;
-protected:
-  void abort() { _abort = true; }
-public:
-  ValueClosure() : _abort(false) {}
-  virtual void do_value(V* value) = 0;
-  bool is_aborted() { return _abort; }
-};
-
-template <class K, class V> class JVMCIHashtable : public CHeapObj<mtCompiler> {
-  friend class VMStructs;
-private:
-  // Instance variables
-  unsigned int             _table_size;
-  JVMCIHashtableEntry<V>** _buckets;
-  unsigned int             _number_of_entries;
-
-public:
-  JVMCIHashtable(size_t size) : _table_size((int)size), _number_of_entries(0) {
-    _buckets = NEW_C_HEAP_ARRAY(JVMCIHashtableEntry<V>*, table_size(), mtCompiler);
-    for (size_t i = 0; i < table_size(); ++i) {
-      _buckets[i] = NULL;
-    }
-  }
-  virtual ~JVMCIHashtable();
-
-private:
-  // Bucket handling
-  unsigned int hash_to_index(unsigned int full_hash) {
-    unsigned int h = full_hash % _table_size;
-    assert(h >= 0 && h < _table_size, "Illegal hash value");
-    return h;
-  }
-
-  unsigned  int index_for(K key) {
-    return hash_to_index(compute_hash(key));
-  }
-
-  size_t entry_size() {
-    return sizeof(V);
-  }
-
-  size_t table_size() { return _table_size; }
-
-  JVMCIHashtableEntry<V>* bucket(unsigned int index) {
-    return _buckets[index];
-  }
-
-  bool add(V v, bool replace);
-
-protected:
-  virtual unsigned int compute_hash(K key) = 0;
-  virtual bool key_equals(K k1, K k2) = 0;
-  virtual K get_key(V value) = 0;
-  virtual K get_key(V* value) = 0;
-
-public:
-  /**
-   * Tries to insert the value in the hash table. Returns false if an entry with the same key already exists.
-   * In this case it does *not* replace the existing entry.
-   */
-  bool add(V v) { return add(v, false); }
-  /**
-   * Inserts the value in the hash table. Returns false if an entry with the same key already exists.
-   * In this case it replaces the existing entry.
-   */
-  bool put(V v) { return add(v, true); }
-  V* get(K k);
-  void for_each(ValueClosure<V>* closure);
-  int number_of_entries() { return _number_of_entries; }
-
-};
-
-#endif // SHARE_VM_JVMCI_JVMCI_HASHTABLE_HPP
--- a/src/share/vm/jvmci/jvmciOptions.cpp	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-#include "precompiled.hpp"
-#include "jvmci/jvmciOptions.hpp"
-#include "jvmci/jvmciRuntime.hpp"
-#include "runtime/arguments.hpp"
-#include "utilities/hashtable.inline.hpp"
-
-class OptionDescParseClosure : public ParseClosure {
-  OptionDescsTable* _table;
-public:
-  OptionDescParseClosure(OptionDescsTable* table) : _table(table) {}
-  void do_line(char* line) {
-    char* idx = strchr(line, '\t');
-    if (idx == NULL) {
-      warn_and_abort("invalid format: could not find first tab");
-      return;
-    }
-    *idx = '\0';
-    char* name = line;
-    line = idx + 1;
-    idx = strchr(line, '\t');
-    if (idx == NULL) {
-      warn_and_abort("invalid format: could not find second tab");
-      return;
-    }
-    *idx = '\0';
-    if (strlen(line) != 1) {
-      warn_and_abort("invalid format: type should be 1 char long");
-      return;
-    }
-    char typeChar = *line;
-    line = idx + 1;
-    idx = strchr(line, '\t');
-    if (idx == NULL) {
-      warn_and_abort("invalid format: could not find third tab");
-      return;
-    }
-    *idx = '\0';
-    char* help = line;
-    line = idx + 1;
-    idx = strchr(line, '\t');
-    if (idx == NULL) {
-      warn_and_abort("invalid format: could not find fourth tab");
-      return;
-    }
-    *idx = '\0';
-    char* declaringClass = line;
-    line = idx + 1;
-    char* fieldClass = line;
-    OptionType type;
-    switch(typeChar) {
-      case 's':
-        type = _string;
-        break;
-      case 'i':
-        type = _int;
-        break;
-      case 'j':
-        type = _long;
-        break;
-      case 'f':
-        type = _float;
-        break;
-      case 'd':
-        type = _double;
-        break;
-      case 'z':
-        type = _boolean;
-        break;
-      default:
-        warn_and_abort("unknown type");
-        return;
-    }
-    char* name2 = NEW_C_HEAP_ARRAY(char, (strlen(name) + 1 + strlen(help) + 1 + strlen(declaringClass) + 1 + strlen(fieldClass) + 1), mtCompiler);
-    char* help2 = name2 + strlen(name) + 1;
-    char* declaringClass2 = help2 + strlen(help) + 1;
-    char* fieldClass2 = declaringClass2 + strlen(declaringClass) + 1;
-    strcpy(name2, name);
-    strcpy(help2, help);
-    strcpy(declaringClass2, declaringClass);
-    strcpy(fieldClass2, fieldClass);
-    OptionDesc desc = {name2, help2, type, declaringClass2, fieldClass2};
-    if (!_table->add(desc)) {
-      warn_and_abort("duplicate option");
-      return;
-    }
-  }
-};
-
-class FreeNamesClosure : public ValueClosure<OptionDesc> {
-  void do_value(OptionDesc* desc) {
-    if (desc->declaringClass == NULL) {
-      return; //skip pseudo-options whose name is not allocated with malloc
-    }
-    FREE_C_HEAP_ARRAY(char, desc->name, mtCompiler);
-  }
-};
-
-OptionDescsTable::~OptionDescsTable() {
-  FreeNamesClosure closure;
-  for_each(&closure);
-}
-
-OptionDescsTable* OptionDescsTable::load_options() {
-  OptionDescsTable* table = new OptionDescsTable();
-  // Add PrintFlags option manually
-  OptionDesc printFlagsDesc;
-  printFlagsDesc.name = PRINT_FLAGS_ARG;
-  printFlagsDesc.type = _boolean;
-  printFlagsDesc.help = PRINT_FLAGS_HELP;
-  printFlagsDesc.declaringClass = NULL;
-  printFlagsDesc.fieldClass = NULL;
-  table->add(printFlagsDesc);
-
-  char optionsDir[JVM_MAXPATHLEN];
-  const char* fileSep = os::file_separator();
-  jio_snprintf(optionsDir, sizeof(optionsDir), "%s%slib%sjvmci%soptions",
-               Arguments::get_java_home(), fileSep, fileSep, fileSep);
-  DIR* dir = os::opendir(optionsDir);
-  if (dir != NULL) {
-    struct dirent *entry;
-    char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(optionsDir), mtInternal);
-    OptionDescParseClosure closure(table);
-    while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL && !closure.is_aborted()) {
-      const char* name = entry->d_name;
-      char optionFilePath[JVM_MAXPATHLEN];
-      jio_snprintf(optionFilePath, sizeof(optionFilePath), "%s%s%s",optionsDir, fileSep, name);
-      JVMCIRuntime::parse_lines(optionFilePath, &closure, false);
-    }
-    FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
-    os::closedir(dir);
-    if (closure.is_aborted()) {
-      delete table;
-      return NULL;
-    }
-    return table;
-  }
-  // TODO(gd) should this be silent?
-  warning("Could not open jvmci options directory (%s)",optionsDir);
-  return table;
-}
-
-OptionDesc* OptionDescsTable::get(const char* name, size_t arglen) {
-  char nameOnly[256];
-  guarantee(arglen < 256, "Max supported option name len is 256");
-  strncpy(nameOnly, name, arglen);
-  nameOnly[arglen] = '\0';
-  return JVMCIHashtable<const char*, OptionDesc>::get(nameOnly);
-}
-
-// Compute string similarity based on Dice's coefficient
-static float str_similar(const char* str1, const char* str2) {
-  size_t len1 = strlen(str1);
-  size_t len2 = strlen(str2);
-
-  if (len1 == 0 || len2 == 0) {
-    return 0;
-  }
-
-  int hits = 0;
-  for (size_t i = 0; i < len1 - 1; ++i) {
-    for (size_t j = 0; j < len2 -1; ++j) {
-      if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) {
-        ++hits;
-        break;
-      }
-    }
-  }
-
-  size_t total = len1 + len2;
-  return 2.0f * (float) hits / (float) total;
-}
-
-float VMOptionsFuzzyMatchSimilarity = 0.7f;
-
-class FuzzyMatchClosure : public ValueClosure<OptionDesc> {
-  OptionDesc* _match;
-  float _max_score;
-  const char* _name;
-public:
-  FuzzyMatchClosure(const char* name) : _name(name), _match(NULL), _max_score(-1) {}
-  void do_value(OptionDesc* value) {
-    float score = str_similar(value->name, _name);
-    if (score > VMOptionsFuzzyMatchSimilarity && score > _max_score) {
-      _max_score = score;
-      _match = value;
-    }
-  }
-  OptionDesc* get_match() {
-    return _match;
-  }
-};
-
-OptionDesc * OptionDescsTable::fuzzy_match(const char* name, size_t length) {
-  FuzzyMatchClosure closure(name);
-  for_each(&closure);
-  return closure.get_match();
-}
-
-class FreeStringsClosure : public ValueClosure<OptionValue> {
-  void do_value(OptionValue* value) {
-    if (value->desc.type == _string) {
-      FREE_C_HEAP_ARRAY(char, value->string_value, mtCompiler);
-    }
-  }
-};
-
-OptionValuesTable::~OptionValuesTable() {
-  FreeStringsClosure closure;
-  for_each(&closure);
-  delete _table;
-}
-
-
-
-OptionValue* OptionValuesTable::get(const char* name, size_t arglen) {
-  char nameOnly[256];
-  guarantee(arglen < 256, "Max supported option name len is 256");
-  strncpy(nameOnly, name, arglen);
-  nameOnly[arglen] = '\0';
-  return JVMCIHashtable<const char*, OptionValue>::get(nameOnly);
-}
--- a/src/share/vm/jvmci/jvmciOptions.hpp	Mon Aug 03 15:19:14 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-#ifndef SHARE_VM_JVMCI_JVMCI_OPTIONS_HPP
-#define SHARE_VM_JVMCI_JVMCI_OPTIONS_HPP
-
-#include "memory/allocation.hpp"
-#include "utilities/exceptions.hpp"
-#include "jvmci/jvmciHashtable.hpp"
-
-#define PRINT_FLAGS_ARG "PrintFlags"
-#define PRINT_FLAGS_HELP "Prints all JVMCI flags (similar to XX's PrintFlagsFinal)"
-
-enum OptionType {
-  _string,
-  _int,
-  _long,
-  _float,
-  _double,
-  _boolean
-};
-
-struct OptionDesc {
-  const char* name;
-  const char* help;
-  OptionType type;
-  const char* declaringClass;
-  const char* fieldClass;
-};
-
-inline unsigned int compute_string_hash(const char *s, int n) {
-  unsigned int val = 0;
-  while (--n >= 0) {
-    val = *s++ + 31 * val;
-  }
-  return val;
-}
-
-class OptionDescsTable : public JVMCIHashtable<const char*, OptionDesc> {
-protected:
-  unsigned int compute_hash(const char* key) { return compute_string_hash(key, (int)strlen(key)); }
-  bool key_equals(const char* k1, const char* k2) { return strcmp(k1, k2) == 0; }
-  const char* get_key(OptionDesc value) { return value.name; } ;
-  const char* get_key(OptionDesc* value) { return value->name; } ;
-public:
-  OptionDescsTable() : JVMCIHashtable<const char*, OptionDesc>(100) {}
-  ~OptionDescsTable();
-  using JVMCIHashtable<const char*, OptionDesc>::get;
-  OptionDesc* get(const char* name, size_t arglen);
-  OptionDesc * fuzzy_match(const char* name, size_t length);
-
-  static OptionDescsTable* load_options();
-};
-
-struct OptionValue {
-  OptionDesc desc;
-  union {
-    const char* string_value;
-    jint int_value;
-    jlong long_value;
-    jfloat float_value;
-    jdouble double_value;
-    jboolean boolean_value;
-  };
-};
-
-class OptionValuesTable : public JVMCIHashtable<const char*, OptionValue> {
-  OptionDescsTable* _table;
-protected:
-  unsigned int compute_hash(const char* key) { return compute_string_hash(key, (int)strlen(key)); }
-  bool key_equals(const char* k1, const char* k2) { return strcmp(k1, k2) == 0; }
-  const char* get_key(OptionValue value) { return value.desc.name; } ;
-  const char* get_key(OptionValue* value) { return value->desc.name; } ;
-public:
-  OptionValuesTable(OptionDescsTable* table) : _table(table), JVMCIHashtable<const char*, OptionValue>(100) {}
-  ~OptionValuesTable();
-  using JVMCIHashtable<const char*, OptionValue>::get;
-  OptionValue* get(const char* name, size_t arglen);
-  OptionDescsTable* options_table() { return _table; }
-};
-
-
-#endif // SHARE_VM_JVMCI_JVMCI_OPTIONS_HPP
--- a/src/share/vm/jvmci/jvmciRuntime.cpp	Mon Aug 03 15:19:14 2015 +0200
+++ b/src/share/vm/jvmci/jvmciRuntime.cpp	Tue Aug 04 00:47:34 2015 +0200
@@ -44,6 +44,7 @@
 
 jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
 bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false;
+const char* JVMCIRuntime::_options = NULL;
 bool JVMCIRuntime::_shutdown_called = false;
 
 void JVMCIRuntime::initialize_natives(JNIEnv *env, jclass c2vmClass) {
@@ -622,7 +623,7 @@
   return value;
 JRT_END
 
-// private static void JVMCIClassLoaderFactory.init()
+// private static void JVMCIClassLoaderFactory.init(ClassLoader loader)
 JVM_ENTRY(void, JVM_InitJVMCIClassLoader(JNIEnv *env, jclass c, jobject loader_handle))
   SystemDictionary::init_jvmci_loader(JNIHandles::resolve(loader_handle));
   SystemDictionary::WKID scan = SystemDictionary::FIRST_JVMCI_WKID;
@@ -643,30 +644,43 @@
   return JNIHandles::make_local(THREAD, JVMCIRuntime::get_service_impls(serviceKlass, THREAD)());
 JVM_END
 
-Handle JVMCIRuntime::callInitializer(const char* className, const char* methodName, const char* returnType) {
+Handle JVMCIRuntime::callInitializer(const char* className, const char* methodName, const char* signature, JavaCallArguments* args) {
   guarantee(!_HotSpotJVMCIRuntime_initialized, "cannot reinitialize HotSpotJVMCIRuntime");
   Thread* THREAD = Thread::current();
 
   TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_ABORT_(Handle()));
   KlassHandle klass = load_required_class(name);
   TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_ABORT_(Handle()));
-  TempNewSymbol sig = SymbolTable::new_symbol(returnType, CHECK_ABORT_(Handle()));
+  TempNewSymbol sig = SymbolTable::new_symbol(signature, CHECK_ABORT_(Handle()));
   JavaValue result(T_OBJECT);
-  JavaCalls::call_static(&result, klass, runtime, sig, CHECK_ABORT_(Handle()));
+  if (args == NULL) {
+    JavaCalls::call_static(&result, klass, runtime, sig, CHECK_ABORT_(Handle()));
+  } else {
+    JavaCalls::call_static(&result, klass, runtime, sig, args, CHECK_ABORT_(Handle()));
+  }
   return Handle((oop)result.get_jobject());
 }
 
 void JVMCIRuntime::initialize_HotSpotJVMCIRuntime() {
   if (JNIHandles::resolve(_HotSpotJVMCIRuntime_instance) == NULL) {
+    Thread* THREAD = Thread::current();
 #ifdef ASSERT
     // This should only be called in the context of the JVMCI class being initialized
-    Thread* THREAD = Thread::current();
     TempNewSymbol name = SymbolTable::new_symbol("jdk/internal/jvmci/runtime/JVMCI", CHECK_ABORT);
     instanceKlassHandle klass = InstanceKlass::cast(load_required_class(name));
     assert(klass->is_being_initialized() && klass->is_reentrant_initialization(THREAD),
            "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization");
 #endif
 
+    if (_options != NULL) {
+      JavaCallArguments args;
+      oop options = java_lang_String::create_oop_from_str(_options, CHECK_ABORT);
+      args.push_oop(options);
+      callInitializer("jdk/internal/jvmci/options/OptionsParser",
+                      "parseOptionsFromVM",
+                      "(Ljava/lang/String;)Ljava/lang/Boolean;", &args);
+    }
+
     Handle result = callInitializer("jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime", "runtime",
                                     "()Ljdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime;");
     _HotSpotJVMCIRuntime_initialized = true;
@@ -782,159 +796,6 @@
   }
 }
 
-OptionValuesTable* JVMCIRuntime::parse_arguments() {
-  OptionDescsTable* table = OptionDescsTable::load_options();
-  if (table == NULL) {
-    return NULL;
-  }
-
-  OptionValuesTable* options = new OptionValuesTable(table);
-
-  // Process option overrides from jvmci.options first
-  parse_jvmci_options_file(options);
-
-  // Now process options on the command line
-  int numOptions = Arguments::num_jvmci_args();
-  for (int i = 0; i < numOptions; i++) {
-    char* arg = Arguments::jvmci_args_array()[i];
-    if (!parse_argument(options, arg)) {
-      delete options;
-      return NULL;
-    }
-  }
-  return options;
-}
-
-void not_found(OptionDescsTable* table, const char* argname, size_t namelen) {
-  jio_fprintf(defaultStream::error_stream(),"Unrecognized VM option '%.*s'\n", namelen, argname);
-  OptionDesc* fuzzy_matched = table->fuzzy_match(argname, strlen(argname));
-  if (fuzzy_matched != NULL) {
-    jio_fprintf(defaultStream::error_stream(),
-                "Did you mean '%s%s%s'?\n",
-                (fuzzy_matched->type == _boolean) ? "(+/-)" : "",
-                fuzzy_matched->name,
-                (fuzzy_matched->type == _boolean) ? "" : "=<value>");
-  }
-}
-
-bool JVMCIRuntime::parse_argument(OptionValuesTable* options, const char* arg) {
-  OptionDescsTable* table = options->options_table();
-  char first = arg[0];
-  const char* name;
-  size_t name_len;
-  if (first == '+' || first == '-') {
-    name = arg + 1;
-    OptionDesc* optionDesc = table->get(name);
-    if (optionDesc == NULL) {
-      not_found(table, name, strlen(name));
-      return false;
-    }
-    if (optionDesc->type != _boolean) {
-      jio_fprintf(defaultStream::error_stream(), "Unexpected +/- setting in VM option '%s'\n", name);
-      return false;
-    }
-    OptionValue value;
-    value.desc = *optionDesc;
-    value.boolean_value = first == '+';
-    options->put(value);
-    return true;
-  } else {
-    const char* sep = strchr(arg, '=');
-    name = arg;
-    const char* value = NULL;
-    if (sep != NULL) {
-      name_len = sep - name;
-      value = sep + 1;
-    } else {
-      name_len = strlen(name);
-    }
-    OptionDesc* optionDesc = table->get(name, name_len);
-    if (optionDesc == NULL) {
-      not_found(table, name, name_len);
-      return false;
-    }
-    if (optionDesc->type == _boolean) {
-      jio_fprintf(defaultStream::error_stream(), "Missing +/- setting for VM option '%s'\n", name);
-      return false;
-    }
-    if (value == NULL) {
-      jio_fprintf(defaultStream::error_stream(), "Must use '-G:%.*s=<value>' format for %.*s option", name_len, name, name_len, name);
-      return false;
-    }
-    OptionValue optionValue;
-    optionValue.desc = *optionDesc;
-    char* check;
-    errno = 0;
-    switch(optionDesc->type) {
-      case _int: {
-        long int int_value = ::strtol(value, &check, 10);
-        if (*check != '\0' || errno == ERANGE || int_value > max_jint || int_value < min_jint) {
-          jio_fprintf(defaultStream::error_stream(), "Expected int value for VM option '%s'\n", name);
-          return false;
-        }
-        optionValue.int_value = int_value;
-        break;
-      }
-      case _long: {
-        long long int long_value = ::strtoll(value, &check, 10);
-        if (*check != '\0' || errno == ERANGE || long_value > max_jlong || long_value < min_jlong) {
-          jio_fprintf(defaultStream::error_stream(), "Expected long value for VM option '%s'\n", name);
-          return false;
-        }
-        optionValue.long_value = long_value;
-        break;
-      }
-      case _float: {
-        optionValue.float_value = (float)::strtod(value, &check); //strtof not available in Windows SDK yet
-        if (*check != '\0' || errno == ERANGE) {
-          jio_fprintf(defaultStream::error_stream(), "Expected float value for VM option '%s'\n", name);
-          return false;
-        }
-        break;
-      }
-      case _double: {
-        optionValue.double_value = ::strtod(value, &check);
-        if (*check != '\0' || errno == ERANGE) {
-          jio_fprintf(defaultStream::error_stream(), "Expected double value for VM option '%s'\n", name);
-          return false;
-        }
-        break;
-      }
-      case _string: {
-        char* copy = NEW_C_HEAP_ARRAY(char, strlen(value) + 1, mtCompiler);
-        strcpy(copy, value);
-        optionValue.string_value = copy;
-        break;
-      }
-      default:
-        ShouldNotReachHere();
-    }
-    options->put(optionValue);
-    return true;
-  }
-}
-
-class JVMCIOptionParseClosure : public ParseClosure {
-  OptionValuesTable* _options;
-public:
-  JVMCIOptionParseClosure(OptionValuesTable* options) : _options(options) {}
-  void do_line(char* line) {
-    if (!JVMCIRuntime::parse_argument(_options, line)) {
-      warn("There was an error parsing an argument. Skipping it.");
-    }
-  }
-};
-
-void JVMCIRuntime::parse_jvmci_options_file(OptionValuesTable* options) {
-  const char* home = Arguments::get_java_home();
-  size_t path_len = strlen(home) + strlen("/lib/jvmci.options") + 1;
-  char path[JVM_MAXPATHLEN];
-  char sep = os::file_separator()[0];
-  jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cjvmci.options", home, sep, sep);
-  JVMCIOptionParseClosure closure(options);
-  parse_lines(path, &closure, false);
-}
-
 #define CHECK_WARN_ABORT_(message) THREAD); \
   if (HAS_PENDING_EXCEPTION) { \
     warning(message); \
@@ -945,149 +806,10 @@
   } \
   (void)(0
 
-class SetOptionClosure : public ValueClosure<OptionValue> {
-  Thread* _thread;
-public:
-  SetOptionClosure(TRAPS) : _thread(THREAD) {}
-  void do_value(OptionValue* optionValue) {
-    TRAPS = _thread;
-    const char* declaringClass = optionValue->desc.declaringClass;
-    if (declaringClass == NULL) {
-      // skip PrintFlags pseudo-option
-      return;
-    }
-    const char* fieldName = optionValue->desc.name;
-    const char* fieldClass = optionValue->desc.fieldClass;
-
-    size_t fieldSigLen = 2 + strlen(fieldClass);
-    char* fieldSig = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, fieldSigLen + 1);
-    jio_snprintf(fieldSig, fieldSigLen + 1, "L%s;", fieldClass);
-    for (size_t i = 0; i < fieldSigLen; ++i) {
-      if (fieldSig[i] == '.') {
-        fieldSig[i] = '/';
-      }
-    }
-    fieldSig[fieldSigLen] = '\0';
-    size_t declaringClassLen = strlen(declaringClass);
-    char* declaringClassBinary = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, declaringClassLen + 1);
-    for (size_t i = 0; i < declaringClassLen; ++i) {
-      if (declaringClass[i] == '.') {
-        declaringClassBinary[i] = '/';
-      } else {
-        declaringClassBinary[i] = declaringClass[i];
-      }
-    }
-    declaringClassBinary[declaringClassLen] = '\0';
-
-    TempNewSymbol name = SymbolTable::new_symbol(declaringClassBinary, CHECK_WARN_ABORT_("Declaring class could not be found"));
-    Klass* klass = JVMCIRuntime::resolve_or_null(name, CHECK_WARN_ABORT_("Declaring class could not be resolved"));
-
-    if (klass == NULL) {
-      warning("Declaring class for option %s could not be resolved", declaringClass);
-      abort();
-      return;
-    }
-
-    // The class has been loaded so the field and signature should already be in the symbol
-    // table.  If they're not there, the field doesn't exist.
-    TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName));
-    TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)fieldSigLen);
-    if (fieldname == NULL || signame == NULL) {
-      warning("Symbols for field for option %s not found (in %s)", fieldName, declaringClass);
-      abort();
-      return;
-    }
-    // Make sure class is initialized before handing id's out to fields
-    klass->initialize(CHECK_WARN_ABORT_("Error while initializing declaring class for option"));
-
-    fieldDescriptor fd;
-    if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) {
-      warning("Field for option %s not found (in %s)", fieldName, declaringClass);
-      abort();
-      return;
-    }
-    oop value;
-    switch(optionValue->desc.type) {
-    case _boolean: {
-      jvalue jv;
-      jv.z = optionValue->boolean_value;
-      value = java_lang_boxing_object::create(T_BOOLEAN, &jv, THREAD);
-      break;
-    }
-    case _int: {
-      jvalue jv;
-      jv.i = optionValue->int_value;
-      value = java_lang_boxing_object::create(T_INT, &jv, THREAD);
-      break;
-    }
-    case _long: {
-      jvalue jv;
-      jv.j = optionValue->long_value;
-      value = java_lang_boxing_object::create(T_LONG, &jv, THREAD);
-      break;
-    }
-    case _float: {
-      jvalue jv;
-      jv.f = optionValue->float_value;
-      value = java_lang_boxing_object::create(T_FLOAT, &jv, THREAD);
-      break;
-    }
-    case _double: {
-      jvalue jv;
-      jv.d = optionValue->double_value;
-      value = java_lang_boxing_object::create(T_DOUBLE, &jv, THREAD);
-      break;
-    }
-    case _string:
-      value = java_lang_String::create_from_str(optionValue->string_value, THREAD)();
-      break;
-    default:
-      ShouldNotReachHere();
-    }
-
-    oop optionValueOop = klass->java_mirror()->obj_field(fd.offset());
-
-    if (optionValueOop == NULL) {
-      warning("Option field was null, can not set %s", fieldName);
-      abort();
-      return;
-    }
-
-    if (!InstanceKlass::cast(optionValueOop->klass())->find_field(vmSymbols::value_name(), vmSymbols::object_signature(), false, &fd)) {
-      warning("'Object value' field not found in option class %s, can not set option %s", fieldClass, fieldName);
-      abort();
-      return;
-    }
-
-    optionValueOop->obj_field_put(fd.offset(), value);
-  }
-};
-
-void JVMCIRuntime::set_options(OptionValuesTable* options, TRAPS) {
-  ensure_jvmci_class_loader_is_initialized();
-  {
-    ResourceMark rm;
-    SetOptionClosure closure(THREAD);
-    options->for_each(&closure);
-    if (closure.is_aborted()) {
-      vm_abort(false);
-    }
-  }
-  OptionValue* printFlags = options->get(PRINT_FLAGS_ARG);
-  if (printFlags != NULL && printFlags->boolean_value) {
-    print_flags_helper(CHECK_ABORT);
-  }
-}
-
-void JVMCIRuntime::print_flags_helper(TRAPS) {
-  // TODO(gd) write this in C++?
-  HandleMark hm(THREAD);
-  TempNewSymbol name = SymbolTable::new_symbol("jdk/internal/jvmci/hotspot/HotSpotOptions", CHECK_ABORT);
-  KlassHandle hotSpotOptionsClass = load_required_class(name);
-  TempNewSymbol setOption = SymbolTable::new_symbol("printFlags", CHECK);
-  JavaValue result(T_VOID);
-  JavaCallArguments args;
-  JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, vmSymbols::void_method_signature(), &args, CHECK);
+void JVMCIRuntime::save_options(const char* options) {
+  assert(options != NULL, "npe");
+  assert(_options == NULL, "cannot reassign JVMCI options");
+  _options = options;
 }
 
 Handle JVMCIRuntime::create_Service(const char* name, TRAPS) {
--- a/src/share/vm/jvmci/jvmciRuntime.hpp	Mon Aug 03 15:19:14 2015 +0200
+++ b/src/share/vm/jvmci/jvmciRuntime.hpp	Tue Aug 04 00:47:34 2015 +0200
@@ -28,7 +28,6 @@
 #include "memory/allocation.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/deoptimization.hpp"
-#include "jvmci/jvmciOptions.hpp"
 
 class ParseClosure : public StackObj {
   int _lineNo;
@@ -59,20 +58,11 @@
  private:
   static jobject _HotSpotJVMCIRuntime_instance;
   static bool _HotSpotJVMCIRuntime_initialized;
+  static const char* _options;
 
   static bool _shutdown_called;
 
   /**
-   * Loads default option value overrides from a <jre_home>/lib/jvmci.options if it exists. Each
-   * line in this file must have the format of a JVMCI command line option without the
-   * leading "-G:" prefix. These option values are set prior to processing of any JVMCI
-   * options present on the command line.
-   */
-  static void parse_jvmci_options_file(OptionValuesTable* options);
-
-  static void print_flags_helper(TRAPS);
-
-  /**
    * Instantiates a service object, calls its default constructor and returns it.
    *
    * @param name the name of a class implementing jdk.internal.jvmci.service.Service
@@ -87,14 +77,10 @@
   static void parse_properties(SystemProperty** plist);
 
   /**
-   * Parses the JVMCI specific VM options that were presented by the launcher and sets
-   * the relevants Java fields.
+   * Saves the value of the "jvmci.options" system property for processing
+   * when JVMCI is initialized.
    */
-  static OptionValuesTable* parse_arguments();
-
-  static bool parse_argument(OptionValuesTable* options, const char* arg);
-
-  static void set_options(OptionValuesTable* options, TRAPS);
+  static void save_options(const char* options);
 
   /**
    * Ensures that the JVMCI class loader is initialized and the well known JVMCI classes are loaded.
@@ -119,7 +105,7 @@
     return _HotSpotJVMCIRuntime_instance;
   }
 
-  static Handle callInitializer(const char* className, const char* methodName, const char* returnType);
+  static Handle callInitializer(const char* className, const char* methodName, const char* returnType, JavaCallArguments* args = NULL);
 
   /**
    * Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime()
--- a/src/share/vm/runtime/arguments.cpp	Mon Aug 03 15:19:14 2015 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Tue Aug 04 00:47:34 2015 +0200
@@ -98,10 +98,6 @@
 int     Arguments::_num_jvm_flags               = 0;
 char**  Arguments::_jvm_args_array              = NULL;
 int     Arguments::_num_jvm_args                = 0;
-#if INCLUDE_JVMCI
-char**  Arguments::_jvmci_args_array              = NULL;
-int     Arguments::_num_jvmci_args                = 0;
-#endif
 char*  Arguments::_java_command                 = NULL;
 SystemProperty* Arguments::_system_properties   = NULL;
 const char*  Arguments::_gc_log_filename        = NULL;
@@ -817,11 +813,6 @@
 void Arguments::build_jvm_flags(const char* arg) {
   add_string(&_jvm_flags_array, &_num_jvm_flags, arg);
 }
-#if INCLUDE_JVMCI
-void Arguments::add_jvmci_arg(const char* arg) {
-  add_string(&_jvmci_args_array, &_num_jvmci_args, arg);
-}
-#endif
 
 // utility function to return a string that concatenates all
 // strings in a given char** array
@@ -3389,17 +3380,6 @@
         }
       }
     }
-#if INCLUDE_JVMCI
-    else if (match_option(option, "-G:", &tail)) { // -G:XXX
-      // Option for the JVMCI compiler.
-      if (PrintVMOptions) {
-        tty->print_cr("JVMCI option %s", tail);
-      }
-      Arguments::add_jvmci_arg(tail);
-
-    // Unknown option
-    }
-#endif
     else if (is_bad_option(option, args->ignoreUnrecognized)) {
       return JNI_ERR;
     }
--- a/src/share/vm/runtime/arguments.hpp	Mon Aug 03 15:19:14 2015 +0200
+++ b/src/share/vm/runtime/arguments.hpp	Tue Aug 04 00:47:34 2015 +0200
@@ -246,11 +246,6 @@
   // an array containing all jvm arguments specified in the command line
   static char** _jvm_args_array;
   static int    _num_jvm_args;
-#if INCLUDE_JVMCI
-  // an array containing all JVMCI arguments specified in the command line
-  static char** _jvmci_args_array;
-  static int    _num_jvmci_args;
-#endif
   // string containing all java command (class/jarfile name and app args)
   static char* _java_command;
 
@@ -410,9 +405,6 @@
   // methods to build strings from individual args
   static void build_jvm_args(const char* arg);
   static void build_jvm_flags(const char* arg);
-#if INCLUDE_JVMCI
-  static void add_jvmci_arg(const char* arg);
-#endif
   static void add_string(char*** bldarray, int* count, const char* arg);
   static const char* build_resource_string(char** args, int count);
 
@@ -492,10 +484,6 @@
   // return a char* array containing all options
   static char** jvm_flags_array()          { return _jvm_flags_array; }
   static char** jvm_args_array()           { return _jvm_args_array; }
-#if INCLUDE_JVMCI
-  static char** jvmci_args_array()           { return _jvmci_args_array; }
-  static int num_jvmci_args()               { return _num_jvmci_args; }
-#endif
   static int num_jvm_flags()               { return _num_jvm_flags; }
   static int num_jvm_args()                { return _num_jvm_args; }
   // return the arguments passed to the Java application
--- a/src/share/vm/runtime/thread.cpp	Mon Aug 03 15:19:14 2015 +0200
+++ b/src/share/vm/runtime/thread.cpp	Tue Aug 04 00:47:34 2015 +0200
@@ -3395,13 +3395,6 @@
   jint parse_result = Arguments::parse(args);
   if (parse_result != JNI_OK) return parse_result;
 
-#if INCLUDE_JVMCI
-  OptionValuesTable* options = JVMCIRuntime::parse_arguments();
-  if (options == NULL) {
-    return JNI_ERR;
-  }
-#endif
-
   os::init_before_ergo();
 
   jint ergo_result = Arguments::apply_ergo();
@@ -3710,8 +3703,10 @@
   }
 
 #if INCLUDE_JVMCI
-  JVMCIRuntime::set_options(options, main_thread);
-  delete options;
+  const char* jvmciOptions = Arguments::PropertyList_get_value(Arguments::system_properties(), "jvmci.options");
+  if (jvmciOptions != NULL) {
+    JVMCIRuntime::save_options(jvmciOptions);
+  }
 #endif
 
   // initialize compiler(s)