changeset 21525:fad971028755

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 28 May 2015 21:26:54 +0200
parents 54933d47cfa4 (current diff) 4b3b38415adf (diff)
children 2270a708ef23 8a01110bfbaf
files graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java src/share/vm/graal/graalRuntime.cpp src/share/vm/graal/graalRuntime.hpp
diffstat 60 files changed, 1671 insertions(+), 1179 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu May 28 21:26:54 2015 +0200
@@ -602,11 +602,10 @@
     }
 
     /**
-     * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the assumptions made during
-     * compilation.
+     * Gets the assumptions made during compilation.
      */
-    public Collection<Assumption> getAssumptions() {
-        return assumptions == null ? Collections.emptyList() : Arrays.asList(assumptions);
+    public Assumption[] getAssumptions() {
+        return assumptions;
     }
 
     /**
@@ -641,15 +640,14 @@
     }
 
     /**
-     * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the methods whose bytecodes
-     * were used as input to the compilation.
+     * Gets the methods whose bytecodes were used as input to the compilation.
      *
      * @return {@code null} if the compilation did not record method dependencies otherwise the
      *         methods whose bytecodes were used as input to the compilation with the first element
      *         being the root method of the compilation
      */
-    public Collection<ResolvedJavaMethod> getMethods() {
-        return methods == null ? null : Arrays.asList(methods);
+    public ResolvedJavaMethod[] getMethods() {
+        return methods;
     }
 
     public DataSection getDataSection() {
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Thu May 28 21:26:54 2015 +0200
@@ -63,6 +63,7 @@
             CompilationResult compResult = new CompilationResult();
             byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
             compResult.setTargetCode(targetCode, targetCode.length);
+            compResult.setTotalFrameSize(0);
 
             InstalledCode code = codeCache.addMethod(method, compResult, null, null);
 
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu May 28 21:26:54 2015 +0200
@@ -1269,20 +1269,23 @@
             assert inputVal.getKind().getStackKind() == Kind.Int;
 
             LIRKind resultKind = LIRKind.derive(inputVal);
-            OperandSize resultSize;
             if (toBits > 32) {
                 resultKind = resultKind.changeType(Kind.Long);
-                resultSize = QWORD;
             } else {
                 resultKind = resultKind.changeType(Kind.Int);
-                resultSize = DWORD;
             }
 
+            /*
+             * Always emit DWORD operations, even if the resultKind is Long. On AMD64, all DWORD
+             * operations implicitly set the upper half of the register to 0, which is what we want
+             * anyway. Compared to the QWORD oparations, the encoding of the DWORD operations is
+             * sometimes one byte shorter.
+             */
             switch (fromBits) {
                 case 8:
-                    return emitConvertOp(resultKind, MOVZXB, resultSize, inputVal);
+                    return emitConvertOp(resultKind, MOVZXB, DWORD, inputVal);
                 case 16:
-                    return emitConvertOp(resultKind, MOVZX, resultSize, inputVal);
+                    return emitConvertOp(resultKind, MOVZX, DWORD, inputVal);
                 case 32:
                     return emitConvertOp(resultKind, MOV, DWORD, inputVal);
             }
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Thu May 28 21:26:54 2015 +0200
@@ -327,7 +327,7 @@
     @Option(help = "Enable expensive assertions", type = OptionType.Debug)
     public static final OptionValue<Boolean> DetailedAsserts = new StableOptionValue<Boolean>() {
         @Override
-        protected Boolean initialValue() {
+        protected Boolean defaultValue() {
             boolean enabled = false;
             // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
             assert (enabled = true) == true;
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/RegisterAllocationConfig.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/RegisterAllocationConfig.java	Thu May 28 21:26:54 2015 +0200
@@ -36,6 +36,36 @@
  */
 public class RegisterAllocationConfig {
 
+    public static final class AllocatableRegisters {
+        public final Register[] allocatableRegisters;
+        public final int minRegisterNumber;
+        public final int maxRegisterNumber;
+
+        public AllocatableRegisters(Register[] allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) {
+            this.allocatableRegisters = allocatableRegisters;
+            this.minRegisterNumber = minRegisterNumber;
+            this.maxRegisterNumber = maxRegisterNumber;
+            assert verify(allocatableRegisters, minRegisterNumber, maxRegisterNumber);
+        }
+
+        private static boolean verify(Register[] allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) {
+            int min = Integer.MAX_VALUE;
+            int max = Integer.MIN_VALUE;
+            for (Register reg : allocatableRegisters) {
+                int number = reg.number;
+                if (number < min) {
+                    min = number;
+                }
+                if (number > max) {
+                    max = number;
+                }
+            }
+            assert minRegisterNumber == min;
+            assert maxRegisterNumber == max;
+            return true;
+        }
+    }
+
     public static final String ALL_REGISTERS = "<all>";
 
     private static Register findRegister(String name, Register[] all) {
@@ -47,7 +77,7 @@
         throw new IllegalArgumentException("register " + name + " is not allocatable");
     }
 
-    private static Register[] initAllocatable(Register[] registers) {
+    protected Register[] initAllocatable(Register[] registers) {
         if (RegisterPressure.getValue() != null && !RegisterPressure.getValue().equals(ALL_REGISTERS)) {
             String[] names = RegisterPressure.getValue().split(",");
             Register[] regs = new Register[names.length];
@@ -60,11 +90,12 @@
         return registers;
     }
 
-    private final RegisterConfig registerConfig;
-    private final Map<PlatformKind.Key, Register[]> categorized = new HashMap<>();
+    protected final RegisterConfig registerConfig;
+    private final Map<PlatformKind.Key, AllocatableRegisters> categorized = new HashMap<>();
     private Register[] cachedRegisters;
 
     public RegisterAllocationConfig(RegisterConfig registerConfig) {
+        assert registerConfig != null;
         this.registerConfig = registerConfig;
     }
 
@@ -72,17 +103,19 @@
      * Gets the set of registers that can be used by the register allocator for a value of a
      * particular kind.
      */
-    public Register[] getAllocatableRegisters(PlatformKind kind) {
+    public AllocatableRegisters getAllocatableRegisters(PlatformKind kind) {
         PlatformKind.Key key = kind.getKey();
         if (categorized.containsKey(key)) {
-            Register[] val = categorized.get(key);
+            AllocatableRegisters val = categorized.get(key);
             return val;
         }
-
-        Register[] ret = registerConfig.filterAllocatableRegisters(kind, getAllocatableRegisters());
+        AllocatableRegisters ret = createAllocatableRegisters(registerConfig.filterAllocatableRegisters(kind, getAllocatableRegisters()));
         categorized.put(key, ret);
         return ret;
+    }
 
+    protected AllocatableRegisters createAllocatableRegisters(Register[] registers) {
+        return new AllocatableRegisters(registers, registers[0].number, registers[registers.length - 1].number);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu May 28 21:26:54 2015 +0200
@@ -300,7 +300,7 @@
             }
 
             try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) {
-                return emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, lirGen, lirSuites);
+                return emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig));
             } catch (Throwable e) {
                 throw Debug.handle(e);
             }
@@ -310,11 +310,11 @@
     }
 
     public static <T extends AbstractBlockBase<T>> LIRGenerationResult emitLowLevel(TargetDescription target, List<T> codeEmittingOrder, List<T> linearScanOrder, LIRGenerationResult lirGenRes,
-                    LIRGeneratorTool lirGen, LIRSuites lirSuites) {
+                    LIRGeneratorTool lirGen, LIRSuites lirSuites, RegisterAllocationConfig registerAllocationConfig) {
         PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen);
         lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, preAllocOptContext);
 
-        AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory());
+        AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig);
         lirSuites.getAllocationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, allocContext);
 
         PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu May 28 21:26:54 2015 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
@@ -82,6 +83,8 @@
      */
     public abstract FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig);
 
+    public abstract RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig);
+
     public abstract FrameMap newFrameMap(RegisterConfig registerConfig);
 
     public abstract LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu May 28 21:26:54 2015 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
@@ -324,4 +325,10 @@
         }
     }
 
+    @Override
+    public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) {
+        RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
+        return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull);
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java	Thu May 28 21:26:54 2015 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.alloc.*;
+
+class AMD64HotSpotRegisterAllocationConfig extends RegisterAllocationConfig {
+    /**
+     * Specify priority of register selection within phases of register allocation. Highest priority
+     * is first. A useful heuristic is to give registers a low priority when they are required by
+     * machine instructions, like EAX and EDX on I486, and choose no-save registers before
+     * save-on-call, & save-on-call before save-on-entry. Registers which participate in fixed
+     * calling sequences should come last. Registers which are used as pairs must fall on an even
+     * boundary.
+     *
+     * Adopted from x86_64.ad.
+     */
+    // @formatter:off
+    static final Register[] registerAllocationOrder = {
+        r10, r11, r8, r9, r12, rcx, rbx, rdi, rdx, rsi, rax, rbp, r13, r14, /*r15,*/ /*rsp,*/
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+    };
+    // @formatter:on
+
+    public AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig) {
+        super(registerConfig);
+    }
+
+    @Override
+    protected Register[] initAllocatable(Register[] registers) {
+        BitSet regMap = new BitSet(registerConfig.getAllocatableRegisters().length);
+        Register[] regs = super.initAllocatable(registers);
+        for (Register reg : regs) {
+            regMap.set(reg.number);
+        }
+
+        Register[] allocatableRegisters = new Register[regs.length];
+        int i = 0;
+        for (Register reg : registerAllocationOrder) {
+            if (regMap.get(reg.number)) {
+                allocatableRegisters[i++] = reg;
+            }
+        }
+
+        assert i == allocatableRegisters.length;
+        return allocatableRegisters;
+    }
+
+    @Override
+    protected AllocatableRegisters createAllocatableRegisters(Register[] registers) {
+        int min = Integer.MAX_VALUE;
+        int max = Integer.MIN_VALUE;
+        for (Register reg : registers) {
+            int number = reg.number;
+            if (number < min) {
+                min = number;
+            }
+            if (number > max) {
+                max = number;
+            }
+        }
+        assert min < max;
+        return new AllocatableRegisters(registers, min, max);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java	Thu May 28 21:26:54 2015 +0200
@@ -28,7 +28,7 @@
 
 /**
  * Utility to create and register a separate class loader for loading Graal classes (i.e., those in
- * found in lib/graal/graal*.jar).
+ * found in jars in lib/graal).
  */
 public class Factory {
 
@@ -69,7 +69,7 @@
 
         List<URL> urls = new ArrayList<>();
         for (String fileName : graal.list()) {
-            if (fileName.startsWith("graal") && fileName.endsWith(".jar")) {
+            if (fileName.endsWith(".jar")) {
                 File file = new File(graal, fileName);
                 if (file.isDirectory()) {
                     continue;
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Thu May 28 21:25:21 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,225 +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 com.oracle.graal.hotspot.sourcegen;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.stream.*;
-import java.util.zip.*;
-
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.options.*;
-
-/**
- * Command line utility for generating the source code of {@code graalRuntime.inline.hpp}. The
- * generated code is comprised of:
- * <ul>
- * <li>{@code -G} command line option parsing {@linkplain #genSetOption(PrintStream) helper}</li>
- * </ul>
- *
- * The purpose of the generated code is to avoid executing Graal related Java code as much as
- * possible during initialization of the Graal runtime. Future solutions such as some kind of AOT
- * system may make such a mechanism redundant in terms of minimizing Graal's impact on VM startup
- * time.
- *
- * The input for the generation is all classes that implement {@link Service} or contain fields
- * annotated by {@link Option}. As such, the code generation process must be executed with a class
- * path including all Graal jars that contains such classes. Currently, this is
- * {@code graal-truffle.jar}.
- */
-public class GenGraalRuntimeInlineHpp {
-
-    public static class GraalJars implements Iterable<ZipEntry> {
-        private final List<ZipFile> jars = new ArrayList<>(2);
-
-        public GraalJars() {
-            String classPath = System.getProperty("java.class.path");
-            for (String e : classPath.split(File.pathSeparator)) {
-                if (e.endsWith(File.separatorChar + "graal.jar") || e.endsWith(File.separatorChar + "graal-truffle.jar")) {
-                    try {
-                        jars.add(new ZipFile(e));
-                    } catch (IOException ioe) {
-                        throw new InternalError(ioe);
-                    }
-                }
-            }
-            if (jars.size() != 2) {
-                throw new InternalError("Could not find graal.jar or graal-truffle.jar on class path: " + classPath);
-            }
-        }
-
-        public Iterator<ZipEntry> iterator() {
-            Stream<ZipEntry> entries = jars.stream().flatMap(ZipFile::stream);
-            return entries.iterator();
-        }
-
-        public InputStream getInputStream(String classFilePath) throws IOException {
-            for (ZipFile jar : jars) {
-                ZipEntry entry = jar.getEntry(classFilePath);
-                if (entry != null) {
-                    return jar.getInputStream(entry);
-                }
-            }
-            return null;
-        }
-    }
-
-    private static final GraalJars graalJars = new GraalJars();
-
-    public static void main(String[] args) {
-        PrintStream out = System.out;
-        try {
-            genSetOption(out);
-        } catch (Throwable t) {
-            t.printStackTrace(out);
-        }
-        out.flush();
-    }
-
-    /**
-     * Generates code for {@code GraalRuntime::set_option()} and
-     * {@code GraalRuntime::set_option_bool()}.
-     */
-    private static void genSetOption(PrintStream out) throws Exception {
-        SortedMap<String, OptionDescriptor> options = getOptions();
-
-        Set<Integer> lengths = new TreeSet<>();
-        for (String s : options.keySet()) {
-            lengths.add(s.length());
-        }
-        lengths.add("PrintFlags".length());
-
-        out.println("bool GraalRuntime::set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS) {");
-        out.println("  bool check_only = hotSpotOptionsClass.is_null();");
-        genMatchers(out, lengths, options, true);
-        out.println("  return false;");
-        out.println("}");
-        out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS) {");
-        out.println("  bool check_only = hotSpotOptionsClass.is_null();");
-        genMatchers(out, lengths, options, false);
-        out.println("  return false;");
-        out.println("}");
-    }
-
-    protected static void genMatchers(PrintStream out, Set<Integer> lengths, SortedMap<String, OptionDescriptor> options, boolean isBoolean) throws Exception {
-        out.println("  switch (name_len) {");
-        for (int len : lengths) {
-            boolean printedCase = false;
-
-            // The use of strncmp is required (instead of strcmp) as the option name will not be
-            // null terminated for <name>=<value> style options.
-            if (len == "PrintFlags".length() && isBoolean) {
-                printedCase = true;
-                out.println("  case " + len + ":");
-                out.printf("    if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len);
-                out.println("      if (value == '+') {");
-                out.println("        if (check_only) {");
-                out.println("          TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));");
-                out.println("          hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));");
-                out.println("        }");
-                out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);");
-                out.println("      }");
-                out.println("      return true;");
-                out.println("    }");
-            }
-            for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
-                OptionDescriptor desc = e.getValue();
-                if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) {
-                    if (!printedCase) {
-                        printedCase = true;
-                        out.println("  case " + len + ":");
-                    }
-                    out.printf("    if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len);
-                    Class<?> declaringClass = desc.getDeclaringClass();
-                    if (isBoolean) {
-                        out.printf("      Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
-                                        toInternalName(getFieldType(desc)));
-                        out.println("      if (!check_only) {");
-                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, value, Handle(), 0L);");
-                        out.println("      }");
-                    } else if (desc.getType() == String.class) {
-                        out.println("      check_required_value(name, name_len, value, CHECK_(true));");
-                        out.printf("      Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
-                                        toInternalName(getFieldType(desc)));
-                        out.println("      if (!check_only) {");
-                        out.println("        Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));");
-                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);");
-                        out.println("      }");
-                    } else {
-                        char spec = getPrimitiveSpecChar(desc);
-                        out.println("      jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));");
-                        out.println("      if (!check_only) {");
-                        out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
-                                        toInternalName(getFieldType(desc)));
-                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);");
-                        out.println("      }");
-                    }
-                    out.println("      return true;");
-                    out.println("    }");
-                }
-            }
-        }
-        out.println("  }");
-    }
-
-    @SuppressWarnings("unchecked")
-    static SortedMap<String, OptionDescriptor> getOptions() throws Exception {
-        Field field = Class.forName("com.oracle.graal.hotspot.HotSpotOptionsLoader").getDeclaredField("options");
-        field.setAccessible(true);
-        SortedMap<String, OptionDescriptor> options = (SortedMap<String, OptionDescriptor>) field.get(null);
-
-        Set<Class<?>> checked = new HashSet<>();
-        for (final OptionDescriptor option : options.values()) {
-            Class<?> cls = option.getDeclaringClass();
-            OptionsVerifier.checkClass(cls, option, checked, graalJars);
-        }
-        return options;
-    }
-
-    private static Class<?> getFieldType(OptionDescriptor desc) throws Exception {
-        return desc.getDeclaringClass().getDeclaredField(desc.getFieldName()).getType();
-    }
-
-    private static String toInternalName(Class<?> c) {
-        return c.getName().replace('.', '/');
-    }
-
-    /**
-     * @see HotSpotOptions#setOption(String, OptionValue, char, String, long)
-     */
-    @SuppressWarnings("javadoc")
-    private static char getPrimitiveSpecChar(OptionDescriptor desc) {
-        if (desc.getType() == Integer.class) {
-            return 'i';
-        }
-        if (desc.getType() == Float.class) {
-            return 'f';
-        }
-        if (desc.getType() == Double.class) {
-            return 'd';
-        }
-        throw GraalInternalError.shouldNotReachHere("Unexpected primitive option type: " + desc.getType().getName());
-    }
-}
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java	Thu May 28 21:25:21 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +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 com.oracle.graal.hotspot.sourcegen;
-
-import static java.lang.String.*;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import jdk.internal.org.objectweb.asm.*;
-import jdk.internal.org.objectweb.asm.Type;
-
-import com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.GraalJars;
-import com.oracle.graal.options.*;
-
-/**
- * A {@link ClassVisitor} that verifies a class declaring one or more {@linkplain OptionValue
- * options} has a class initializer that only initializes the option(s). This sanity check mitigates
- * the possibility of an option value being used before the code that sets the value (e.g., from the
- * command line) has been executed.
- */
-final class OptionsVerifier extends ClassVisitor {
-
-    public static void checkClass(Class<?> cls, OptionDescriptor option, Set<Class<?>> checked, GraalJars graalJars) throws IOException {
-        if (!checked.contains(cls)) {
-            checked.add(cls);
-            Class<?> superclass = cls.getSuperclass();
-            if (superclass != null && !superclass.equals(Object.class)) {
-                checkClass(superclass, option, checked, graalJars);
-            }
-
-            String classFilePath = cls.getName().replace('.', '/') + ".class";
-            ClassReader cr = new ClassReader(Objects.requireNonNull(graalJars.getInputStream(classFilePath), "Could not find class file for " + cls.getName()));
-
-            ClassVisitor cv = new OptionsVerifier(cls, option);
-            cr.accept(cv, 0);
-        }
-    }
-
-    /**
-     * The option field context of the verification.
-     */
-    private final OptionDescriptor option;
-
-    /**
-     * The class in which {@link #option} is declared or a super-class of that class. This is the
-     * class whose {@code <clinit>} method is being verified.
-     */
-    private final Class<?> cls;
-
-    /**
-     * Source file context for error reporting.
-     */
-    String sourceFile = null;
-
-    /**
-     * Line number for error reporting.
-     */
-    int lineNo = -1;
-
-    final Class<?>[] boxingTypes = {Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class};
-
-    private static Class<?> resolve(String name) {
-        try {
-            return Class.forName(name.replace('/', '.'));
-        } catch (ClassNotFoundException e) {
-            throw new InternalError(e);
-        }
-    }
-
-    OptionsVerifier(Class<?> cls, OptionDescriptor desc) {
-        super(Opcodes.ASM5);
-        this.cls = cls;
-        this.option = desc;
-    }
-
-    @Override
-    public void visitSource(String source, String debug) {
-        this.sourceFile = source;
-    }
-
-    void verify(boolean condition, String message) {
-        if (!condition) {
-            error(message);
-        }
-    }
-
-    void error(String message) {
-        String errorMessage = format("%s:%d: Illegal code in %s.<clinit> which may be executed when %s.%s is initialized:%n%n    %s%n%n" + "The recommended solution is to move " + option.getName() +
-                        " into a separate class (e.g., %s.Options).%n", sourceFile, lineNo, cls.getSimpleName(), option.getDeclaringClass().getSimpleName(), option.getName(), message,
-                        option.getDeclaringClass().getSimpleName());
-        throw new InternalError(errorMessage);
-
-    }
-
-    @Override
-    public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) {
-        if (name.equals("<clinit>")) {
-            return new MethodVisitor(Opcodes.ASM5) {
-
-                @Override
-                public void visitLineNumber(int line, Label start) {
-                    lineNo = line;
-                }
-
-                @Override
-                public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) {
-                    if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) {
-                        verify(resolve(owner).equals(option.getDeclaringClass()), format("store to field %s.%s", resolve(owner).getSimpleName(), fieldName));
-                        verify(opcode != Opcodes.PUTFIELD, format("store to non-static field %s.%s", resolve(owner).getSimpleName(), fieldName));
-                    }
-                }
-
-                private Executable resolveMethod(String owner, String methodName, String methodDesc) {
-                    Class<?> declaringClass = resolve(owner);
-                    if (methodName.equals("<init>")) {
-                        for (Constructor<?> c : declaringClass.getDeclaredConstructors()) {
-                            if (methodDesc.equals(Type.getConstructorDescriptor(c))) {
-                                return c;
-                            }
-                        }
-                    } else {
-                        Type[] argumentTypes = Type.getArgumentTypes(methodDesc);
-                        for (Method m : declaringClass.getDeclaredMethods()) {
-                            if (m.getName().equals(methodName)) {
-                                if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) {
-                                    if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) {
-                                        return m;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    throw new NoSuchMethodError(declaringClass + "." + methodName + methodDesc);
-                }
-
-                /**
-                 * Checks whether a given method is allowed to be called.
-                 */
-                private boolean checkInvokeTarget(Executable method) {
-                    Class<?> holder = method.getDeclaringClass();
-                    if (method instanceof Constructor) {
-                        if (OptionValue.class.isAssignableFrom(holder)) {
-                            return true;
-                        }
-                    } else if (Arrays.asList(boxingTypes).contains(holder)) {
-                        return method.getName().equals("valueOf");
-                    } else if (method.getDeclaringClass().equals(Class.class)) {
-                        return method.getName().equals("desiredAssertionStatus");
-                    }
-                    return false;
-                }
-
-                @Override
-                public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) {
-                    Executable callee = resolveMethod(owner, methodName, methodDesc);
-                    verify(checkInvokeTarget(callee), "invocation of " + callee);
-                }
-            };
-        } else {
-            return null;
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu May 28 21:26:54 2015 +0200
@@ -40,6 +40,7 @@
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -377,4 +378,10 @@
             return overlap;
         }
     }
+
+    @Override
+    public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) {
+        RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
+        return new RegisterAllocationConfig(registerConfigNonNull);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu May 28 21:26:54 2015 +0200
@@ -29,7 +29,6 @@
 import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.debug.Debug.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.hotspot.InitTimer.*;
 import static com.oracle.graal.hotspot.meta.HotSpotSuitesProvider.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
 
@@ -61,15 +60,6 @@
 //JaCoCo Exclude
 
 public class CompilationTask {
-
-    static {
-        try (InitTimer t = timer("initialize CompilationTask")) {
-            // Must be first to ensure any options accessed by the rest of the class
-            // initializer are initialized from the command line.
-            HotSpotOptions.initialize();
-        }
-    }
-
     private static final DebugMetric BAILOUTS = Debug.metric("Bailouts");
 
     private final HotSpotBackend backend;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Thu May 28 21:26:54 2015 +0200
@@ -40,7 +40,6 @@
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess;
-import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -120,14 +119,12 @@
          *
          * @param options a space separated set of option value settings with each option setting in
          *            a format compatible with
-         *            {@link HotSpotOptions#parseOption(String, OptionConsumer)}. Ignored if null.
+         *            {@link OptionUtils#parseOption(String, OptionConsumer)}. Ignored if null.
          */
         public Config(String options) {
             if (options != null) {
                 for (String option : options.split("\\s+")) {
-                    if (!HotSpotOptions.parseOption(option, this)) {
-                        throw new GraalInternalError("Invalid option specified: %s", option);
-                    }
+                    OptionUtils.parseOption(option, this);
                 }
             }
         }
@@ -213,7 +210,7 @@
      */
     public void compile() throws Throwable {
         // By default only report statistics for the CTW threads themselves
-        if (GraalDebugConfig.DebugValueThreadFilter.hasInitialValue()) {
+        if (GraalDebugConfig.DebugValueThreadFilter.hasDefaultValue()) {
             GraalDebugConfig.DebugValueThreadFilter.setValue("^CompileTheWorld");
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java	Thu May 28 21:26:54 2015 +0200
@@ -36,6 +36,8 @@
 import com.oracle.graal.api.code.CompilationResult.JumpTable;
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.code.CompilationResult.Site;
+import com.oracle.graal.api.meta.Assumptions.Assumption;
+import com.oracle.graal.api.meta.*;
 
 /**
  * A {@link CompilationResult} with additional HotSpot-specific information required for installing
@@ -43,16 +45,28 @@
  */
 public abstract class HotSpotCompiledCode {
 
-    public final CompilationResult comp;
-
     public final Site[] sites;
     public final ExceptionHandler[] exceptionHandlers;
     public final Comment[] comments;
+    public final Assumption[] assumptions;
+
+    public final byte[] targetCode;
+    public final int targetCodeSize;
 
     public final byte[] dataSection;
     public final int dataSectionAlignment;
     public final DataPatch[] dataSectionPatches;
 
+    public final int totalFrameSize;
+    public final int customStackAreaOffset;
+
+    /**
+     * The list of the methods whose bytecodes were used as input to the compilation. If
+     * {@code null}, then the compilation did not record method dependencies. Otherwise, the first
+     * element of this array is the root method of the compilation.
+     */
+    public final ResolvedJavaMethod[] methods;
+
     public static class Comment {
 
         public final String text;
@@ -65,7 +79,6 @@
     }
 
     public HotSpotCompiledCode(CompilationResult compResult) {
-        this.comp = compResult;
         sites = getSortedSites(compResult);
         if (compResult.getExceptionHandlers().isEmpty()) {
             exceptionHandlers = null;
@@ -90,8 +103,12 @@
                 comments[i] = new Comment(annotation.position, text);
             }
         }
+        assumptions = compResult.getAssumptions();
         assert validateFrames();
 
+        targetCode = compResult.getTargetCode();
+        targetCodeSize = compResult.getTargetCodeSize();
+
         DataSection data = compResult.getDataSection();
         data.finalizeLayout();
         dataSection = new byte[data.getSectionSize()];
@@ -102,6 +119,11 @@
 
         dataSectionAlignment = data.getSectionAlignment();
         dataSectionPatches = patchBuilder.build().toArray(len -> new DataPatch[len]);
+
+        totalFrameSize = compResult.getTotalFrameSize();
+        customStackAreaOffset = compResult.getCustomStackAreaOffset();
+
+        methods = compResult.getMethods();
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Thu May 28 21:26:54 2015 +0200
@@ -53,7 +53,7 @@
 
         // Stubs cannot be recompiled so they cannot be compiled with
         // assumptions and there is no point in recording evol_method dependencies
-        assert compResult.getAssumptions().isEmpty() : "stubs should not use assumptions: " + this;
+        assert compResult.getAssumptions() == null : "stubs should not use assumptions: " + this;
         assert compResult.getMethods() == null : "stubs should not record evol_method dependencies: " + this;
 
         for (DataPatch data : compResult.getDataPatches()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu May 28 21:26:54 2015 +0200
@@ -65,10 +65,6 @@
     private static final HotSpotGraalRuntime instance;
 
     static {
-        try (InitTimer t = timer("initialize HotSpotOptions")) {
-            HotSpotOptions.initialize();
-        }
-
         try (InitTimer t = timer("HotSpotGraalRuntime.<init>")) {
             instance = new HotSpotGraalRuntime();
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Thu May 28 21:26:54 2015 +0200
@@ -23,13 +23,11 @@
 package com.oracle.graal.hotspot;
 
 import static com.oracle.graal.compiler.GraalDebugConfig.*;
-import static com.oracle.graal.hotspot.HotSpotOptionsLoader.*;
-import static java.lang.Double.*;
+import static com.oracle.graal.options.OptionsLoader.*;
 
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.options.*;
-import com.oracle.graal.options.OptionUtils.OptionConsumer;
 
 //JaCoCo Exclude
 
@@ -41,14 +39,7 @@
 
     private static final String GRAAL_OPTION_PREFIX = "-G:";
 
-    /**
-     * Parses the Graal specific options specified to HotSpot (e.g., on the command line).
-     */
-    private static native void parseVMOptions();
-
     static {
-        parseVMOptions();
-
         assert !Debug.Initialization.isDebugInitialized() : "The class " + Debug.class.getName() + " must not be initialized before the Graal runtime has been initialized. " +
                         "This can be fixed by placing a call to " + Graal.class.getName() + ".runtime() on the path that triggers initialization of " + Debug.class.getName();
         if (areDebugScopePatternsEnabled()) {
@@ -65,57 +56,9 @@
         }
     }
 
-    /**
-     * Ensures {@link HotSpotOptions} is initialized.
-     */
-    public static void initialize() {
+    static void printFlags() {
+        OptionUtils.printFlags(options, GRAAL_OPTION_PREFIX);
     }
 
-    /**
-     * Helper for the VM code called by {@link #parseVMOptions()}.
-     *
-     * @param name the name of a parsed option
-     * @param option the object encapsulating the option
-     * @param spec specification of boolean option value, type of option value or action to take
-     */
-    static void setOption(String name, OptionValue<?> option, char spec, String stringValue, long primitiveValue) {
-        switch (spec) {
-            case '+':
-                option.setValue(Boolean.TRUE);
-                break;
-            case '-':
-                option.setValue(Boolean.FALSE);
-                break;
-            case '?':
-                OptionUtils.printFlags(options, GRAAL_OPTION_PREFIX);
-                break;
-            case ' ':
-                OptionUtils.printNoMatchMessage(options, name, GRAAL_OPTION_PREFIX);
-                break;
-            case 'i':
-                option.setValue((int) primitiveValue);
-                break;
-            case 'f':
-                option.setValue((float) longBitsToDouble(primitiveValue));
-                break;
-            case 'd':
-                option.setValue(longBitsToDouble(primitiveValue));
-                break;
-            case 's':
-                option.setValue(stringValue);
-                break;
-        }
-    }
-
-    /**
-     * 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. If null, the
-     *            {@link OptionValue#setValue(Object)} method of the specified option is called
-     *            instead.
-     */
-    public static boolean parseOption(String option, OptionConsumer setter) {
-        return OptionUtils.parseOption(options, option, GRAAL_OPTION_PREFIX, setter);
-    }
+    public native Object getOptionValue(String optionName);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java	Thu May 28 21:25:21 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +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 com.oracle.graal.hotspot;
-
-import java.util.*;
-
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.options.*;
-
-/**
- * Helper class for separating loading of options from option initialization at runtime.
- */
-class HotSpotOptionsLoader {
-    static final SortedMap<String, OptionDescriptor> options = new TreeMap<>();
-
-    /**
-     * Initializes {@link #options} from {@link Options} services.
-     */
-    static {
-        for (Options opts : Services.load(Options.class)) {
-            for (OptionDescriptor desc : opts) {
-                if (isHotSpotOption(desc)) {
-                    String name = desc.getName();
-                    OptionDescriptor existing = options.put(name, desc);
-                    assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
-                }
-            }
-        }
-    }
-
-    /**
-     * Determines if a given option is a HotSpot command line option.
-     */
-    private static boolean isHotSpotOption(OptionDescriptor desc) {
-        return desc.getClass().getName().startsWith("com.oracle.graal");
-    }
-}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java	Thu May 28 21:26:54 2015 +0200
@@ -621,13 +621,14 @@
         return attributes(asRegister(operand)).isCallerSave();
     }
 
-    <B extends AbstractBlockBase<B>> void allocate(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    <B extends AbstractBlockBase<B>> void allocate(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
 
         /*
          * This is the point to enable debug logging for the whole register allocation.
          */
         try (Indent indent = Debug.logAndIndent("LinearScan allocate")) {
-            AllocationContext context = new AllocationContext(spillMoveFactory);
+            AllocationContext context = new AllocationContext(spillMoveFactory, registerAllocationConfig);
 
             createLifetimeAnalysisPhase().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false);
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanAssignLocationsPhase.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanAssignLocationsPhase.java	Thu May 28 21:26:54 2015 +0200
@@ -30,6 +30,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
@@ -51,7 +52,8 @@
     }
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         assignLocations();
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java	Thu May 28 21:26:54 2015 +0200
@@ -30,6 +30,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
@@ -57,7 +58,8 @@
     }
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         eliminateSpillMoves();
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java	Thu May 28 21:26:54 2015 +0200
@@ -61,7 +61,8 @@
     }
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         numberInstructions();
         allocator.printLir("Before register allocation", true);
         computeLocalLiveSets();
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java	Thu May 28 21:26:54 2015 +0200
@@ -29,6 +29,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
@@ -50,7 +51,8 @@
     }
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         optimizeSpillPosition();
         allocator.printIntervals("After optimize spill position");
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java	Thu May 28 21:26:54 2015 +0200
@@ -48,14 +48,15 @@
     });
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         final LinearScan allocator;
         if (LinearScanPhase.SSA_LSRA.getValue()) {
-            allocator = new SSALinearScan(target, lirGenRes, spillMoveFactory, new RegisterAllocationConfig(lirGenRes.getFrameMapBuilder().getRegisterConfig()));
+            allocator = new SSALinearScan(target, lirGenRes, spillMoveFactory, registerAllocationConfig);
         } else {
-            allocator = new LinearScan(target, lirGenRes, spillMoveFactory, new RegisterAllocationConfig(lirGenRes.getFrameMapBuilder().getRegisterConfig()));
+            allocator = new LinearScan(target, lirGenRes, spillMoveFactory, registerAllocationConfig);
         }
-        allocator.allocate(target, lirGenRes, codeEmittingOrder, linearScanOrder, spillMoveFactory);
+        allocator.allocate(target, lirGenRes, codeEmittingOrder, linearScanOrder, spillMoveFactory, registerAllocationConfig);
     }
 
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java	Thu May 28 21:26:54 2015 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.gen.*;
@@ -40,7 +41,8 @@
     }
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         allocator.printIntervals("Before register allocation");
         allocateRegisters();
         allocator.printIntervals("After register allocation");
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java	Thu May 28 21:26:54 2015 +0200
@@ -27,6 +27,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
@@ -48,7 +49,8 @@
     }
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         resolveDataFlow();
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java	Thu May 28 21:26:54 2015 +0200
@@ -30,6 +30,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.common.util.*;
 import com.oracle.graal.debug.*;
@@ -50,6 +51,10 @@
 
     private MoveResolver moveResolver; // for ordering spill moves
 
+    private int minReg;
+
+    private int maxReg;
+
     /**
      * Only 10% of the lists in {@link #spillIntervals} are actually used. But when they are used,
      * they can grow quite long. The maximum length observed was 45 (all numbers taken from a
@@ -95,10 +100,22 @@
         }
     }
 
+    int maxRegisterNumber() {
+        return maxReg;
+    }
+
+    int minRegisterNumber() {
+        return minReg;
+    }
+
+    boolean isRegisterInRange(int reg) {
+        return reg >= minRegisterNumber() && reg <= maxRegisterNumber();
+    }
+
     void excludeFromUse(Interval i) {
         Value location = i.location();
         int i1 = asRegister(location).number;
-        if (i1 >= availableRegs[0].number && i1 <= availableRegs[availableRegs.length - 1].number) {
+        if (isRegisterInRange(i1)) {
             usePos[i1] = 0;
         }
     }
@@ -107,7 +124,7 @@
         if (usePos != -1) {
             assert usePos != 0 : "must use excludeFromUse to set usePos to 0";
             int i = asRegister(interval.location()).number;
-            if (i >= availableRegs[0].number && i <= availableRegs[availableRegs.length - 1].number) {
+            if (isRegisterInRange(i)) {
                 if (this.usePos[i] > usePos) {
                     this.usePos[i] = usePos;
                 }
@@ -126,7 +143,7 @@
     void setBlockPos(Interval i, int blockPos) {
         if (blockPos != -1) {
             int reg = asRegister(i.location()).number;
-            if (reg >= availableRegs[0].number && reg <= availableRegs[availableRegs.length - 1].number) {
+            if (isRegisterInRange(reg)) {
                 if (this.blockPos[reg] > blockPos) {
                     this.blockPos[reg] = blockPos;
                 }
@@ -696,8 +713,7 @@
             Register minFullReg = null;
             Register maxPartialReg = null;
 
-            for (int i = 0; i < availableRegs.length; ++i) {
-                Register availableReg = availableRegs[i];
+            for (Register availableReg : availableRegs) {
                 int number = availableReg.number;
                 if (usePos[number] >= intervalTo) {
                     // this register is free for the full interval
@@ -858,7 +874,10 @@
     }
 
     void initVarsForAlloc(Interval interval) {
-        availableRegs = allocator.regAllocConfig.getAllocatableRegisters(interval.kind().getPlatformKind());
+        AllocatableRegisters allocatableRegisters = allocator.regAllocConfig.getAllocatableRegisters(interval.kind().getPlatformKind());
+        availableRegs = allocatableRegisters.allocatableRegisters;
+        minReg = allocatableRegisters.minRegisterNumber;
+        maxReg = allocatableRegisters.maxRegisterNumber;
     }
 
     static boolean isMove(LIRInstruction op, Interval from, Interval to) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java	Thu May 28 21:26:54 2015 +0200
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
@@ -53,7 +54,8 @@
     }
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         new Marker<B>(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build();
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationPhase.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationPhase.java	Thu May 28 21:26:54 2015 +0200
@@ -25,26 +25,29 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.gen.*;
-import com.oracle.graal.lir.gen.LIRGeneratorTool.*;
+import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory;
 
 public abstract class AllocationPhase extends LIRPhase<AllocationPhase.AllocationContext> {
 
     public static final class AllocationContext {
         private final SpillMoveFactory spillMoveFactory;
+        private final RegisterAllocationConfig registerAllocationConfig;
 
-        public AllocationContext(SpillMoveFactory spillMoveFactory) {
+        public AllocationContext(SpillMoveFactory spillMoveFactory, RegisterAllocationConfig registerAllocationConfig) {
             this.spillMoveFactory = spillMoveFactory;
+            this.registerAllocationConfig = registerAllocationConfig;
         }
     }
 
     @Override
     protected final <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, AllocationContext context) {
-        run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.spillMoveFactory);
+        run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.spillMoveFactory, context.registerAllocationConfig);
     }
 
     protected abstract <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder,
-                    SpillMoveFactory spillMoveFactory);
+                    SpillMoveFactory spillMoveFactory, RegisterAllocationConfig registerAllocationConfig);
 
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java	Thu May 28 21:26:54 2015 +0200
@@ -30,6 +30,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -69,7 +70,8 @@
     private static final DebugTimer AssignSlotsTimer = Debug.timer("LSStackSlotAllocator[AssignSlots]");
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         lirGenRes.buildFrameMap(this);
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java	Thu May 28 21:26:54 2015 +0200
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -40,7 +41,8 @@
 public class SimpleStackSlotAllocator extends AllocationPhase implements StackSlotAllocator {
 
     @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory,
+                    RegisterAllocationConfig registerAllocationConfig) {
         lirGenRes.buildFrameMap(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java	Thu May 28 21:26:54 2015 +0200
@@ -962,7 +962,7 @@
             return true;
 
         } else if (node instanceof Invoke) {
-            assert node instanceof InvokeNode || node instanceof InvokeWithExceptionNode : "The only two Invoke node classes";
+            assert node instanceof InvokeNode || node instanceof InvokeWithExceptionNode : "The only two Invoke node classes. Got " + node.getClass();
             assert direct : "Invoke and InvokeWithException only have direct successor and input edges";
             if (edges.type() == Edges.Type.Successors) {
                 assert edges.getCount() == (node instanceof InvokeWithExceptionNode ? 2 : 1) : "InvokeNode has one successor (next); InvokeWithExceptionNode has two successors (next, exceptionEdge)";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/GraalJars.java	Thu May 28 21:26:54 2015 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package com.oracle.graal.options.processor;
+
+import java.io.*;
+import java.util.*;
+import java.util.stream.*;
+import java.util.zip.*;
+
+public class GraalJars implements Iterable<ZipEntry> {
+    private final List<ZipFile> jars = new ArrayList<>(2);
+
+    public GraalJars() {
+        String classPath = System.getProperty("java.class.path");
+        for (String e : classPath.split(File.pathSeparator)) {
+            if (e.endsWith(File.separatorChar + "graal.jar") || e.endsWith(File.separatorChar + "graal-truffle.jar")) {
+                try {
+                    jars.add(new ZipFile(e));
+                } catch (IOException ioe) {
+                    throw new InternalError(ioe);
+                }
+            }
+        }
+        if (jars.size() != 2) {
+            throw new InternalError("Could not find graal.jar or graal-truffle.jar on class path: " + classPath);
+        }
+    }
+
+    public Iterator<ZipEntry> iterator() {
+        Stream<ZipEntry> entries = jars.stream().flatMap(ZipFile::stream);
+        return entries.iterator();
+    }
+
+    public InputStream getInputStream(String classFilePath) throws IOException {
+        for (ZipFile jar : jars) {
+            ZipEntry entry = jar.getEntry(classFilePath);
+            if (entry != null) {
+                return jar.getInputStream(entry);
+            }
+        }
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java	Thu May 28 21:26:54 2015 +0200
@@ -211,6 +211,7 @@
 
         try {
             createProviderFile(pkg, optionsClassName, originatingElements);
+            createOptionsFile(info, pkg, topDeclaringClass.toString(), originatingElements);
         } catch (IOException e) {
             processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType);
         }
@@ -224,6 +225,53 @@
         writer.close();
     }
 
+    private void createOptionsFile(OptionsInfo info, String pkg, String relativeName, Element... originatingElements) throws IOException {
+        String filename = "META-INF/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, "Unsoported 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 Graal code style guide checked by Checkstyle
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionsVerifier.java	Thu May 28 21:26:54 2015 +0200
@@ -0,0 +1,184 @@
+/*
+ * 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 com.oracle.graal.options.processor;
+
+import static java.lang.String.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import jdk.internal.org.objectweb.asm.*;
+import jdk.internal.org.objectweb.asm.Type;
+
+import com.oracle.graal.options.*;
+
+/**
+ * A {@link ClassVisitor} that verifies a class declaring one or more {@linkplain OptionValue
+ * options} has a class initializer that only initializes the option(s). This sanity check mitigates
+ * the possibility of an option value being used before the code that sets the value (e.g., from the
+ * command line) has been executed.
+ */
+final class OptionsVerifier extends ClassVisitor {
+
+    public static void checkClass(Class<?> cls, OptionDescriptor option, Set<Class<?>> checked, GraalJars graalJars) throws IOException {
+        if (!checked.contains(cls)) {
+            checked.add(cls);
+            Class<?> superclass = cls.getSuperclass();
+            if (superclass != null && !superclass.equals(Object.class)) {
+                checkClass(superclass, option, checked, graalJars);
+            }
+
+            String classFilePath = cls.getName().replace('.', '/') + ".class";
+            ClassReader cr = new ClassReader(Objects.requireNonNull(graalJars.getInputStream(classFilePath), "Could not find class file for " + cls.getName()));
+
+            ClassVisitor cv = new OptionsVerifier(cls, option);
+            cr.accept(cv, 0);
+        }
+    }
+
+    /**
+     * The option field context of the verification.
+     */
+    private final OptionDescriptor option;
+
+    /**
+     * The class in which {@link #option} is declared or a super-class of that class. This is the
+     * class whose {@code <clinit>} method is being verified.
+     */
+    private final Class<?> cls;
+
+    /**
+     * Source file context for error reporting.
+     */
+    String sourceFile = null;
+
+    /**
+     * Line number for error reporting.
+     */
+    int lineNo = -1;
+
+    final Class<?>[] boxingTypes = {Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class};
+
+    private static Class<?> resolve(String name) {
+        try {
+            return Class.forName(name.replace('/', '.'));
+        } catch (ClassNotFoundException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    OptionsVerifier(Class<?> cls, OptionDescriptor desc) {
+        super(Opcodes.ASM5);
+        this.cls = cls;
+        this.option = desc;
+    }
+
+    @Override
+    public void visitSource(String source, String debug) {
+        this.sourceFile = source;
+    }
+
+    void verify(boolean condition, String message) {
+        if (!condition) {
+            error(message);
+        }
+    }
+
+    void error(String message) {
+        String errorMessage = format("%s:%d: Illegal code in %s.<clinit> which may be executed when %s.%s is initialized:%n%n    %s%n%n" + "The recommended solution is to move " + option.getName() +
+                        " into a separate class (e.g., %s.Options).%n", sourceFile, lineNo, cls.getSimpleName(), option.getDeclaringClass().getSimpleName(), option.getName(), message,
+                        option.getDeclaringClass().getSimpleName());
+        throw new InternalError(errorMessage);
+
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) {
+        if (name.equals("<clinit>")) {
+            return new MethodVisitor(Opcodes.ASM5) {
+
+                @Override
+                public void visitLineNumber(int line, Label start) {
+                    lineNo = line;
+                }
+
+                @Override
+                public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) {
+                    if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) {
+                        verify(resolve(owner).equals(option.getDeclaringClass()), format("store to field %s.%s", resolve(owner).getSimpleName(), fieldName));
+                        verify(opcode != Opcodes.PUTFIELD, format("store to non-static field %s.%s", resolve(owner).getSimpleName(), fieldName));
+                    }
+                }
+
+                private Executable resolveMethod(String owner, String methodName, String methodDesc) {
+                    Class<?> declaringClass = resolve(owner);
+                    if (methodName.equals("<init>")) {
+                        for (Constructor<?> c : declaringClass.getDeclaredConstructors()) {
+                            if (methodDesc.equals(Type.getConstructorDescriptor(c))) {
+                                return c;
+                            }
+                        }
+                    } else {
+                        Type[] argumentTypes = Type.getArgumentTypes(methodDesc);
+                        for (Method m : declaringClass.getDeclaredMethods()) {
+                            if (m.getName().equals(methodName)) {
+                                if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) {
+                                    if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) {
+                                        return m;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    throw new NoSuchMethodError(declaringClass + "." + methodName + methodDesc);
+                }
+
+                /**
+                 * Checks whether a given method is allowed to be called.
+                 */
+                private boolean checkInvokeTarget(Executable method) {
+                    Class<?> holder = method.getDeclaringClass();
+                    if (method instanceof Constructor) {
+                        if (OptionValue.class.isAssignableFrom(holder)) {
+                            return true;
+                        }
+                    } else if (Arrays.asList(boxingTypes).contains(holder)) {
+                        return method.getName().equals("valueOf");
+                    } else if (method.getDeclaringClass().equals(Class.class)) {
+                        return method.getName().equals("desiredAssertionStatus");
+                    }
+                    return false;
+                }
+
+                @Override
+                public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) {
+                    Executable callee = resolveMethod(owner, methodName, methodDesc);
+                    verify(checkInvokeTarget(callee), "invocation of " + callee);
+                }
+            };
+        } else {
+            return null;
+        }
+    }
+}
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionUtils.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionUtils.java	Thu May 28 21:26:54 2015 +0200
@@ -34,24 +34,19 @@
      * 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. If null, the
-     *            {@link OptionValue#setValue(Object)} method of the specified option is called
-     *            instead.
+     * @param setter the object to notify of the parsed option and value.
      */
-    public static boolean parseOption(SortedMap<String, OptionDescriptor> options, String option, String prefix, OptionConsumer setter) {
+    public static void parseOption(String option, OptionConsumer setter) {
+        SortedMap<String, OptionDescriptor> options = OptionsLoader.options;
+        Objects.requireNonNull(setter);
         if (option.length() == 0) {
-            return false;
+            return;
         }
 
         Object value = null;
         String optionName = null;
         String valueString = null;
 
-        if (option.equals("+PrintFlags")) {
-            printFlags(options, prefix);
-            return true;
-        }
-
         char first = option.charAt(0);
         if (first == '+' || first == '-') {
             optionName = option.substring(1);
@@ -69,21 +64,18 @@
 
         OptionDescriptor desc = options.get(optionName);
         if (desc == null) {
-            printNoMatchMessage(options, optionName, prefix);
-            return false;
+            throw new IllegalArgumentException("Option '" + optionName + "' not found");
         }
 
         Class<?> optionType = desc.getType();
 
         if (value == null) {
             if (optionType == Boolean.TYPE || optionType == Boolean.class) {
-                System.err.println("Value for boolean option '" + optionName + "' must use '" + prefix + "+" + optionName + "' or '" + prefix + "-" + optionName + "' format");
-                return false;
+                throw new IllegalArgumentException("Boolean option '" + optionName + "' must use +/- prefix");
             }
 
             if (valueString == null) {
-                System.err.println("Value for option '" + optionName + "' must use '" + prefix + optionName + "=<value>' format");
-                return false;
+                throw new IllegalArgumentException("Missing value for non-boolean option '" + optionName + "' must use " + optionName + "=<value> format");
             }
 
             if (optionType == Float.class) {
@@ -96,28 +88,16 @@
                 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) {
-                System.err.println("Value for option '" + optionName + "' must use '" + prefix + optionName + "=<value>' format");
-                return false;
+                throw new IllegalArgumentException("Non-boolean option '" + optionName + "' can not use +/- prefix. Use " + optionName + "=<value> format");
             }
         }
 
-        if (value != null) {
-            if (setter != null) {
-                setter.set(desc, value);
-            } else {
-                OptionValue<?> optionValue = desc.getOptionValue();
-                optionValue.setValue(value);
-                // System.err.println("Set option " + desc.getName() + " to " + value);
-            }
-        } else {
-            System.err.println("Wrong value \"" + valueString + "\" for option " + optionName);
-            return false;
-        }
-
-        return true;
+        setter.set(desc, value);
     }
 
     private static long parseLong(String v) {
@@ -141,27 +121,6 @@
         return Long.parseLong(valueString) * scale;
     }
 
-    public static void printNoMatchMessage(SortedMap<String, OptionDescriptor> options, String optionName, String prefix) {
-        OptionDescriptor desc = options.get(optionName);
-        if (desc != null) {
-            if (desc.getType() == Boolean.class) {
-                System.err.println("Boolean option " + optionName + " must be prefixed with '+' or '-'");
-            } else {
-                System.err.println(desc.getType().getSimpleName() + " option " + optionName + " must not be prefixed with '+' or '-'");
-            }
-        } else {
-            System.err.println("Could not find option " + optionName + " (use " + prefix + "+PrintFlags to see options)");
-            List<OptionDescriptor> matches = fuzzyMatch(options, optionName);
-            if (!matches.isEmpty()) {
-                System.err.println("Did you mean one of the following?");
-                for (OptionDescriptor match : matches) {
-                    boolean isBoolean = match.getType() == Boolean.class;
-                    System.err.println(String.format("    %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=<value>"));
-                }
-            }
-        }
-    }
-
     /**
      * Wraps some given text to one or more lines of a given maximum width.
      *
@@ -220,38 +179,4 @@
 
         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(SortedMap<String, OptionDescriptor> options, String optionName) {
-        List<OptionDescriptor> matches = new ArrayList<>();
-        for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
-            float score = stringSimiliarity(e.getKey(), optionName);
-            if (score >= FUZZY_MATCH_THRESHOLD) {
-                matches.add(e.getValue());
-            }
-        }
-        return matches;
-    }
 }
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Thu May 28 21:26:54 2015 +0200
@@ -30,7 +30,6 @@
  * An option value.
  */
 public class OptionValue<T> {
-
     /**
      * Temporarily changes the value for an option. The {@linkplain OptionValue#getValue() value} of
      * {@code option} is set to {@code value} until {@link OverrideScope#close()} is called on the
@@ -138,7 +137,7 @@
         overrideScopeTL.set(overrideScope);
     }
 
-    private T initialValue;
+    private T defaultValue;
 
     /**
      * The raw option value.
@@ -164,29 +163,30 @@
 
     @SuppressWarnings("unchecked")
     public OptionValue(T value) {
-        this.initialValue = value;
-        this.value = (T) UNINITIALIZED;
+        this.defaultValue = value;
+        this.value = (T) DEFAULT;
         addToHistogram(this);
     }
 
+    private static final Object DEFAULT = "DEFAULT";
     private static final Object UNINITIALIZED = "UNINITIALIZED";
 
     /**
      * Creates an uninitialized option value for a subclass that initializes itself
-     * {@link #initialValue() lazily}.
+     * {@link #defaultValue() lazily}.
      */
     @SuppressWarnings("unchecked")
     protected OptionValue() {
-        this.initialValue = (T) UNINITIALIZED;
-        this.value = (T) UNINITIALIZED;
+        this.defaultValue = (T) UNINITIALIZED;
+        this.value = (T) DEFAULT;
         addToHistogram(this);
     }
 
     /**
-     * Lazy initialization of value.
+     * Lazy initialization of default value.
      */
-    protected T initialValue() {
-        throw new InternalError("Uninitialized option value must override initialValue()");
+    protected T defaultValue() {
+        throw new InternalError("Option without a default value value must override defaultValue()");
     }
 
     /**
@@ -223,27 +223,19 @@
      * {@link #setValue(Object)} or registering {@link OverrideScope}s. Therefore, it is also not
      * affected by options set on the command line.
      */
-    public T getInitialValue() {
-        if (initialValue == UNINITIALIZED) {
-            initialValue = initialValue();
+    public T getDefaultValue() {
+        if (defaultValue == UNINITIALIZED) {
+            defaultValue = defaultValue();
         }
-        return initialValue;
+        return defaultValue;
     }
 
     /**
      * Returns true if the option has the same value that was set in the source code.
      */
-    public boolean hasInitialValue() {
-        if (!(this instanceof StableOptionValue)) {
-            OverrideScope overrideScope = getOverrideScope();
-            if (overrideScope != null) {
-                T override = overrideScope.getOverride(this);
-                if (override != null) {
-                    return false;
-                }
-            }
-        }
-        return value == UNINITIALIZED || Objects.equals(value, getInitialValue());
+    public boolean hasDefaultValue() {
+        getValue(); // ensure initialized
+        return value == DEFAULT || Objects.equals(value, getDefaultValue());
     }
 
     /**
@@ -262,10 +254,10 @@
                 }
             }
         }
-        if (value != UNINITIALIZED) {
+        if (value != DEFAULT) {
             return value;
         } else {
-            return getInitialValue();
+            return getDefaultValue();
         }
     }
 
@@ -285,10 +277,10 @@
                 overrideScope.getOverrides(this, (Collection<Object>) values);
             }
         }
-        if (value != UNINITIALIZED) {
+        if (value != DEFAULT) {
             values.add(value);
         } else {
-            values.add(getInitialValue());
+            values.add(getDefaultValue());
         }
         return values;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsLoader.java	Thu May 28 21:26:54 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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 com.oracle.graal.options;
+
+import java.util.*;
+
+import com.oracle.graal.api.runtime.*;
+
+/**
+ * Helper class used to load option descriptors. Only to be used in the slow-path.
+ */
+public class OptionsLoader {
+    public static final SortedMap<String, OptionDescriptor> options = new TreeMap<>();
+
+    /**
+     * Initializes {@link #options} from {@link Options} services.
+     */
+    static {
+        for (Options opts : Services.load(Options.class)) {
+            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();
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java	Thu May 28 21:25:21 2015 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java	Thu May 28 21:26:54 2015 +0200
@@ -42,7 +42,7 @@
 
     /**
      * Creates an uninitialized stable option value for a subclass that initializes itself
-     * {@link #initialValue() lazily}.
+     * {@link #defaultValue() lazily}.
      */
     public StableOptionValue() {
     }
--- a/make/Makefile	Thu May 28 21:25:21 2015 +0200
+++ b/make/Makefile	Thu May 28 21:26:54 2015 +0200
@@ -638,6 +638,9 @@
 $(EXPORT_JRE_LIB_GRAAL_SERVICES_DIR)/%: $(SHARED_DIR)/services/%
 	$(install-file)
 
+$(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/%: $(SHARED_DIR)/options/%
+	$(install-file)
+
 $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/code/%
 	$(install-file)
 
--- a/make/defs.make	Thu May 28 21:25:21 2015 +0200
+++ b/make/defs.make	Thu May 28 21:26:54 2015 +0200
@@ -370,5 +370,41 @@
 EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_SERVICES_DIR)/com.oracle.graal.truffle.hotspot.nfi.RawNativeCallNodeFactory
 EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_SERVICES_DIR)/com.oracle.graal.truffle.OptimizedCallTargetInstrumentationFactory
 
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.common.GraalOptions
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.GraalCompiler
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.GraalDebugConfig
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.phases.HighTier
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.phases.LowTier
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.graph.Graph
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.CompileTheWorld
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.debug.BenchmarkCounters
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.HotSpotBackend
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.HotSpotGraalRuntime
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.replacements.InstanceOfSnippets
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.replacements.MonitorSnippets
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.replacements.NewObjectSnippets
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.java.AbstractBytecodeParser
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.alloc.lsra.LinearScan
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.alloc.lsra.LocationMarker
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.alloc.lsra.OptimizingLinearScanWalker
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.constopt.ConstantLoadOptimization
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.gen.LIRGenerator
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.phases.LIRPhase
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.phases.PostAllocationOptimizationStage
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.ssa.SSADestructionPhase
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.stackslotalloc.LSStackSlotAllocator
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.loop.LoopPolicies
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.phases.common.DeadCodeEliminationPhase
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.phases.common.inlining.InliningPhase
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.phases.tiers.Suites
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.printer.NoDeadCodeVerifyHandler
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.replacements.StandardGraphBuilderPlugins
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.truffle.PartialEvaluator
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.truffle.TruffleCompilerOptions
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.virtual.phases.ea.PartialEscapePhase
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.asm.CompilationResultBuilder
+EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.java.GraphBuilderPhase
+
+
 .PHONY: $(HS_ALT_MAKE)/defs.make
 
--- a/mx/mx_graal.py	Thu May 28 21:25:21 2015 +0200
+++ b/mx/mx_graal.py	Thu May 28 21:26:54 2015 +0200
@@ -30,7 +30,6 @@
 from os.path import join, exists, dirname, basename
 from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER
 from outputparser import OutputParser, ValuesMatcher
-import hashlib
 import mx
 import xml.dom.minidom
 import sanitycheck
@@ -520,62 +519,6 @@
         os.makedirs(hsSrcGenDir)
     return hsSrcGenDir
 
-def _update_graalRuntime_inline_hpp(dist):
-    """
-    (Re)generates graalRuntime.inline.hpp based on a given distribution
-    that transitively represents all the input for the generation process.
-
-    A SHA1 digest is computed for all generated content and is written to
-    graalRuntime.inline.hpp as well as stored in a generated class
-    that is appended to the dist.path jar. At runtime, these two digests
-    are checked for consistency.
-    """
-
-    p = mx.project('com.oracle.graal.hotspot.sourcegen')
-    mainClass = 'com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp'
-    if exists(join(p.output_dir(), mainClass.replace('.', os.sep) + '.class')):
-        genSrcDir = _makeHotspotGeneratedSourcesDir()
-        graalRuntime_inline_hpp = join(genSrcDir, 'graalRuntime.inline.hpp')
-        cp = os.pathsep.join([mx.distribution(d).path for d in dist.distDependencies] + [dist.path, p.output_dir()])
-        tmp = StringIO.StringIO()
-        mx.run_java(['-cp', mx._separatedCygpathU2W(cp), mainClass], out=tmp.write)
-
-        # Compute SHA1 for currently generated graalRuntime.inline.hpp content
-        # and all other generated sources in genSrcDir
-        d = hashlib.sha1()
-        d.update(tmp.getvalue())
-        for e in os.listdir(genSrcDir):
-            if e != 'graalRuntime.inline.hpp':
-                with open(join(genSrcDir, e)) as fp:
-                    d.update(fp.read())
-        sha1 = d.hexdigest()
-
-        # Add SHA1 to end of graalRuntime.inline.hpp
-        print >> tmp, ''
-        print >> tmp, 'const char* GraalRuntime::_generated_sources_sha1 = "' + sha1 + '";'
-
-        mx.update_file(graalRuntime_inline_hpp, tmp.getvalue())
-
-        # Store SHA1 in generated Java class and append class to specified jar
-        javaPackageName = 'com.oracle.graal.hotspot.sourcegen'
-        javaClassName = javaPackageName + '.GeneratedSourcesSha1'
-        javaSource = join(_graal_home, 'GeneratedSourcesSha1.java')
-        javaClass = join(_graal_home, javaClassName.replace('.', os.path.sep) + '.class')
-        with open(javaSource, 'w') as fp:
-            print >> fp, 'package ' + javaPackageName + ';'
-            print >> fp, 'class GeneratedSourcesSha1 { private static final String value = "' + sha1 + '"; }'
-        subprocess.check_call([mx.java().javac, '-d', mx._cygpathU2W(_graal_home), mx._cygpathU2W(javaSource)], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
-        zf = zipfile.ZipFile(dist.path, 'a')
-        with open(javaClass, 'rb') as fp:
-            zf.writestr(javaClassName.replace('.', '/') + '.class', fp.read())
-        zf.close()
-        os.unlink(javaSource)
-        os.unlink(javaClass)
-        javaClassParent = os.path.dirname(javaClass)
-        while len(os.listdir(javaClassParent)) == 0:
-            os.rmdir(javaClassParent)
-            javaClassParent = os.path.dirname(javaClassParent)
-
 def _copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE):
     name = os.path.basename(src)
     dstLib = join(dst, name)
@@ -666,27 +609,41 @@
             filtered.append(className)
     return filtered
 
-def _extractGraalServiceFiles(graalJars, destination, cleanDestination=True):
+def _extractGraalFiles(graalJars, servicesDir, optionsDir, cleanDestination=True):
     if cleanDestination:
-        if exists(destination):
-            shutil.rmtree(destination)
-        os.makedirs(destination)
+        if exists(servicesDir):
+            shutil.rmtree(servicesDir)
+        if exists(optionsDir):
+            shutil.rmtree(optionsDir)
+    if not exists(servicesDir):
+        os.makedirs(servicesDir)
+    if not exists(optionsDir):
+        os.makedirs(optionsDir)
     servicesMap = {}
+    optionsFiles = []
     for jar in graalJars:
         if os.path.isfile(jar):
             with zipfile.ZipFile(jar) as zf:
                 for member in zf.namelist():
-                    if not member.startswith('META-INF/services'):
-                        continue
-                    serviceName = basename(member)
-                    # we don't handle directories
-                    assert serviceName and member == 'META-INF/services/' + serviceName
-                    with zf.open(member) as serviceFile:
-                        serviceImpls = servicesMap.setdefault(serviceName, [])
-                        for line in serviceFile.readlines():
-                            line = line.strip()
-                            if line:
-                                serviceImpls.append(line)
+                    if member.startswith('META-INF/services'):
+                        serviceName = basename(member)
+                        # we don't handle directories
+                        assert serviceName and member == 'META-INF/services/' + serviceName
+                        with zf.open(member) as serviceFile:
+                            serviceImpls = servicesMap.setdefault(serviceName, [])
+                            for line in serviceFile.readlines():
+                                line = line.strip()
+                                if line:
+                                    serviceImpls.append(line)
+                    elif member.startswith('META-INF/options'):
+                        filename = basename(member)
+                        # we don't handle directories
+                        assert filename and member == 'META-INF/options/' + filename
+                        targetpath = join(optionsDir, filename)
+                        optionsFiles.append(filename)
+                        with zf.open(member) as optionsFile, \
+                             file(targetpath, "wb") as target:
+                            shutil.copyfileobj(optionsFile, target)
     graalServices = _filterGraalService(servicesMap.keys(), graalJars)
     for serviceName in graalServices:
         serviceImpls = servicesMap[serviceName]
@@ -694,18 +651,19 @@
         f = os.fdopen(fd, 'w+')
         for serviceImpl in serviceImpls:
             f.write(serviceImpl + os.linesep)
-        target = join(destination, serviceName)
+        target = join(servicesDir, serviceName)
         f.close()
         shutil.move(tmp, target)
         if mx.get_os() != 'windows':
             os.chmod(target, JDK_UNIX_PERMISSIONS_FILE)
-    return graalServices
-
-def _updateGraalServiceFiles(jdkDir):
+    return (graalServices, optionsFiles)
+
+def _updateGraalFiles(jdkDir):
     jreGraalDir = join(jdkDir, 'jre', 'lib', 'graal')
     graalJars = [join(jreGraalDir, e) for e in os.listdir(jreGraalDir) if e.startswith('graal') and e.endswith('.jar')]
     jreGraalServicesDir = join(jreGraalDir, 'services')
-    _extractGraalServiceFiles(graalJars, jreGraalServicesDir)
+    jreGraalOptionsDir = join(jreGraalDir, 'options')
+    _extractGraalFiles(graalJars, jreGraalServicesDir, jreGraalOptionsDir)
 
 
 
@@ -715,17 +673,7 @@
     """
 
     dist = mx.distribution(deployableDist.name)
-
-    if dist.name == 'GRAAL_TRUFFLE':
-        # The content in graalRuntime.inline.hpp is generated from Graal
-        # classes that implement com.oracle.graal.api.runtime.Service
-        # or contain com.oracle.graal.options.Option annotated fields.
-        # Since GRAAL_TRUFFLE is the leaf most distribution containing
-        # such classes, the generation is triggered when GRAAL_TRUFFLE
-        # is (re)built.
-        _update_graalRuntime_inline_hpp(dist)
     jdks = _jdksDir()
-
     if exists(jdks):
         for e in os.listdir(jdks):
             jdkDir = join(jdks, e)
@@ -744,7 +692,7 @@
                     _copyToJdk(dist.sourcesPath, jdkDir)
                 if deployableDist.isGraalClassLoader:
                     # deploy service files
-                    _updateGraalServiceFiles(jdkDir)
+                    _updateGraalFiles(jdkDir)
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
@@ -919,11 +867,15 @@
             if defLine not in defs:
                 mx.abort('Missing following line in ' + defsPath + '\n' + defLine)
             shutil.copy(dist.path, opts2.export_dir)
-        services = _extractGraalServiceFiles(graalJars, join(opts2.export_dir, 'services'))
+        services, optionsFiles = _extractGraalFiles(graalJars, join(opts2.export_dir, 'services'), join(opts2.export_dir, 'options'))
         for service in services:
             defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_SERVICES_DIR)/' + service
             if defLine not in defs:
                 mx.abort('Missing following line in ' + defsPath + ' for service from ' + dist.name + '\n' + defLine)
+        for optionsFile in optionsFiles:
+            defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/' + optionsFile
+            if defLine not in defs:
+                mx.abort('Missing following line in ' + defsPath + ' for options from ' + dist.name + '\n' + defLine)
         graalOptions = join(_graal_home, 'graal.options')
         if exists(graalOptions):
             shutil.copy(graalOptions, opts2.export_dir)
@@ -1766,7 +1718,7 @@
 
     # Force
     if not mx._opts.strict_compliance:
-        mx.log("[gate] foring strict compliance")
+        mx.log("[gate] forcing strict compliance")
         mx._opts.strict_compliance = True
 
     tasks = []
--- a/mx/suite.py	Thu May 28 21:25:21 2015 +0200
+++ b/mx/suite.py	Thu May 28 21:26:54 2015 +0200
@@ -326,15 +326,6 @@
       "workingSets" : "Graal,HotSpot",
     },
 
-    "com.oracle.graal.hotspot.sourcegen" : {
-      "subDir" : "graal",
-      "sourceDirs" : ["src"],
-      "dependencies" : ["com.oracle.graal.hotspot"],
-      "checkstyle" : "com.oracle.graal.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "Graal,HotSpot",
-    },
-
     "com.oracle.graal.hotspot.jfr" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
@@ -403,6 +394,9 @@
     "com.oracle.graal.options" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
+      "dependencies" : [
+        "com.oracle.graal.api.runtime",
+      ],
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal",
@@ -457,7 +451,6 @@
         "com.oracle.graal.nodeinfo",
         "com.oracle.graal.compiler.common",
         "com.oracle.graal.api.collections",
-        "com.oracle.graal.api.runtime",
         "FINDBUGS",
       ],
       "javaCompliance" : "1.8",
--- a/mxtool/mx.py	Thu May 28 21:25:21 2015 +0200
+++ b/mxtool/mx.py	Thu May 28 21:26:54 2015 +0200
@@ -1681,7 +1681,7 @@
         self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
         self.add_argument('--java-home', help='primary JDK directory (must be JDK 7 or later)', metavar='<path>')
         self.add_argument('--extra-java-homes', help='secondary JDK directories separated by "' + os.pathsep + '"', metavar='<path>')
-        self.add_argument('--strict-compliance', action='store_true', dest='strict_compliance', help='Projects of a certain compliance will only be built with a JDK of this exact compliance', default=False)
+        self.add_argument('--strict-compliance', action='store_true', dest='strict_compliance', help='Projects with an explicit compliance will only be built if a JDK exactly matching the compliance is available', default=False)
         self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
         self.add_argument('--kill-with-sigquit', action='store_true', dest='killwithsigquit', help='send sigquit first before killing child processes')
         if get_os() != 'windows':
--- a/src/share/vm/classfile/systemDictionary.hpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu May 28 21:26:54 2015 +0200
@@ -225,7 +225,6 @@
   GRAAL_ONLY(do_klass(DebugInfo_klass,                       com_oracle_graal_api_code_DebugInfo,                          Graal)) \
   GRAAL_ONLY(do_klass(RegisterSaveLayout_klass,              com_oracle_graal_api_code_RegisterSaveLayout,                 Graal)) \
   GRAAL_ONLY(do_klass(BytecodeFrame_klass,                   com_oracle_graal_api_code_BytecodeFrame,                      Graal)) \
-  GRAAL_ONLY(do_klass(CompilationResult_klass,               com_oracle_graal_api_code_CompilationResult,                  Graal)) \
   GRAAL_ONLY(do_klass(CompilationResult_Call_klass,          com_oracle_graal_api_code_CompilationResult_Call,             Graal)) \
   GRAAL_ONLY(do_klass(CompilationResult_ConstantReference_klass, com_oracle_graal_api_code_CompilationResult_ConstantReference, Graal)) \
   GRAAL_ONLY(do_klass(CompilationResult_DataPatch_klass,     com_oracle_graal_api_code_CompilationResult_DataPatch,        Graal)) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu May 28 21:26:54 2015 +0200
@@ -334,7 +334,6 @@
   GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/meta/Assumptions$NoFinalizableSubclass")) \
   GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_ConcreteMethod,     "com/oracle/graal/api/meta/Assumptions$ConcreteMethod"))          \
   GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_CallSiteTargetValue,"com/oracle/graal/api/meta/Assumptions$CallSiteTargetValue"))     \
-  GRAAL_ONLY(template(com_oracle_graal_api_code_CompilationResult,              "com/oracle/graal/api/code/CompilationResult"))                   \
   GRAAL_ONLY(template(com_oracle_graal_api_code_CompilationResult_Call,         "com/oracle/graal/api/code/CompilationResult$Call"))              \
   GRAAL_ONLY(template(com_oracle_graal_api_code_CompilationResult_ConstantReference, "com/oracle/graal/api/code/CompilationResult$ConstantReference")) \
   GRAAL_ONLY(template(com_oracle_graal_api_code_CompilationResult_DataPatch,    "com/oracle/graal/api/code/CompilationResult$DataPatch"))         \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu May 28 21:26:54 2015 +0200
@@ -390,7 +390,7 @@
   CompilerThread* compilerThread = thread->is_Compiler_thread() ? thread->as_CompilerThread() : NULL;
   _oop_recorder = new OopRecorder(&_arena, true);
   _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL);
-  objArrayHandle assumptions = CompilationResult::assumptions(HotSpotCompiledCode::comp(compiled_code));
+  objArrayHandle assumptions = HotSpotCompiledCode::assumptions(compiled_code);
   if (!assumptions.is_null()) {
     int length = assumptions->length();
     for (int i = 0; i < length; ++i) {
@@ -413,7 +413,7 @@
       }
     }
   }
-  objArrayHandle methods = CompilationResult::methods(HotSpotCompiledCode::comp(compiled_code));
+  objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code);
   if (!methods.is_null()) {
     int length = methods->length();
     for (int i = 0; i < length; ++i) {
@@ -483,7 +483,6 @@
 }
 
 void CodeInstaller::initialize_fields(oop compiled_code) {
-  Handle comp_result = HotSpotCompiledCode::comp(compiled_code);
   if (compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
     Handle hotspotJavaMethod = HotSpotCompiledNmethod::method(compiled_code);
     methodHandle method = getMethodFromHotSpotMethod(hotspotJavaMethod());
@@ -497,10 +496,10 @@
   _sites_handle = JNIHandles::make_local(HotSpotCompiledCode::sites(compiled_code));
   _exception_handlers_handle = JNIHandles::make_local(HotSpotCompiledCode::exceptionHandlers(compiled_code));
 
-  _code_handle = JNIHandles::make_local(CompilationResult::targetCode(comp_result));
-  _code_size = CompilationResult::targetCodeSize(comp_result);
-  _total_frame_size = CompilationResult::totalFrameSize(comp_result);
-  _custom_stack_area_offset = CompilationResult::customStackAreaOffset(comp_result);
+  _code_handle = JNIHandles::make_local(HotSpotCompiledCode::targetCode(compiled_code));
+  _code_size = HotSpotCompiledCode::targetCodeSize(compiled_code);
+  _total_frame_size = HotSpotCompiledCode::totalFrameSize(compiled_code);
+  _custom_stack_area_offset = HotSpotCompiledCode::customStackAreaOffset(compiled_code);
 
   // Pre-calculate the constants section size.  This is required for PC-relative addressing.
   _data_section_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSection(compiled_code));
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu May 28 21:26:54 2015 +0200
@@ -502,7 +502,6 @@
       assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
       InstalledCode::set_address(installed_code_handle, (jlong) cb);
       InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
-      oop comp_result = HotSpotCompiledCode::comp(compiled_code_handle);
       if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
         HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
         HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalHashtable.cpp	Thu May 28 21:26:54 2015 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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 "graal/graalHashtable.hpp"
+
+template<class K, class V> bool GraalHashtable<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 (GraalHashtableEntry<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;
+    }
+  }
+  GraalHashtableEntry<V>* e = new GraalHashtableEntry<V>(value);
+  e->set_next(_buckets[index]);
+  _buckets[index] = e;
+  ++_number_of_entries;
+  return true;
+}
+
+template<class K, class V> V* GraalHashtable<K,V>::get(K key) {
+  unsigned int index = index_for(key);
+  for (GraalHashtableEntry<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 GraalHashtable<K, V>::for_each(ValueClosure<V>* closure) {
+  for (size_t i = 0; i < table_size(); ++i) {
+    for (GraalHashtableEntry<V>* e = bucket(i); e != NULL && !closure->is_aborted(); e = e->next()) {
+      closure->do_value(e->literal_addr());
+    }
+  }
+}
+
+template<class K, class V> GraalHashtable<K,V>::~GraalHashtable() {
+  for (size_t i = 0; i < table_size(); ++i) {
+    GraalHashtableEntry<V>* e = bucket(i);
+    while (e != NULL) {
+      GraalHashtableEntry<V>* current = e;
+      e = e->next();
+      delete current;
+    }
+  }
+  FREE_C_HEAP_ARRAY(GraalHashtableEntry*, _buckets, mtCompiler);
+}
+
+// Instantiation
+#include "graal/graalOptions.hpp"
+template class GraalHashtable<const char*, OptionDesc>;
+template class GraalHashtable<const char*, OptionValue>;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalHashtable.hpp	Thu May 28 21:26:54 2015 +0200
@@ -0,0 +1,137 @@
+/*
+ * 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_GRAAL_GRAAL_HASHTABLE_HPP
+#define SHARE_VM_GRAAL_GRAAL_HASHTABLE_HPP
+
+#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
+
+// based on hashtable.hpp
+
+template <class T> class GraalHashtableEntry : public CHeapObj<mtCompiler> {
+  friend class VMStructs;
+private:
+  T               _literal;       // ref to item in table.
+  GraalHashtableEntry*  _next;          // Link to next element in the linked list for this bucket
+
+public:
+  GraalHashtableEntry(T literal) :  _literal(literal), _next(NULL) {}
+
+  T literal() {
+    return _literal;
+  }
+
+  void set_literal(T value) {
+    _literal = value;
+  }
+
+  T* literal_addr() {
+    return &_literal;
+  }
+
+  GraalHashtableEntry* next() const {
+    return _next;
+  }
+
+  void set_next(GraalHashtableEntry* 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 GraalHashtable : public CHeapObj<mtCompiler> {
+  friend class VMStructs;
+private:
+  // Instance variables
+  unsigned int             _table_size;
+  GraalHashtableEntry<V>** _buckets;
+  unsigned int             _number_of_entries;
+
+public:
+  GraalHashtable(size_t size) : _table_size(size), _number_of_entries(0) {
+    _buckets = NEW_C_HEAP_ARRAY(GraalHashtableEntry<V>*, table_size(), mtCompiler);
+    for (size_t i = 0; i < table_size(); ++i) {
+      _buckets[i] = NULL;
+    }
+  }
+  virtual ~GraalHashtable();
+
+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; }
+
+  GraalHashtableEntry<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_GRAAL_GRAAL_HASHTABLE_HPP
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu May 28 21:26:54 2015 +0200
@@ -68,13 +68,18 @@
     boolean_field(HotSpotNmethod, isDefault)                                                                                                                   \
   end_class                                                                                                                                                    \
   start_class(HotSpotCompiledCode)                                                                                                                             \
-    oop_field(HotSpotCompiledCode, comp, "Lcom/oracle/graal/api/code/CompilationResult;")                                                                      \
     objArrayOop_field(HotSpotCompiledCode, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;")                                                       \
     objArrayOop_field(HotSpotCompiledCode, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;")                               \
     objArrayOop_field(HotSpotCompiledCode, comments, "[Lcom/oracle/graal/hotspot/HotSpotCompiledCode$Comment;")                                                \
+    objArrayOop_field(HotSpotCompiledCode, assumptions, "[Lcom/oracle/graal/api/meta/Assumptions$Assumption;")                                                 \
+    typeArrayOop_field(HotSpotCompiledCode, targetCode, "[B")                                                                                                  \
+    int_field(HotSpotCompiledCode, targetCodeSize)                                                                                                             \
     typeArrayOop_field(HotSpotCompiledCode, dataSection, "[B")                                                                                                 \
     int_field(HotSpotCompiledCode, dataSectionAlignment)                                                                                                       \
     objArrayOop_field(HotSpotCompiledCode, dataSectionPatches, "[Lcom/oracle/graal/api/code/CompilationResult$DataPatch;")                                     \
+    int_field(HotSpotCompiledCode, totalFrameSize)                                                                                                             \
+    int_field(HotSpotCompiledCode, customStackAreaOffset)                                                                                                      \
+    objArrayOop_field(HotSpotCompiledCode, methods, "[Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")                                                         \
   end_class                                                                                                                                                    \
   start_class(HotSpotCompiledCode_Comment)                                                                                                                     \
     oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;")                                                                                         \
@@ -93,14 +98,6 @@
   start_class(HotSpotForeignCallLinkageImpl)                                                                                                                   \
     long_field(HotSpotForeignCallLinkageImpl, address)                                                                                                         \
   end_class                                                                                                                                                    \
-  start_class(CompilationResult)                                                                                                                               \
-    int_field(CompilationResult, totalFrameSize)                                                                                                               \
-    int_field(CompilationResult, customStackAreaOffset)                                                                                                        \
-    typeArrayOop_field(CompilationResult, targetCode, "[B")                                                                                                    \
-    objArrayOop_field(CompilationResult, assumptions, "[Lcom/oracle/graal/api/meta/Assumptions$Assumption;")                                                   \
-    objArrayOop_field(CompilationResult, methods, "[Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")                                                           \
-    int_field(CompilationResult, targetCodeSize)                                                                                                               \
-  end_class                                                                                                                                                    \
   start_class(Assumptions_NoFinalizableSubclass)                                                                                                               \
     oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                 \
   end_class                                                                                                                                                    \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalOptions.cpp	Thu May 28 21:26:54 2015 +0200
@@ -0,0 +1,241 @@
+/*
+ * 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 "graal/graalOptions.hpp"
+#include "graal/graalRuntime.hpp"
+#include "runtime/arguments.hpp"
+#include "utilities/hashtable.inline.hpp"
+
+class OptionsParseClosure : public ParseClosure {
+  OptionsTable* _table;
+public:
+  OptionsParseClosure(OptionsTable* 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("unkown 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) {
+    FREE_C_HEAP_ARRAY(char, desc->name, mtCompiler);
+  }
+};
+
+OptionsTable::~OptionsTable() {
+  FreeNamesClosure closure;
+  for_each(&closure);
+}
+
+OptionsTable* OptionsTable::load_options() {
+  OptionsTable* table = new OptionsTable();
+  // 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%sgraal%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);
+    OptionsParseClosure 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);
+      GraalRuntime::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 graal options directory (%s)",optionsDir);
+  return table;
+}
+
+OptionDesc* OptionsTable::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 GraalHashtable<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 * OptionsTable::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);
+    }
+  }
+};
+
+OptionsValueTable::~OptionsValueTable() {
+  FreeStringsClosure closure;
+  for_each(&closure);
+  delete _table;
+}
+
+
+
+OptionValue* OptionsValueTable::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 GraalHashtable<const char*, OptionValue>::get(nameOnly);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalOptions.hpp	Thu May 28 21:26:54 2015 +0200
@@ -0,0 +1,103 @@
+/*
+ * 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_GRAAL_GRAAL_OPTIONS_HPP
+#define SHARE_VM_GRAAL_GRAAL_OPTIONS_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/exceptions.hpp"
+#include "graal/graalHashtable.hpp"
+
+#define PRINT_FLAGS_ARG "PrintFlags"
+#define PRINT_FLAGS_HELP "Prints all Graal 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 OptionsTable : public GraalHashtable<const char*, OptionDesc> {
+protected:
+  unsigned int compute_hash(const char* key) { return compute_string_hash(key, 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:
+  OptionsTable() : GraalHashtable<const char*, OptionDesc>(100) {}
+  ~OptionsTable();
+  using GraalHashtable<const char*, OptionDesc>::get;
+  OptionDesc* get(const char* name, size_t arglen);
+  OptionDesc * fuzzy_match(const char* name, size_t length);
+
+  static OptionsTable* 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 OptionsValueTable : public GraalHashtable<const char*, OptionValue> {
+  OptionsTable* _table;
+protected:
+  unsigned int compute_hash(const char* key) { return compute_string_hash(key, 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:
+  OptionsValueTable(OptionsTable* table) : _table(table), GraalHashtable<const char*, OptionValue>(100) {}
+  ~OptionsValueTable();
+  using GraalHashtable<const char*, OptionValue>::get;
+  OptionValue* get(const char* name, size_t arglen);
+  OptionsTable* options_table() { return _table; }
+};
+
+
+#endif // SHARE_VM_GRAAL_GRAAL_OPTIONS_HPP
--- a/src/share/vm/graal/graalRuntime.cpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Thu May 28 21:26:54 2015 +0200
@@ -37,6 +37,7 @@
 #include "runtime/arguments.hpp"
 #include "runtime/reflection.hpp"
 #include "utilities/debug.hpp"
+#include "utilities/defaultStream.hpp"
 
 jobject GraalRuntime::_HotSpotGraalRuntime_instance = NULL;
 bool GraalRuntime::_HotSpotGraalRuntime_initialized = false;
@@ -625,6 +626,11 @@
   SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_GRAAL_WKID, scan, CHECK);
 JVM_END
 
+// boolean com.oracle.graal.hotspot.HotSpotOptions.isCITimingEnabled()
+JVM_ENTRY(jboolean, JVM_IsCITimingEnabled(JNIEnv *env, jclass c))
+  return CITime || CITimeEach;
+JVM_END
+
 // private static GraalRuntime Graal.initializeRuntime()
 JVM_ENTRY(jobject, JVM_GetGraalRuntime(JNIEnv *env, jclass c))
   GraalRuntime::initialize_HotSpotGraalRuntime();
@@ -665,26 +671,9 @@
   return JNIHandles::make_local(THREAD, (oop) result.get_jobject());
 JVM_END
 
-void GraalRuntime::check_generated_sources_sha1(TRAPS) {
-  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/sourcegen/GeneratedSourcesSha1", CHECK_ABORT);
-  KlassHandle klass = load_required_class(name);
-  fieldDescriptor fd;
-  if (!InstanceKlass::cast(klass())->find_field(vmSymbols::value_name(), vmSymbols::string_signature(), true, &fd)) {
-    THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), "GeneratedSourcesSha1.value");
-  }
-
-  Symbol* value = java_lang_String::as_symbol(klass->java_mirror()->obj_field(fd.offset()), CHECK);
-  if (!value->equals(_generated_sources_sha1)) {
-    char buf[200];
-    jio_snprintf(buf, sizeof(buf), "Generated sources SHA1 check failed (%s != %s) - need to rebuild the VM", value->as_C_string(), _generated_sources_sha1);
-    THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
-  }
-}
-
 Handle GraalRuntime::callInitializer(const char* className, const char* methodName, const char* returnType) {
   guarantee(!_HotSpotGraalRuntime_initialized, "cannot reinitialize HotSpotGraalRuntime");
   Thread* THREAD = Thread::current();
-  check_generated_sources_sha1(CHECK_ABORT_(Handle()));
 
   TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_ABORT_(Handle()));
   KlassHandle klass = load_required_class(name);
@@ -725,14 +714,6 @@
   GraalRuntime::initialize_natives(env, c2vmClass);
 JVM_END
 
-// private static void HotSpotOptions.parseVMOptions()
-JVM_ENTRY(void, JVM_ParseGraalOptions(JNIEnv *env, jclass c))
-  HandleMark hm;
-  KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c)));
-  GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK);
-JVM_END
-
-
 void GraalRuntime::ensure_graal_class_loader_is_initialized() {
   // This initialization code is guarded by a static pointer to the Factory class.
   // Once it is non-null, the Graal class loader and well known Graal classes are
@@ -771,235 +752,316 @@
     *((jboolean *) addr) = (jboolean) UseGraalClassLoader;
     klass->initialize(CHECK_ABORT);
     _FactoryKlass = klass();
+    assert(!UseGraalClassLoader || SystemDictionary::graal_loader() != NULL, "Graal classloader should have been initialized");
   }
 }
 
-jint GraalRuntime::check_arguments(TRAPS) {
-  KlassHandle nullHandle;
-  parse_arguments(nullHandle, THREAD);
-  if (HAS_PENDING_EXCEPTION) {
-    // Errors in parsing Graal arguments cause exceptions.
-    // We now load and initialize HotSpotOptions which in turn
-    // causes argument parsing to be redone with better error messages.
-    CLEAR_PENDING_EXCEPTION;
-    TempNewSymbol name = SymbolTable::new_symbol("Lcom/oracle/graal/hotspot/HotSpotOptions;", CHECK_ABORT_(JNI_ERR));
-    instanceKlassHandle hotSpotOptionsClass = resolve_or_fail(name, CHECK_ABORT_(JNI_ERR));
-
-    parse_arguments(hotSpotOptionsClass, THREAD);
-    assert(HAS_PENDING_EXCEPTION, "must be");
+OptionsValueTable* GraalRuntime::parse_arguments() {
+  OptionsTable* table = OptionsTable::load_options();
+  if (table == NULL) {
+    return NULL;
+  }
 
-    ResourceMark rm;
-    Handle exception = PENDING_EXCEPTION;
-    CLEAR_PENDING_EXCEPTION;
-    oop message = java_lang_Throwable::message(exception);
-    if (message != NULL) {
-      tty->print_cr("Error parsing Graal options: %s", java_lang_String::as_utf8_string(message));
-    } else {
-      call_printStackTrace(exception, THREAD);
-    }
-    return JNI_ERR;
-  }
-  return JNI_OK;
-}
-
-void GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) {
-  ResourceMark rm(THREAD);
+  OptionsValueTable* options = new OptionsValueTable(table);
 
   // Process option overrides from graal.options first
-  parse_graal_options_file(hotSpotOptionsClass, CHECK);
+  parse_graal_options_file(options);
 
   // Now process options on the command line
   int numOptions = Arguments::num_graal_args();
   for (int i = 0; i < numOptions; i++) {
     char* arg = Arguments::graal_args_array()[i];
-    parse_argument(hotSpotOptionsClass, arg, CHECK);
+    if (!parse_argument(options, arg)) {
+      delete options;
+      return NULL;
+    }
   }
+  return options;
 }
 
-void GraalRuntime::check_required_value(const char* name, size_t name_len, const char* value, TRAPS) {
-  if (value == NULL) {
-    char buf[200];
-    jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=<value>' format for %.*s option", name_len, name, name_len, name);
-    THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
+void not_found(OptionsTable* 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>");
   }
 }
 
-void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) {
-  ensure_graal_class_loader_is_initialized();
+bool GraalRuntime::parse_argument(OptionsValueTable* options, const char* arg) {
+  OptionsTable* table = options->options_table();
   char first = arg[0];
-  char* name;
+  const char* name;
   size_t name_len;
-  bool recognized = true;
   if (first == '+' || first == '-') {
     name = arg + 1;
-    name_len = strlen(name);
-    recognized = set_option_bool(hotSpotOptionsClass, name, name_len, first, CHECK);
+    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 {
-    char* sep = strchr(arg, '=');
+    const char* sep = strchr(arg, '=');
     name = arg;
-    char* value = NULL;
+    const char* value = NULL;
     if (sep != NULL) {
       name_len = sep - name;
       value = sep + 1;
     } else {
       name_len = strlen(name);
     }
-    recognized = set_option(hotSpotOptionsClass, name, name_len, value, CHECK);
-  }
-
-  if (!recognized) {
-    bool throw_err = hotSpotOptionsClass.is_null();
-    if (!hotSpotOptionsClass.is_null()) {
-      set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), ' ', Handle(), 0L);
-      if (!HAS_PENDING_EXCEPTION) {
-        throw_err = true;
-      }
+    OptionDesc* optionDesc = table->get(name, name_len);
+    if (optionDesc == NULL) {
+      not_found(table, name, name_len);
+      return false;
     }
-
-    if (throw_err) {
-      char buf[200];
-      jio_snprintf(buf, sizeof(buf), "Unrecognized Graal option %.*s", name_len, name);
-      THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
+    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;
     }
-  }
-}
-
-void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) {
-  const char* home = Arguments::get_java_home();
-  size_t path_len = strlen(home) + strlen("/lib/graal.options") + 1;
-  char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
-  char sep = os::file_separator()[0];
-  sprintf(path, "%s%clib%cgraal.options", home, sep, sep);
-
-  struct stat st;
-  if (os::stat(path, &st) == 0) {
-    int file_handle = os::open(path, 0, 0);
-    if (file_handle != -1) {
-      char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size);
-      int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size);
-      if (num_read == -1) {
-        warning("Error reading file %s due to %s", path, strerror(errno));
-      } else if (num_read != st.st_size) {
-        warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path);
+    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;
       }
-      os::close(file_handle);
-      if (num_read == st.st_size) {
-        char* line = buffer;
-        int lineNo = 1;
-        while (line - buffer < num_read) {
-          char* nl = strchr(line, '\n');
-          if (nl != NULL) {
-            *nl = '\0';
-          }
-          parse_argument(hotSpotOptionsClass, line, THREAD);
-          if (HAS_PENDING_EXCEPTION) {
-            warning("Error in %s:%d", path, lineNo);
-            return;
-          }
-          if (nl != NULL) {
-            line = nl + 1;
-            lineNo++;
-          } else {
-            // File without newline at the end
-            break;
-          }
+      case _float: {
+        optionValue.float_value = ::strtof(value, &check);
+        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;
       }
-    } else {
-      warning("Error opening file %s due to %s", path, strerror(errno));
+      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;
   }
 }
 
-jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS) {
-  check_required_value(name, name_len, value, CHECK_(0L));
-  union {
-    jint i;
-    jlong l;
-    double d;
-  } uu;
-  uu.l = 0L;
-  char dummy;
-  switch (spec) {
-    case 'd':
-    case 'f': {
-      if (sscanf(value, "%lf%c", &uu.d, &dummy) == 1) {
-        return uu.l;
-      }
-      break;
+class GraalOptionParseClosure : public ParseClosure {
+  OptionsValueTable* _options;
+public:
+  GraalOptionParseClosure(OptionsValueTable* options) : _options(options) {}
+  void do_line(char* line) {
+    if (!GraalRuntime::parse_argument(_options, line)) {
+      warn("There was an error parsing an argument. Skipping it.");
     }
-    case 'i': {
-      if (sscanf(value, "%d%c", &uu.i, &dummy) == 1) {
-        return (jlong)uu.i;
-      }
-      break;
-    }
-    default:
-      ShouldNotReachHere();
   }
-  ResourceMark rm(THREAD);
-  char buf[200];
-  bool missing = strlen(value) == 0;
-  if (missing) {
-    jio_snprintf(buf, sizeof(buf), "Missing %s value for Graal option %.*s", (spec == 'i' ? "numeric" : "float/double"), name_len, name);
-  } else {
-    jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %.*s: %s", (spec == 'i' ? "numeric" : "float/double"), name_len, name, value);
-  }
-  THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L);
+};
+
+void GraalRuntime::parse_graal_options_file(OptionsValueTable* options) {
+  const char* home = Arguments::get_java_home();
+  size_t path_len = strlen(home) + strlen("/lib/graal.options") + 1;
+  char path[JVM_MAXPATHLEN];
+  char sep = os::file_separator()[0];
+  jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cgraal.options", home, sep, sep);
+  GraalOptionParseClosure closure(options);
+  parse_lines(path, &closure, false);
 }
 
-void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) {
-  Thread* THREAD = Thread::current();
-  Handle name_handle;
-  if (name != NULL) {
-    if (strlen(name) > name_len) {
-      // Temporarily replace '=' with NULL to create the Java string for the option name
-      char save = name[name_len];
-      name[name_len] = '\0';
-      name_handle = java_lang_String::create_from_str(name, THREAD);
-      name[name_len] = '=';
-      if (HAS_PENDING_EXCEPTION) {
-        return;
+#define CHECK_WARN_ABORT_(message) THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    warning(message); \
+    char buf[512]; \
+    jio_snprintf(buf, 512, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
+    return; \
+  } \
+  (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];
       }
-    } else {
-      assert(strlen(name) == name_len, "must be");
-      name_handle = java_lang_String::create_from_str(name, CHECK);
+    }
+    declaringClassBinary[declaringClassLen] = '\0';
+
+    TempNewSymbol name = SymbolTable::new_symbol(declaringClassBinary, CHECK_WARN_ABORT_("Declaring class could not be found"));
+    Klass* klass = GraalRuntime::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 GraalRuntime::set_options(OptionsValueTable* options, TRAPS) {
+  ensure_graal_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);
+  }
+}
 
-  TempNewSymbol setOption = SymbolTable::new_symbol("setOption", CHECK);
-  TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", CHECK);
+void GraalRuntime::print_flags_helper(TRAPS) {
+  // TODO(gd) write this in C++?
+  HandleMark hm(THREAD);
+  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", CHECK_ABORT);
+  KlassHandle hotSpotOptionsClass = load_required_class(name);
+  TempNewSymbol setOption = SymbolTable::new_symbol("printFlags", CHECK);
   JavaValue result(T_VOID);
   JavaCallArguments args;
-  args.push_oop(name_handle());
-  args.push_oop(option());
-  args.push_int(spec);
-  args.push_oop(stringValue());
-  args.push_long(primitiveValue);
-  JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, CHECK);
-}
-
-Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) {
-  TempNewSymbol name = SymbolTable::new_symbol(declaringClass, CHECK_NH);
-  Klass* klass = resolve_or_fail(name, CHECK_NH);
-
-  // 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)strlen(fieldSig));
-  if (fieldname == NULL || signame == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle());
-  }
-  // Make sure class is initialized before handing id's out to fields
-  klass->initialize(CHECK_NH);
-
-  fieldDescriptor fd;
-  if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) {
-    THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle());
-  }
-
-  Handle ret = klass->java_mirror()->obj_field(fd.offset());
-  return ret;
+  JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, vmSymbols::void_method_signature(), &args, CHECK);
 }
 
 Handle GraalRuntime::create_Service(const char* name, TRAPS) {
@@ -1074,18 +1136,12 @@
   return klass;
 }
 
-Handle GraalRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) {
-  const char* home = Arguments::get_java_home();
-  const char* serviceName = serviceKlass->external_name();
-  size_t path_len = strlen(home) + strlen("/lib/graal/services/") + strlen(serviceName) + 1;
-  char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
-  char sep = os::file_separator()[0];
-  sprintf(path, "%s%clib%cgraal%cservices%c%s", home, sep, sep, sep, sep, serviceName);
+void GraalRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) {
   struct stat st;
-  if (os::stat(path, &st) == 0) {
+  if (os::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file
     int file_handle = os::open(path, 0, 0);
     if (file_handle != -1) {
-      char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size + 1);
+      char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal);
       int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size);
       if (num_read == -1) {
         warning("Error reading file %s due to %s", path, strerror(errno));
@@ -1093,11 +1149,12 @@
         warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path);
       }
       os::close(file_handle);
+      closure->set_filename(path);
       if (num_read == st.st_size) {
         buffer[num_read] = '\0';
-        GrowableArray<char*>* implNames = new GrowableArray<char*>();
+
         char* line = buffer;
-        while (line - buffer < num_read) {
+        while (line - buffer < num_read && !closure->is_aborted()) {
           // find line end (\r, \n or \r\n)
           char* nextline = NULL;
           char* cr = strchr(line, '\r');
@@ -1125,13 +1182,7 @@
           *end = '\0';
           // skip comments and empty lines
           if (*line != '#' && strlen(line) > 0) {
-            // Turn all '.'s into '/'s
-            for (size_t index = 0; line[index] != '\0'; index++) {
-              if (line[index] == '.') {
-                line[index] = '/';
-              }
-            }
-            implNames->append(line);
+            closure->parse_line(line);
           }
           if (nextline != NULL) {
             line = nextline;
@@ -1140,23 +1191,55 @@
             break;
           }
         }
-
-        objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), implNames->length(), CHECK_NH);
-        objArrayHandle services(THREAD, servicesOop);
-        for (int i = 0; i < implNames->length(); ++i) {
-          char* implName = implNames->at(i);
-          Handle service = create_Service(implName, CHECK_NH);
-          services->obj_at_put(i, service());
-        }
-        return services;
       }
+      FREE_C_HEAP_ARRAY(char, buffer, mtInternal);
     } else {
       warning("Error opening file %s due to %s", path, strerror(errno));
     }
-  } else {
-    warning("Error opening file %s due to %s", path, strerror(errno));
+  } else if (warnStatFailure) {
+    warning("Could not stat file %s due to %s", path, strerror(errno));
   }
-  return Handle();
 }
 
-#include "graalRuntime.inline.hpp"
+class ServiceParseClosure : public ParseClosure {
+  GrowableArray<char*> _implNames;
+public:
+  ServiceParseClosure() : _implNames() {}
+  void do_line(char* line) {
+    size_t lineLen = strlen(line);
+    char* implName = NEW_C_HEAP_ARRAY(char, lineLen + 1, mtCompiler); // TODO (gd) i'm leaking
+    // Turn all '.'s into '/'s
+    for (size_t index = 0; index < lineLen; ++index) {
+      if (line[index] == '.') {
+        implName[index] = '/';
+      } else {
+        implName[index] = line[index];
+      }
+    }
+    implName[lineLen] = '\0';
+    _implNames.append(implName);
+  }
+  GrowableArray<char*>* implNames() {return &_implNames;}
+};
+
+
+Handle GraalRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) {
+  const char* home = Arguments::get_java_home();
+  const char* serviceName = serviceKlass->external_name();
+  size_t path_len = strlen(home) + strlen("/lib/graal/services/") + strlen(serviceName) + 1;
+  char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
+  char sep = os::file_separator()[0];
+  sprintf(path, "%s%clib%cgraal%cservices%c%s", home, sep, sep, sep, sep, serviceName);
+  ServiceParseClosure closure;
+  parse_lines(path, &closure, true); // TODO(gd) cache parsing results?
+
+  GrowableArray<char*>* implNames = closure.implNames();
+  objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), implNames->length(), CHECK_NH);
+  objArrayHandle services(THREAD, servicesOop);
+  for (int i = 0; i < implNames->length(); ++i) {
+    char* implName = implNames->at(i);
+    Handle service = create_Service(implName, CHECK_NH);
+    services->obj_at_put(i, service());
+  }
+  return services;
+}
--- a/src/share/vm/graal/graalRuntime.hpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Thu May 28 21:26:54 2015 +0200
@@ -27,91 +27,49 @@
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/deoptimization.hpp"
+#include "graal/graalOptions.hpp"
+
+class ParseClosure : public StackObj {
+  int _lineNo;
+  char* _filename;
+  bool _abort;
+protected:
+  void abort() { _abort = true; }
+  void warn_and_abort(const char* message) {
+    warn(message);
+    abort();
+  }
+  void warn(const char* message) {
+    warning("Error at line %d while parsing %s: %s", _lineNo, _filename == NULL ? "?" : _filename, message);
+  }
+ public:
+  ParseClosure() : _lineNo(0), _filename(NULL), _abort(false) {}
+  void parse_line(char* line) {
+    _lineNo++;
+    do_line(line);
+  }
+  virtual void do_line(char* line) = 0;
+  int lineNo() { return _lineNo; }
+  bool is_aborted() { return _abort; }
+  void set_filename(char* path) {_filename = path; _lineNo = 0;}
+};
 
 class GraalRuntime: public CHeapObj<mtCompiler> {
  private:
-
   static jobject _HotSpotGraalRuntime_instance;
   static bool _HotSpotGraalRuntime_initialized;
-  static const char* _generated_sources_sha1;
 
   static bool _shutdown_called;
 
   /**
-   * Reads the OptionValue object from a specified static field.
-   *
-   * @throws LinkageError if the field could not be resolved
-   */
-  static Handle get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS);
-
-  /**
-   * Parses the string form of a numeric, float or double option into a jlong (using raw bits for floats/doubles).
-   *
-   * @param spec 'i', 'f' or 'd' (see HotSpotOptions.setOption())
-   * @param name option name
-   * @param name_len length of option name
-   * @param value string value to parse
-   * @throws InternalError if value could not be parsed according to spec
-   */
-  static jlong parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS);
-
-  /**
    * Loads default option value overrides from a <jre_home>/lib/graal.options if it exists. Each
    * line in this file must have the format of a Graal command line option without the
    * leading "-G:" prefix. These option values are set prior to processing of any Graal
    * options present on the command line.
    */
-  static void parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS);
-
-  /**
-   * Parses a given argument and sets the denoted Graal option.
-   *
-   * @throws InternalError if there was a problem parsing or setting the option
-   */
-  static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS);
-
-  /**
-   * Searches for a Boolean Graal option denoted by a given name and sets it value.
-   *
-   * The definition of this method is in graalRuntime.inline.hpp
-   * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.
-   *
-   * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option
-   * @param name option name
-   * @param name_len length of option name
-   * @param value '+' to set the option, '-' to reset the option
-   * @returns true if the option was found
-   * @throws InternalError if there was a problem setting the option's value
-   */
-  static bool set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS);
+  static void parse_graal_options_file(OptionsValueTable* options);
 
-  /**
-   * Searches for a Graal option denoted by a given name and sets it value.
-   *
-   * The definition of this method is in graalRuntime.inline.hpp
-   * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.
-   *
-   * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option
-   * @param name option name
-   * @param name_len length of option name
-   * @returns true if the option was found
-   * @throws InternalError if there was a problem setting the option's value
-   */
-  static bool set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS);
-
-  /**
-   * Raises an InternalError for an option that expects a value but was specified without a "=<value>" prefix.
-   */
-  static void check_required_value(const char* name, size_t name_len, const char* value, TRAPS);
-
-  /**
-   * Java call to HotSpotOptions.setOption(String name, OptionValue<?> option, char spec, String stringValue, long primitiveValue)
-   *
-   * @param name option name
-   * @param name_len length of option name
-   */
-  static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue);
-
+  static void print_flags_helper(TRAPS);
   /**
    * Instantiates a service object, calls its default constructor and returns it.
    *
@@ -119,12 +77,17 @@
    */
   static Handle create_Service(const char* name, TRAPS);
 
+ public:
+
   /**
-   * Checks that _generated_sources_sha1 equals GeneratedSourcesSha1.value.
+   * Parses the Graal specific VM options that were presented by the launcher and sets
+   * the relevants Java fields.
    */
-  static void check_generated_sources_sha1(TRAPS);
+  static OptionsValueTable* parse_arguments();
 
- public:
+  static bool parse_argument(OptionsValueTable* options, const char* arg);
+
+  static void set_options(OptionsValueTable* options, TRAPS);
 
   /**
    * Ensures that the Graal class loader is initialized and the well known Graal classes are loaded.
@@ -171,12 +134,11 @@
    * Given an interface representing a Graal service (i.e. sub-interface of
    * com.oracle.graal.api.runtime.Service), gets an array of objects, one per
    * known implementation of the service.
-   *
-   * The definition of this method is in graalRuntime.inline.hpp
-   * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.
    */
   static Handle get_service_impls(KlassHandle serviceKlass, TRAPS);
 
+  static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure);
+
   /**
    * Aborts the VM due to an unexpected exception.
    */
@@ -222,20 +184,6 @@
 
   static BufferBlob* initialize_buffer_blob();
 
-  /**
-   * Checks that all Graal specific VM options presented by the launcher are recognized
-   * and formatted correctly. To set relevant Java fields from the option, parse_arguments()
-   * must be called. This method makes no Java calls apart from creating exception objects
-   * if there is an errors in the Graal options.
-   */
-  static jint check_arguments(TRAPS);
-
-  /**
-   * Parses the JVMCI specific VM options that were presented by the launcher and sets
-   * the relevants Java fields.
-   */
-  static void parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS);
-
   static BasicType kindToBasicType(jchar ch);
 
   // The following routines are all called from compiled Graal code
--- a/src/share/vm/prims/nativeLookup.cpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/prims/nativeLookup.cpp	Thu May 28 21:26:54 2015 +0200
@@ -133,7 +133,7 @@
   jobject  JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c, jclass serviceClass);
   jobject  JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c);
   jobject  JNICALL JVM_CreateNativeFunctionInterface(JNIEnv *env, jclass c);
-  jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass);
+  jboolean JNICALL JVM_IsCITimingEnabled(JNIEnv *env);
 #ifdef COMPILERGRAAL
   void     JNICALL JVM_PrintAndResetGraalCompRate(JNIEnv *env, jclass c);
 #endif
@@ -155,7 +155,7 @@
   { CC"Java_com_oracle_truffle_api_Truffle_createRuntime",                                                NULL, FN_PTR(JVM_CreateTruffleRuntime)               },
   { CC"Java_com_oracle_nfi_NativeFunctionInterfaceRuntime_createInterface",                               NULL, FN_PTR(JVM_CreateNativeFunctionInterface)      },
   { CC"Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_init",                                       NULL, FN_PTR(JVM_InitializeGraalNatives)             },
-  { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions",                                      NULL, FN_PTR(JVM_ParseGraalOptions)                  },
+  { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_isCITimingEnabled",                                   NULL, FN_PTR(JVM_IsCITimingEnabled)                  },
 #endif
 };
 
--- a/src/share/vm/runtime/arguments.cpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Thu May 28 21:26:54 2015 +0200
@@ -3617,7 +3617,7 @@
 
 #ifdef GRAAL
   if (!UseGraalClassLoader) {
-    // Append lib/graal/graal*.jar to boot class path
+    // Append lib/graal/*.jar to boot class path
     char graalDir[JVM_MAXPATHLEN];
     const char* fileSep = os::file_separator();
     jio_snprintf(graalDir, sizeof(graalDir), "%s%slib%sgraal", Arguments::get_java_home(), fileSep, fileSep);
@@ -3628,9 +3628,7 @@
       while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
         const char* name = entry->d_name;
         const char* ext = name + strlen(name) - 4;
-        if (ext > name && strcmp(ext, ".jar") == 0
-            && strlen(name) > strlen("graal")
-            && strncmp(name, "graal", strlen("graal")) == 0) {
+        if (ext > name && strcmp(ext, ".jar") == 0) {
           char fileName[JVM_MAXPATHLEN];
           jio_snprintf(fileName, sizeof(fileName), "%s%s%s", graalDir, fileSep, name);
           scp_p->add_suffix(fileName);
--- a/src/share/vm/runtime/thread.cpp	Thu May 28 21:25:21 2015 +0200
+++ b/src/share/vm/runtime/thread.cpp	Thu May 28 21:26:54 2015 +0200
@@ -3395,6 +3395,13 @@
   jint parse_result = Arguments::parse(args);
   if (parse_result != JNI_OK) return parse_result;
 
+#ifdef GRAAL
+  OptionsValueTable* options = GraalRuntime::parse_arguments();
+  if (options == NULL) {
+    return JNI_ERR;
+  }
+#endif
+
   os::init_before_ergo();
 
   jint ergo_result = Arguments::apply_ergo();
@@ -3703,11 +3710,7 @@
   }
 
 #ifdef GRAAL
-  status = GraalRuntime::check_arguments(main_thread);
-  if (status != JNI_OK) {
-    *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again
-    return status;
-  }
+  GraalRuntime::set_options(options, main_thread);
 #endif
 
   // initialize compiler(s)