changeset 23209:f35e653aa876

moved @Option mechanism from JVMCI to Graal (GRAAL-1371)
author Doug Simon <doug.simon@oracle.com>
date Mon, 21 Dec 2015 16:19:35 +0100
parents 58eb143a8259
children 942a54aadb47
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/BackendOptions.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/OptionsVerifierTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompilerOptions.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/GraalDebugConfig.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/CompressedNullCheckTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/LoadJavaMirrorWithKlassTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorldOptions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompilerFactory.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTTYStreamProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/PrintStreamOption.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraalConstantReflectionProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippetsOptions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippetsOptions.java graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParserOptions.java graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/backend/ConstantPhiTest.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/backend/LargeConstantSectionTest.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_instanceof01.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/LambdaEagerTest.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/phases/StackMoveOptimizationPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/OptimizingLinearScanWalker.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceRegisterAllocationPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/lsra/TraceLinearScan.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DefaultLoopPolicies.java graal/com.oracle.graal.options.processor/src/META-INF/services/javax.annotation.processing.Processor graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java graal/com.oracle.graal.options.test/src/com/oracle/graal/options/test/NestedBooleanOptionValueTest.java graal/com.oracle.graal.options.test/src/com/oracle/graal/options/test/TestOptionValue.java graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java graal/com.oracle.graal.options/src/com/oracle/graal/options/GraalJarsOptionDescriptorsProvider.java graal/com.oracle.graal.options/src/com/oracle/graal/options/NestedBooleanOptionValue.java graal/com.oracle.graal.options/src/com/oracle/graal/options/Option.java graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptors.java graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionType.java graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsLoader.java graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsParser.java graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java graal/com.oracle.graal.salver/src/com/oracle/graal/salver/SalverOptions.java graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntimeAccess.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/LazyInitializationTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGetOptionBuiltin.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLSetOptionBuiltin.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java mx.graal/mx_graal_8.py mx.graal/mx_graal_9.py mx.graal/suite.py
diffstat 81 files changed, 2532 insertions(+), 223 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/BackendOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/BackendOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.compiler.common;
 
-import jdk.vm.ci.options.DerivedOptionValue;
-import jdk.vm.ci.options.DerivedOptionValue.OptionSupplier;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
+import com.oracle.graal.options.DerivedOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.DerivedOptionValue.OptionSupplier;
 
 /**
  * Options to control the backend configuration.
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.compiler.common;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.StableOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.StableOptionValue;
 
 /**
  * This class encapsulates options that control the behavior of the Graal compiler.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -58,7 +58,6 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.SpeculationLog;
-import jdk.vm.ci.options.DerivedOptionValue;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -102,6 +101,7 @@
 import com.oracle.graal.nodes.spi.LoweringProvider;
 import com.oracle.graal.nodes.spi.Replacements;
 import com.oracle.graal.nodes.virtual.VirtualObjectNode;
+import com.oracle.graal.options.DerivedOptionValue;
 import com.oracle.graal.phases.BasePhase;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.Phase;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -31,9 +31,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
-
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -53,6 +50,8 @@
 import com.oracle.graal.nodes.memory.WriteNode;
 import com.oracle.graal.nodes.spi.LoweringTool;
 import com.oracle.graal.nodes.util.GraphUtil;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.common.FloatingReadPhase;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/OptionsVerifierTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/OptionsVerifierTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -48,12 +48,13 @@
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.vm.ci.options.OptionDescriptor;
-import jdk.vm.ci.options.OptionDescriptors;
-import jdk.vm.ci.options.OptionValue;
 
 import org.junit.Test;
 
+import com.oracle.graal.options.OptionDescriptor;
+import com.oracle.graal.options.OptionDescriptors;
+import com.oracle.graal.options.OptionValue;
+
 /**
  * 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
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Dec 21 16:19:35 2015 +0100
@@ -44,8 +44,6 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.TriState;
 import jdk.vm.ci.meta.VMConstant;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
 
 import com.oracle.graal.compiler.LIRGenerationPhase.LIRGenerationContext;
 import com.oracle.graal.compiler.common.alloc.ComputeBlockOrder;
@@ -72,6 +70,8 @@
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.PhaseSuite;
 import com.oracle.graal.phases.common.DeadCodeEliminationPhase;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompilerOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompilerOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.compiler;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * Options related to {@link GraalCompiler}.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Dec 21 16:19:35 2015 +0100
@@ -33,9 +33,6 @@
 import static com.oracle.graal.compiler.common.GraalOptions.PartialEscapeAnalysis;
 import static com.oracle.graal.compiler.common.GraalOptions.UseGraalInstrumentation;
 import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Optional;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.loop.DefaultLoopPolicies;
 import com.oracle.graal.loop.LoopPolicies;
@@ -43,6 +40,9 @@
 import com.oracle.graal.loop.phases.LoopPeelingPhase;
 import com.oracle.graal.loop.phases.LoopUnswitchingPhase;
 import com.oracle.graal.nodes.spi.LoweringTool;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.PhaseSuite;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.common.ConvertDeoptimizeToGuardPhase;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Mon Dec 21 16:19:35 2015 +0100
@@ -27,11 +27,11 @@
 import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer;
 import static com.oracle.graal.compiler.common.GraalOptions.UseGraalInstrumentation;
 import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Required;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.nodes.spi.LoweringTool;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.PhaseSuite;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.common.DeadCodeEliminationPhase;
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/GraalDebugConfig.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/GraalDebugConfig.java	Mon Dec 21 16:19:35 2015 +0100
@@ -29,11 +29,12 @@
 import java.util.List;
 import java.util.Set;
 
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
+
 import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.meta.JavaMethod;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 public class GraalDebugConfig implements DebugConfig {
     @SuppressWarnings("all")
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Dec 21 16:19:35 2015 +0100
@@ -32,9 +32,6 @@
 import java.util.function.Consumer;
 
 import jdk.vm.ci.common.JVMCIError;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.CollectionsFactory;
 import com.oracle.graal.debug.Debug;
@@ -44,6 +41,9 @@
 import com.oracle.graal.debug.Fingerprint;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.iterators.NodeIterable;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * This class is a graph container, it contains the set of nodes that belong to this graph.
--- a/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/CompressedNullCheckTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/CompressedNullCheckTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -24,8 +24,6 @@
 
 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
 
 import org.junit.Assert;
 import org.junit.Assume;
@@ -37,6 +35,8 @@
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.IsNullNode;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 
 /**
  * Ensures that frame omission works in cases where it is expected to.
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -34,8 +34,6 @@
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
 
 import org.junit.Assert;
 import org.junit.Ignore;
@@ -54,6 +52,8 @@
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.memory.FloatingReadNode;
 import com.oracle.graal.nodes.memory.ReadNode;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.tiers.Suites;
 import com.oracle.graal.phases.tiers.SuitesProvider;
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/LoadJavaMirrorWithKlassTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/LoadJavaMirrorWithKlassTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -25,8 +25,6 @@
 import java.util.Objects;
 
 import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
 
 import org.junit.Test;
 
@@ -34,6 +32,8 @@
 import com.oracle.graal.compiler.test.GraalCompilerTest;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 import com.oracle.graal.phases.tiers.Suites;
 
 public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java	Mon Dec 21 16:19:35 2015 +0100
@@ -143,7 +143,7 @@
             HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime();
             int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
             HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, jvmciEnv);
-            CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, false);
+            CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false);
             task.runCompilation();
         }
     }
@@ -160,7 +160,7 @@
             try (AllocSpy as = AllocSpy.open(methodName)) {
                 HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime();
                 HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, JVMCICompiler.INVOCATION_ENTRY_BCI, jvmciEnv);
-                CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, false);
+                CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false);
                 task.runCompilation();
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Dec 21 16:19:35 2015 +0100
@@ -105,6 +105,8 @@
      */
     private final boolean installAsDefault;
 
+    private final boolean useProfilingInfo;
+
     static class Lazy {
         /**
          * A {@link com.sun.management.ThreadMXBean} to be able to query some information about the
@@ -113,10 +115,11 @@
         static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
     }
 
-    public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean installAsDefault) {
+    public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) {
         this.jvmciRuntime = jvmciRuntime;
         this.compiler = compiler;
         this.request = request;
+        this.useProfilingInfo = useProfilingInfo;
         this.installAsDefault = installAsDefault;
     }
 
@@ -192,7 +195,7 @@
             try (Scope s = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(getId()), true))) {
                 // Begin the compilation event.
                 compilationEvent.begin();
-                result = compiler.compile(method, entryBCI);
+                result = compiler.compile(method, entryBCI, useProfilingInfo);
             } catch (Throwable e) {
                 throw Debug.handle(e);
             } finally {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Dec 21 16:19:35 2015 +0100
@@ -71,11 +71,6 @@
 import jdk.vm.ci.hotspot.HotSpotVMConfig;
 import jdk.vm.ci.meta.ConstantPool;
 import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.options.OptionDescriptor;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
-import jdk.vm.ci.options.OptionsParser;
-import jdk.vm.ci.options.OptionsParser.OptionConsumer;
 import jdk.vm.ci.runtime.JVMCI;
 import jdk.vm.ci.runtime.JVMCICompiler;
 
@@ -89,6 +84,11 @@
 import com.oracle.graal.debug.TTY;
 import com.oracle.graal.debug.internal.DebugScope;
 import com.oracle.graal.debug.internal.MemUseTrackerImpl;
+import com.oracle.graal.options.OptionDescriptor;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
+import com.oracle.graal.options.OptionsParser;
+import com.oracle.graal.options.OptionsParser.OptionConsumer;
 
 /**
  * This class implements compile-the-world functionality with JVMCI.
@@ -228,7 +228,6 @@
         // ...but we want to see exceptions.
         config.putIfAbsent(PrintBailout, true);
         config.putIfAbsent(PrintStackTraceOnException, true);
-        config.putIfAbsent(HotSpotResolvedJavaMethod.Options.UseProfilingInformation, false);
     }
 
     public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler) {
@@ -481,7 +480,9 @@
             HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(
                             CompileTheWorld.class.getDeclaredMethod("dummy"));
             int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
-            CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), false);
+            boolean useProfilingInfo = false;
+            boolean installAsDefault = false;
+            CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault);
             task.runCompilation();
         } catch (NoSuchMethodException | SecurityException e1) {
             e1.printStackTrace();
@@ -676,7 +677,10 @@
             long allocatedAtStart = MemUseTrackerImpl.getCurrentThreadAllocatedBytes();
             int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
             HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
-            CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, false);
+            // For more stable CTW execution, disable use of profiling information
+            boolean useProfilingInfo = false;
+            boolean installAsDefault = false;
+            CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault);
             task.runCompilation();
 
             memoryUsed.getAndAdd(MemUseTrackerImpl.getCurrentThreadAllocatedBytes() - allocatedAtStart);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorldOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorldOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.hotspot;
 
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
+
 import jdk.vm.ci.hotspot.HotSpotVMConfig;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 /**
  * Options related to {@link CompileTheWorld}.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Dec 21 16:19:35 2015 +0100
@@ -37,9 +37,6 @@
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotVMConfig;
 import jdk.vm.ci.meta.Value;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
 import com.oracle.graal.compiler.common.spi.ForeignCallDescriptor;
@@ -67,6 +64,9 @@
 import com.oracle.graal.lir.framemap.FrameMap;
 import com.oracle.graal.lir.framemap.ReferenceMapBuilder;
 import com.oracle.graal.nodes.UnwindNode;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.tiers.SuitesProvider;
 import com.oracle.graal.word.Pointer;
 import com.oracle.graal.word.Word;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java	Mon Dec 21 16:19:35 2015 +0100
@@ -48,7 +48,6 @@
 import com.oracle.graal.debug.TopLevelDebugConfig;
 import com.oracle.graal.debug.internal.DebugScope;
 import com.oracle.graal.hotspot.meta.HotSpotProviders;
-import com.oracle.graal.hotspot.meta.HotSpotSuitesProvider;
 import com.oracle.graal.hotspot.phases.OnStackReplacementPhase;
 import com.oracle.graal.java.GraphBuilderPhase;
 import com.oracle.graal.lir.asm.CompilationResultBuilderFactory;
@@ -56,8 +55,9 @@
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.DebugInfoMode;
+import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext;
-import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.nodes.spi.Replacements;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.OptimisticOptimizations.Optimization;
@@ -88,7 +88,7 @@
             DebugEnvironment.initialize(TTY.out);
         }
 
-        CompilationTask task = new CompilationTask(jvmciRuntime, this, (HotSpotCompilationRequest) request, true);
+        CompilationTask task = new CompilationTask(jvmciRuntime, this, (HotSpotCompilationRequest) request, true, true);
         try (DebugConfigScope dcs = Debug.setConfig(new TopLevelDebugConfig())) {
             task.runCompilation();
         }
@@ -106,7 +106,7 @@
         System.exit(0);
     }
 
-    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI) {
+    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo) {
         HotSpotBackend backend = graalRuntime.getHostBackend();
         HotSpotProviders providers = backend.getProviders();
         final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
@@ -139,8 +139,9 @@
         }
         CompilationResult result = new CompilationResult();
         result.setEntryBCI(entryBCI);
-        GraalCompiler.compileGraph(graph, cc, method, providers, backend, getGraphBuilderSuite(providers, isOSR), optimisticOpts, profilingInfo, suites, lirSuites, result,
-                        CompilationResultBuilderFactory.Default);
+        boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints();
+        PhaseSuite<HighTierContext> graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR, useProfilingInfo);
+        GraalCompiler.compileGraph(graph, cc, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, CompilationResultBuilderFactory.Default);
 
         if (!isOSR) {
             ProfilingInfo profile = method.getProfilingInfo();
@@ -185,14 +186,46 @@
         return providers.getSuites().getDefaultLIRSuites();
     }
 
-    protected PhaseSuite<HighTierContext> getGraphBuilderSuite(HotSpotProviders providers, boolean isOSR) {
-        PhaseSuite<HighTierContext> suite = providers.getSuites().getDefaultGraphBuilderSuite();
-        if (providers.getCodeCache().shouldDebugNonSafepoints()) {
-            suite = HotSpotSuitesProvider.withSimpleDebugInfo(suite);
-        }
-        if (isOSR) {
-            suite = suite.copy();
-            suite.appendPhase(new OnStackReplacementPhase());
+    /**
+     * Reconfigures a given graph builder suite (GBS) if one of the given GBS parameter values is
+     * not the default.
+     *
+     * @param suite the graph builder suite
+     * @param shouldDebugNonSafepoints specifies if extra debug info should be generated (default is
+     *            false)
+     * @param isOSR specifies if extra OSR-specific post-processing is required (default is false)
+     * @param useProfilingInfo specifies if the graph builder should use profiling info (default is
+     *            true)
+     * @return a new suite derived from {@code suite} if any of the GBS parameters did not have a
+     *         default value otherwise {@code suite}
+     */
+    protected PhaseSuite<HighTierContext> configGraphBuilderSuite(PhaseSuite<HighTierContext> suite, boolean shouldDebugNonSafepoints, boolean isOSR, boolean useProfilingInfo) {
+        if (shouldDebugNonSafepoints || isOSR || !useProfilingInfo) {
+            PhaseSuite<HighTierContext> newGbs = suite.copy();
+
+            if (shouldDebugNonSafepoints || !useProfilingInfo) {
+                // This complexity below is to ensure exactly one
+                // GraphBuilderConfiguration copy is made.
+                GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous();
+                GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig();
+                if (shouldDebugNonSafepoints) {
+                    graphBuilderConfig = graphBuilderConfig.withDebugInfoMode(DebugInfoMode.Simple);
+                    if (!useProfilingInfo) {
+                        graphBuilderConfig.setUseProfiling(false);
+                    }
+                } else {
+                    assert !useProfilingInfo;
+                    graphBuilderConfig = graphBuilderConfig.copy();
+                    graphBuilderConfig.setUseProfiling(false);
+                }
+
+                GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig);
+                newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase);
+            }
+            if (isOSR) {
+                newGbs.appendPhase(new OnStackReplacementPhase());
+            }
+            return newGbs;
         }
         return suite;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompilerFactory.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompilerFactory.java	Mon Dec 21 16:19:35 2015 +0100
@@ -23,20 +23,39 @@
 package com.oracle.graal.hotspot;
 
 import static jdk.vm.ci.inittimer.InitTimer.timer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
 import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.inittimer.InitTimer;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
 import jdk.vm.ci.runtime.JVMCIRuntime;
 import jdk.vm.ci.service.Services;
+import sun.misc.VM;
 
+import com.oracle.graal.options.GraalJarsOptionDescriptorsProvider;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionsParser;
 import com.oracle.graal.phases.tiers.CompilerConfiguration;
 
 public abstract class HotSpotGraalCompilerFactory implements JVMCICompilerFactory {
 
+    static {
+        initializeOptions();
+    }
+
     static class Options {
 
         // @formatter:off
@@ -62,6 +81,73 @@
         }
     }
 
+    /**
+     * Parses the options in the file denoted by the {@linkplain VM#getSavedProperty(String) saved}
+     * system property named {@code "graal.options.file"} if the file exists followed by the options
+     * encoded in saved system properties whose names start with {@code "graal.option."}.
+     */
+    @SuppressWarnings("try")
+    private static void initializeOptions() {
+        try (InitTimer t = timer("InitializeOptions")) {
+            boolean jdk8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0;
+            GraalJarsOptionDescriptorsProvider odp = jdk8OrEarlier ? GraalJarsOptionDescriptorsProvider.create() : null;
+
+            String optionsFile = System.getProperty("graal.options.file");
+
+            if (optionsFile != null) {
+                File graalOptions = new File(optionsFile);
+                if (graalOptions.exists()) {
+                    try (BufferedReader br = new BufferedReader(new FileReader(graalOptions))) {
+                        String optionSetting = null;
+                        int lineNo = 1;
+                        List<String> optionSettings = new ArrayList<>();
+                        while ((optionSetting = br.readLine()) != null) {
+                            if (!optionSetting.isEmpty() && optionSetting.charAt(0) != '#') {
+                                try {
+                                    OptionsParser.parseOptionSettingTo(optionSetting, optionSettings);
+                                } catch (Throwable e) {
+                                    throw new InternalError("Error parsing " + graalOptions + ", line " + lineNo, e);
+                                }
+                            }
+                            lineNo++;
+                        }
+                        try {
+                            OptionsParser.parseOptions(optionSettings.toArray(new String[optionSettings.size()]), null, odp, null);
+                        } catch (Throwable e) {
+                            throw new InternalError("Error parsing an option from " + graalOptions, e);
+                        }
+                    } catch (IOException e) {
+                        throw new InternalError("Error reading " + graalOptions, e);
+                    }
+                }
+            }
+
+            Properties savedProps = getSavedProperties();
+
+            List<String> optionSettings = new ArrayList<>();
+            for (Map.Entry<Object, Object> e : savedProps.entrySet()) {
+                String name = (String) e.getKey();
+                if (name.startsWith("graal.option.")) {
+                    String value = (String) e.getValue();
+                    optionSettings.add(name.substring("graal.option.".length()));
+                    optionSettings.add(value);
+                }
+            }
+
+            OptionsParser.parseOptions(optionSettings.toArray(new String[optionSettings.size()]), null, odp, null);
+        }
+    }
+
+    private static Properties getSavedProperties() {
+        try {
+            Field savedPropsField = VM.class.getDeclaredField("savedProps");
+            savedPropsField.setAccessible(true);
+            return (Properties) savedPropsField.get(null);
+        } catch (Exception e) {
+            throw new JVMCIError(e);
+        }
+    }
+
     protected abstract HotSpotBackendFactory getBackendFactory(Architecture arch);
 
     protected abstract CompilerConfiguration createCompilerConfiguration();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTTYStreamProvider.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTTYStreamProvider.java	Mon Dec 21 16:19:35 2015 +0100
@@ -24,11 +24,11 @@
 
 import java.io.PrintStream;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
 import jdk.vm.ci.service.ServiceProvider;
 
 import com.oracle.graal.debug.TTYStreamProvider;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
 
 @ServiceProvider(TTYStreamProvider.class)
 public class HotSpotTTYStreamProvider implements TTYStreamProvider {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/PrintStreamOption.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/PrintStreamOption.java	Mon Dec 21 16:19:35 2015 +0100
@@ -29,9 +29,10 @@
 import java.io.PrintStream;
 import java.lang.management.ManagementFactory;
 
+import com.oracle.graal.options.OptionValue;
+
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
-import jdk.vm.ci.options.OptionValue;
 
 /**
  * An option that encapsulates and configures a print stream.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Mon Dec 21 16:19:35 2015 +0100
@@ -39,13 +39,13 @@
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotVMConfig;
 import jdk.vm.ci.inittimer.SuppressFBWarnings;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.debug.TTY;
 import com.oracle.graal.hotspot.replacements.NewObjectSnippets;
 import com.oracle.graal.nodes.debug.DynamicCounterNode;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 //JaCoCo Exclude
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraalConstantReflectionProvider.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraalConstantReflectionProvider.java	Mon Dec 21 16:19:35 2015 +0100
@@ -38,9 +38,12 @@
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.runtime.JVMCI;
 
 import com.oracle.graal.graph.NodeClass;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.StableOptionValue;
 import com.oracle.graal.replacements.ReplacementsImpl;
 import com.oracle.graal.replacements.SnippetCounter;
 import com.oracle.graal.replacements.SnippetTemplate;
@@ -56,10 +59,24 @@
         super(runtime);
     }
 
+    private ResolvedJavaType cachedStableOptionValueType;
+
+    /**
+     * The {@code value} field in {@link OptionValue} is considered constant if {@code receiver} is
+     * a {@link StableOptionValue} instance.
+     */
     @Override
     public JavaConstant readConstantFieldValue(ResolvedJavaField field, JavaConstant receiver) {
         MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
         assert !ImmutableCode.getValue() || isCalledForSnippets(metaAccess) || SnippetGraphUnderConstruction.get() != null || FieldReadEnabledInImmutableCode.get() == Boolean.TRUE : receiver;
+        if (!field.isStatic() && field.getName().equals("value")) {
+            if (cachedStableOptionValueType == null) {
+                cachedStableOptionValueType = metaAccess.lookupJavaType(StableOptionValue.class);
+            }
+            if (cachedStableOptionValueType.isInstance(receiver)) {
+                return readFieldValue(field, receiver);
+            }
+        }
         return super.readConstantFieldValue(field, receiver);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Mon Dec 21 16:19:35 2015 +0100
@@ -38,7 +38,6 @@
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.options.StableOptionValue;
 import jdk.vm.ci.service.Services;
 import sun.reflect.Reflection;
 
@@ -74,6 +73,7 @@
 import com.oracle.graal.nodes.memory.address.OffsetAddressNode;
 import com.oracle.graal.nodes.spi.StampProvider;
 import com.oracle.graal.nodes.util.GraphUtil;
+import com.oracle.graal.options.StableOptionValue;
 import com.oracle.graal.replacements.InlineDuringParsingPlugin;
 import com.oracle.graal.replacements.MethodHandlePlugin;
 import com.oracle.graal.replacements.NodeIntrinsificationPlugin;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Mon Dec 21 16:19:35 2015 +0100
@@ -25,8 +25,6 @@
 import static com.oracle.graal.compiler.common.GraalOptions.ImmutableCode;
 import static com.oracle.graal.compiler.common.GraalOptions.VerifyPhases;
 import jdk.vm.ci.hotspot.HotSpotVMConfig;
-import jdk.vm.ci.options.DerivedOptionValue;
-import jdk.vm.ci.options.DerivedOptionValue.OptionSupplier;
 
 import com.oracle.graal.hotspot.HotSpotBackend;
 import com.oracle.graal.hotspot.HotSpotGraalRuntimeProvider;
@@ -44,6 +42,8 @@
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.DebugInfoMode;
+import com.oracle.graal.options.DerivedOptionValue;
+import com.oracle.graal.options.DerivedOptionValue.OptionSupplier;
 import com.oracle.graal.phases.BasePhase;
 import com.oracle.graal.phases.PhaseSuite;
 import com.oracle.graal.phases.common.AddressLoweringPhase;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippetsOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippetsOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * Options related to {@link InstanceOfSnippets}.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Dec 21 16:19:35 2015 +0100
@@ -62,9 +62,6 @@
 import jdk.vm.ci.meta.LocationIdentity;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.api.replacements.Fold;
 import com.oracle.graal.compiler.common.spi.ForeignCallDescriptor;
@@ -99,6 +96,9 @@
 import com.oracle.graal.nodes.memory.address.OffsetAddressNode;
 import com.oracle.graal.nodes.spi.LoweringTool;
 import com.oracle.graal.nodes.type.StampTool;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.common.inlining.InliningUtil;
 import com.oracle.graal.replacements.Log;
 import com.oracle.graal.replacements.Snippet;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippetsOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippetsOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * Options related to {@link NewObjectSnippets}.
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParserOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParserOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.java;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.StableOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.StableOptionValue;
 
 /**
  * Options related to {@link BytecodeParser}.
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,12 +22,11 @@
  */
 package com.oracle.graal.java;
 
-import jdk.vm.ci.options.DerivedOptionValue;
-import jdk.vm.ci.options.DerivedOptionValue.OptionSupplier;
-
 import com.oracle.graal.lir.phases.LIRSuites;
 import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import com.oracle.graal.options.DerivedOptionValue;
+import com.oracle.graal.options.DerivedOptionValue.OptionSupplier;
 import com.oracle.graal.phases.PhaseSuite;
 import com.oracle.graal.phases.tiers.CompilerConfiguration;
 import com.oracle.graal.phases.tiers.HighTierContext;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/backend/ConstantPhiTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/backend/ConstantPhiTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -27,13 +27,12 @@
 
 import java.lang.reflect.Method;
 
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
-
 import org.junit.Test;
 
 import com.oracle.graal.compiler.common.GraalOptions;
 import com.oracle.graal.jtt.JTTTest;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 
 public class ConstantPhiTest extends JTTTest {
 
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/backend/LargeConstantSectionTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/backend/LargeConstantSectionTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -34,8 +34,6 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
 import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN;
 import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Label;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
@@ -48,6 +46,8 @@
 import com.oracle.graal.api.directives.GraalDirectives;
 import com.oracle.graal.compiler.common.GraalOptions;
 import com.oracle.graal.jtt.JTTTest;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 
 public class LargeConstantSectionTest extends JTTTest {
     private static final String NAME = "LargeConstantSection";
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_instanceof01.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_instanceof01.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,13 +22,12 @@
  */
 package com.oracle.graal.jtt.bytecode;
 
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
-
 import org.junit.Test;
 
 import com.oracle.graal.compiler.phases.HighTier;
 import com.oracle.graal.jtt.JTTTest;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 import com.oracle.graal.phases.tiers.Suites;
 
 /**
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/LambdaEagerTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/LambdaEagerTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -28,14 +28,14 @@
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.meta.DeoptimizationReason;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
 
 import org.junit.Test;
 
 import com.oracle.graal.compiler.common.GraalOptions;
 import com.oracle.graal.compiler.test.GraalCompilerTest;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 
 public class LambdaEagerTest extends GraalCompilerTest {
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/phases/StackMoveOptimizationPhase.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/phases/StackMoveOptimizationPhase.java	Mon Dec 21 16:19:35 2015 +0100
@@ -32,9 +32,6 @@
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.Value;
-import jdk.vm.ci.options.NestedBooleanOptionValue;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
 
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
 import com.oracle.graal.debug.Debug;
@@ -46,6 +43,9 @@
 import com.oracle.graal.lir.amd64.AMD64Move.AMD64StackMove;
 import com.oracle.graal.lir.gen.LIRGenerationResult;
 import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase;
+import com.oracle.graal.options.NestedBooleanOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
 
 /**
  * Replaces sequential {@link AMD64StackMove}s of the same type with a single
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java	Mon Dec 21 16:19:35 2015 +0100
@@ -45,10 +45,6 @@
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.LIRKind;
 import jdk.vm.ci.meta.Value;
-import jdk.vm.ci.options.NestedBooleanOptionValue;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig;
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
@@ -68,6 +64,10 @@
 import com.oracle.graal.lir.gen.LIRGenerationResult;
 import com.oracle.graal.lir.gen.LIRGeneratorTool.MoveFactory;
 import com.oracle.graal.lir.phases.AllocationPhase.AllocationContext;
+import com.oracle.graal.options.NestedBooleanOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * An implementation of the linear scan register allocator algorithm described in <a
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java	Mon Dec 21 16:19:35 2015 +0100
@@ -32,10 +32,6 @@
 
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.AllocatableValue;
-import jdk.vm.ci.options.NestedBooleanOptionValue;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
 import com.oracle.graal.debug.Debug;
@@ -49,6 +45,10 @@
 import com.oracle.graal.lir.alloc.lsra.LinearScan.IntervalPredicate;
 import com.oracle.graal.lir.gen.LIRGenerationResult;
 import com.oracle.graal.lir.phases.AllocationPhase;
+import com.oracle.graal.options.NestedBooleanOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 public class LinearScanEliminateSpillMovePhase extends AllocationPhase {
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/OptimizingLinearScanWalker.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/OptimizingLinearScanWalker.java	Mon Dec 21 16:19:35 2015 +0100
@@ -27,9 +27,6 @@
 import static jdk.vm.ci.code.ValueUtil.isRegister;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.meta.AllocatableValue;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
 import com.oracle.graal.debug.Debug;
@@ -39,6 +36,9 @@
 import com.oracle.graal.lir.alloc.lsra.Interval.RegisterBindingLists;
 import com.oracle.graal.lir.alloc.lsra.Interval.RegisterPriority;
 import com.oracle.graal.lir.alloc.lsra.Interval.State;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 public class OptimizingLinearScanWalker extends LinearScanWalker {
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceRegisterAllocationPhase.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceRegisterAllocationPhase.java	Mon Dec 21 16:19:35 2015 +0100
@@ -25,9 +25,6 @@
 import java.util.List;
 
 import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig;
 import com.oracle.graal.compiler.common.alloc.TraceBuilder;
@@ -49,6 +46,9 @@
 import com.oracle.graal.lir.phases.AllocationPhase;
 import com.oracle.graal.lir.ssi.SSIUtil;
 import com.oracle.graal.lir.ssi.SSIVerifier;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * An implementation of a Trace Register Allocator as described in <a
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/lsra/TraceLinearScan.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/lsra/TraceLinearScan.java	Mon Dec 21 16:19:35 2015 +0100
@@ -45,10 +45,6 @@
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.LIRKind;
 import jdk.vm.ci.meta.Value;
-import jdk.vm.ci.options.NestedBooleanOptionValue;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig;
 import com.oracle.graal.compiler.common.alloc.TraceBuilder.TraceBuilderResult;
@@ -71,6 +67,10 @@
 import com.oracle.graal.lir.gen.LIRGenerationResult;
 import com.oracle.graal.lir.gen.LIRGeneratorTool.MoveFactory;
 import com.oracle.graal.lir.phases.LIRPhase;
+import com.oracle.graal.options.NestedBooleanOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * An implementation of the linear scan register allocator algorithm described in <a
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Mon Dec 21 16:19:35 2015 +0100
@@ -50,9 +50,6 @@
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.VMConstant;
 import jdk.vm.ci.meta.Value;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.asm.AbstractAddress;
 import com.oracle.graal.asm.Assembler;
@@ -65,6 +62,9 @@
 import com.oracle.graal.lir.LIRInstruction;
 import com.oracle.graal.lir.LabelRef;
 import com.oracle.graal.lir.framemap.FrameMap;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * Fills in a {@link CompilationResult} as its code is being assembled.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Mon Dec 21 16:19:35 2015 +0100
@@ -37,9 +37,6 @@
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.LIRKind;
 import jdk.vm.ci.meta.Value;
-import jdk.vm.ci.options.NestedBooleanOptionValue;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
 
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
 import com.oracle.graal.compiler.common.cfg.BlockMap;
@@ -61,6 +58,9 @@
 import com.oracle.graal.lir.gen.LIRGenerationResult;
 import com.oracle.graal.lir.gen.LIRGeneratorTool;
 import com.oracle.graal.lir.phases.PreAllocationOptimizationPhase;
+import com.oracle.graal.options.NestedBooleanOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
 
 /**
  * This optimization tries to improve the handling of constants by replacing a single definition of
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Dec 21 16:19:35 2015 +0100
@@ -50,9 +50,6 @@
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.PlatformKind;
 import jdk.vm.ci.meta.Value;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.asm.Label;
 import com.oracle.graal.compiler.common.calc.Condition;
@@ -74,6 +71,9 @@
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.SwitchStrategy;
 import com.oracle.graal.lir.Variable;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * This class traverses the HIR instructions and generates LIR instructions from them.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java	Mon Dec 21 16:19:35 2015 +0100
@@ -26,9 +26,6 @@
 import java.util.regex.Pattern;
 
 import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
 import com.oracle.graal.debug.Debug;
@@ -38,6 +35,9 @@
 import com.oracle.graal.debug.DebugTimer;
 import com.oracle.graal.lir.LIR;
 import com.oracle.graal.lir.gen.LIRGenerationResult;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 /**
  * Base class for all {@link LIR low-level} phases. Subclasses should be stateless. There will be
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java	Mon Dec 21 16:19:35 2015 +0100
@@ -23,10 +23,6 @@
 package com.oracle.graal.lir.phases;
 
 import static com.oracle.graal.lir.phases.LIRPhase.Options.LIROptimization;
-import jdk.vm.ci.options.NestedBooleanOptionValue;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.lir.ControlFlowOptimizer;
 import com.oracle.graal.lir.EdgeMoveOptimizer;
@@ -34,6 +30,10 @@
 import com.oracle.graal.lir.RedundantMoveElimination;
 import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
 import com.oracle.graal.lir.profiling.MoveProfiling;
+import com.oracle.graal.options.NestedBooleanOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 public class PostAllocationOptimizationStage extends LIRPhaseSuite<PostAllocationOptimizationContext> {
     public static class Options {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java	Mon Dec 21 16:19:35 2015 +0100
@@ -40,9 +40,6 @@
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.LIRKind;
 import jdk.vm.ci.meta.Value;
-import jdk.vm.ci.options.NestedBooleanOptionValue;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
 
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
 import com.oracle.graal.debug.Debug;
@@ -61,6 +58,9 @@
 import com.oracle.graal.lir.framemap.VirtualStackSlotRange;
 import com.oracle.graal.lir.gen.LIRGenerationResult;
 import com.oracle.graal.lir.phases.AllocationPhase;
+import com.oracle.graal.options.NestedBooleanOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
 
 /**
  * Linear Scan {@link StackSlotAllocator}.
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DefaultLoopPolicies.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DefaultLoopPolicies.java	Mon Dec 21 16:19:35 2015 +0100
@@ -28,10 +28,6 @@
 
 import java.util.List;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
-
 import com.oracle.graal.debug.Debug;
 import com.oracle.graal.debug.DebugMetric;
 import com.oracle.graal.graph.Node;
@@ -44,6 +40,9 @@
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
 import com.oracle.graal.nodes.debug.ControlFlowAnchorNode;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 public class DefaultLoopPolicies implements LoopPolicies {
     @Option(help = "", type = OptionType.Expert) public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(500);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options.processor/src/META-INF/services/javax.annotation.processing.Processor	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,1 @@
+com.oracle.graal.options.processor.OptionProcessor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options.processor;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.JavaFileObject;
+
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionDescriptor;
+import com.oracle.graal.options.OptionDescriptors;
+import com.oracle.graal.options.OptionValue;
+
+/**
+ * Processes static fields annotated with {@link Option}. An {@link OptionDescriptors}
+ * implementation is generated for each top level class containing at least one such field. The name
+ * of the generated class for top level class {@code com.foo.Bar} is
+ * {@code com.foo.Bar_OptionDescriptors}.
+ */
+@SupportedAnnotationTypes({"com.oracle.graal.options.Option"})
+public class OptionProcessor extends AbstractProcessor {
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    private final Set<Element> processed = new HashSet<>();
+
+    private void processElement(Element element, OptionsInfo info) {
+
+        if (!element.getModifiers().contains(Modifier.STATIC)) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
+            return;
+        }
+        if (element.getModifiers().contains(Modifier.PRIVATE)) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field cannot be private", element);
+            return;
+        }
+
+        Option annotation = element.getAnnotation(Option.class);
+        assert annotation != null;
+        assert element instanceof VariableElement;
+        assert element.getKind() == ElementKind.FIELD;
+        VariableElement field = (VariableElement) element;
+        String fieldName = field.getSimpleName().toString();
+
+        Elements elements = processingEnv.getElementUtils();
+        Types types = processingEnv.getTypeUtils();
+
+        TypeMirror fieldType = field.asType();
+        if (fieldType.getKind() != TypeKind.DECLARED) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + OptionValue.class.getName(), element);
+            return;
+        }
+        DeclaredType declaredFieldType = (DeclaredType) fieldType;
+
+        TypeMirror optionValueType = elements.getTypeElement(OptionValue.class.getName()).asType();
+        if (!types.isSubtype(fieldType, types.erasure(optionValueType))) {
+            String msg = String.format("Option field type %s is not a subclass of %s", fieldType, optionValueType);
+            processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
+            return;
+        }
+
+        if (!field.getModifiers().contains(Modifier.STATIC)) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
+            return;
+        }
+        if (field.getModifiers().contains(Modifier.PRIVATE)) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "Option field cannot be private", element);
+            return;
+        }
+
+        String help = annotation.help();
+        if (help.length() != 0) {
+            char firstChar = help.charAt(0);
+            if (!Character.isUpperCase(firstChar)) {
+                processingEnv.getMessager().printMessage(Kind.ERROR, "Option help text must start with upper case letter", element);
+                return;
+            }
+        }
+
+        String optionName = annotation.name();
+        if (optionName.equals("")) {
+            optionName = fieldName;
+        }
+
+        DeclaredType declaredOptionValueType = declaredFieldType;
+        while (!types.isSameType(types.erasure(declaredOptionValueType), types.erasure(optionValueType))) {
+            List<? extends TypeMirror> directSupertypes = types.directSupertypes(declaredFieldType);
+            assert !directSupertypes.isEmpty();
+            declaredOptionValueType = (DeclaredType) directSupertypes.get(0);
+        }
+
+        assert !declaredOptionValueType.getTypeArguments().isEmpty();
+        String optionType = declaredOptionValueType.getTypeArguments().get(0).toString();
+        if (optionType.startsWith("java.lang.")) {
+            optionType = optionType.substring("java.lang.".length());
+        }
+
+        Element enclosing = element.getEnclosingElement();
+        String declaringClass = "";
+        String separator = "";
+        Set<Element> originatingElementsList = info.originatingElements;
+        originatingElementsList.add(field);
+        while (enclosing != null) {
+            if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) {
+                if (enclosing.getModifiers().contains(Modifier.PRIVATE)) {
+                    String msg = String.format("Option field cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing);
+                    processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
+                    return;
+                }
+                originatingElementsList.add(enclosing);
+                declaringClass = enclosing.getSimpleName() + separator + declaringClass;
+                separator = ".";
+            } else {
+                assert enclosing.getKind() == ElementKind.PACKAGE;
+            }
+            enclosing = enclosing.getEnclosingElement();
+        }
+
+        info.options.add(new OptionInfo(optionName, help, optionType, declaringClass, field));
+    }
+
+    private void createFiles(OptionsInfo info) {
+        String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString();
+        Name topDeclaringClass = info.topDeclaringType.getSimpleName();
+        Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]);
+
+        createOptionsDescriptorsFile(info, pkg, topDeclaringClass, originatingElements);
+    }
+
+    private void createOptionsDescriptorsFile(OptionsInfo info, String pkg, Name topDeclaringClass, Element[] originatingElements) {
+        String optionsClassName = topDeclaringClass + "_" + OptionDescriptors.class.getSimpleName();
+
+        Filer filer = processingEnv.getFiler();
+        try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) {
+
+            out.println("// CheckStyle: stop header check");
+            out.println("// CheckStyle: stop line length check");
+            out.println("// GENERATED CONTENT - DO NOT EDIT");
+            out.println("// Source: " + topDeclaringClass + ".java");
+            out.println("package " + pkg + ";");
+            out.println("");
+            out.println("import java.util.*;");
+            out.println("import " + OptionDescriptors.class.getPackage().getName() + ".*;");
+            out.println("");
+            out.println("public class " + optionsClassName + " implements " + OptionDescriptors.class.getSimpleName() + " {");
+
+            String desc = OptionDescriptor.class.getSimpleName();
+
+            int i = 0;
+            Collections.sort(info.options);
+
+            out.println("    @Override");
+            out.println("    public OptionDescriptor get(String value) {");
+            out.println("        // CheckStyle: stop line length check");
+            if (info.options.size() == 1) {
+                out.println("        if (value.equals(\"" + info.options.get(0).name + "\")) {");
+            } else {
+                out.println("        switch (value) {");
+            }
+            for (OptionInfo option : info.options) {
+                String name = option.name;
+                String optionValue;
+                if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
+                    throw new InternalError();
+                } else {
+                    optionValue = option.declaringClass + "." + option.field.getSimpleName();
+                }
+                String type = option.type;
+                String help = option.help;
+                String declaringClass = option.declaringClass;
+                Name fieldName = option.field.getSimpleName();
+                if (info.options.size() == 1) {
+                    out.printf("            return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
+                } else {
+                    out.printf("            case \"" + name + "\": return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
+                }
+            }
+            out.println("        }");
+            out.println("        // CheckStyle: resume line length check");
+            out.println("        return null;");
+            out.println("    }");
+            out.println();
+            out.println("    @Override");
+            out.println("    public Iterator<" + desc + "> iterator() {");
+            out.println("        // CheckStyle: stop line length check");
+            out.println("        List<" + desc + "> options = Arrays.asList(");
+            for (OptionInfo option : info.options) {
+                String optionValue;
+                if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
+                    throw new InternalError();
+                } else {
+                    optionValue = option.declaringClass + "." + option.field.getSimpleName();
+                }
+                String name = option.name;
+                String type = option.type;
+                String help = option.help;
+                String declaringClass = option.declaringClass;
+                Name fieldName = option.field.getSimpleName();
+                String comma = i == info.options.size() - 1 ? "" : ",";
+                out.printf("            %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s\n", desc, name, type, help, declaringClass, fieldName, optionValue, comma);
+                i++;
+            }
+            out.println("        );");
+            out.println("        // CheckStyle: resume line length check");
+            out.println("        return options.iterator();");
+            out.println("    }");
+            out.println("}");
+        }
+    }
+
+    protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) {
+        try {
+            // Ensure Unix line endings to comply with code style guide checked by Checkstyle
+            JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, originatingElements);
+            return new PrintWriter(sourceFile.openWriter()) {
+
+                @Override
+                public void println() {
+                    print("\n");
+                }
+            };
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static class OptionInfo implements Comparable<OptionInfo> {
+
+        final String name;
+        final String help;
+        final String type;
+        final String declaringClass;
+        final VariableElement field;
+
+        public OptionInfo(String name, String help, String type, String declaringClass, VariableElement field) {
+            this.name = name;
+            this.help = help;
+            this.type = type;
+            this.declaringClass = declaringClass;
+            this.field = field;
+        }
+
+        @Override
+        public int compareTo(OptionInfo other) {
+            return name.compareTo(other.name);
+        }
+
+        @Override
+        public String toString() {
+            return declaringClass + "." + field;
+        }
+    }
+
+    static class OptionsInfo {
+
+        final Element topDeclaringType;
+        final List<OptionInfo> options = new ArrayList<>();
+        final Set<Element> originatingElements = new HashSet<>();
+
+        public OptionsInfo(Element topDeclaringType) {
+            this.topDeclaringType = topDeclaringType;
+        }
+    }
+
+    private static Element topDeclaringType(Element element) {
+        Element enclosing = element.getEnclosingElement();
+        if (enclosing == null || enclosing.getKind() == ElementKind.PACKAGE) {
+            assert element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE;
+            return element;
+        }
+        return topDeclaringType(enclosing);
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver()) {
+            return true;
+        }
+
+        Map<Element, OptionsInfo> map = new HashMap<>();
+        for (Element element : roundEnv.getElementsAnnotatedWith(Option.class)) {
+            if (!processed.contains(element)) {
+                processed.add(element);
+                Element topDeclaringType = topDeclaringType(element);
+                OptionsInfo options = map.get(topDeclaringType);
+                if (options == null) {
+                    options = new OptionsInfo(topDeclaringType);
+                    map.put(topDeclaringType, options);
+                }
+                processElement(element, options);
+            }
+        }
+
+        boolean ok = true;
+        Map<String, OptionInfo> uniqueness = new HashMap<>();
+        for (OptionsInfo info : map.values()) {
+            for (OptionInfo option : info.options) {
+                OptionInfo conflict = uniqueness.put(option.name, option);
+                if (conflict != null) {
+                    processingEnv.getMessager().printMessage(Kind.ERROR, "Duplicate option names for " + option + " and " + conflict, option.field);
+                    ok = false;
+                }
+            }
+        }
+
+        if (ok) {
+            for (OptionsInfo info : map.values()) {
+                createFiles(info);
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options.test/src/com/oracle/graal/options/test/NestedBooleanOptionValueTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+/**
+ * @test
+ * @run junit jdk.vm.ci.options.test.NestedBooleanOptionValueTest
+ */
+
+package com.oracle.graal.options.test;
+
+import static com.oracle.graal.options.test.NestedBooleanOptionValueTest.Options.Master0;
+import static com.oracle.graal.options.test.NestedBooleanOptionValueTest.Options.Master1;
+import static com.oracle.graal.options.test.NestedBooleanOptionValueTest.Options.Master2;
+import static com.oracle.graal.options.test.NestedBooleanOptionValueTest.Options.NestedOption0;
+import static com.oracle.graal.options.test.NestedBooleanOptionValueTest.Options.NestedOption1;
+import static com.oracle.graal.options.test.NestedBooleanOptionValueTest.Options.NestedOption2;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.oracle.graal.options.NestedBooleanOptionValue;
+import com.oracle.graal.options.OptionDescriptor;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
+
+public class NestedBooleanOptionValueTest {
+
+    public static class Options {
+        public static final OptionValue<Boolean> Master0 = new OptionValue<>(true);
+        public static final OptionValue<Boolean> NestedOption0 = new NestedBooleanOptionValue(Master0, true);
+        public static final OptionValue<Boolean> Master1 = new OptionValue<>(true);
+        public static final OptionValue<Boolean> NestedOption1 = new NestedBooleanOptionValue(Master1, true);
+        public static final OptionValue<Boolean> Master2 = new OptionValue<>(true);
+        public static final OptionValue<Boolean> NestedOption2 = new NestedBooleanOptionValue(Master2, false);
+    }
+
+    static final OptionDescriptor master0 = OptionDescriptor.create("Master0", Boolean.class, "", Options.class, "Master0", Master0);
+    static final OptionDescriptor nestedOption0 = OptionDescriptor.create("NestedOption0", Boolean.class, "", Options.class, "NestedOption0", NestedOption0);
+    static final OptionDescriptor master1 = OptionDescriptor.create("Master1", Boolean.class, "", Options.class, "Master1", Master1);
+    static final OptionDescriptor nestedOption1 = OptionDescriptor.create("NestedOption1", Boolean.class, "", Options.class, "NestedOption1", NestedOption1);
+    static final OptionDescriptor master2 = OptionDescriptor.create("Master2", Boolean.class, "", Options.class, "Master2", Master2);
+    static final OptionDescriptor nestedOption2 = OptionDescriptor.create("NestedOption2", Boolean.class, "", Options.class, "NestedOption2", NestedOption2);
+
+    @SuppressWarnings("try")
+    @Test
+    public void runOverrides() {
+        assertTrue(Master0.getValue());
+        assertTrue(NestedOption0.getValue());
+        try (OverrideScope s1 = OptionValue.override(Master0, false)) {
+            assertFalse(Master0.getValue());
+            assertFalse(NestedOption0.getValue());
+            try (OverrideScope s2 = OptionValue.override(NestedOption0, false)) {
+                assertFalse(NestedOption0.getValue());
+            }
+            try (OverrideScope s2 = OptionValue.override(NestedOption0, true)) {
+                assertTrue(NestedOption0.getValue());
+            }
+        }
+        assertTrue(Master0.getValue());
+        try (OverrideScope s1 = OptionValue.override(NestedOption0, false)) {
+            assertFalse(NestedOption0.getValue());
+        }
+        try (OverrideScope s1 = OptionValue.override(NestedOption0, true)) {
+            assertTrue(NestedOption0.getValue());
+        }
+    }
+
+    @Test
+    public void runDefaultTrue() {
+        Master1.setValue(true);
+        assertTrue(Master1.getValue());
+        assertTrue(NestedOption1.getValue());
+        // nested value unset
+        Master1.setValue(false);
+        assertFalse(Master1.getValue());
+        assertFalse(NestedOption1.getValue());
+        // set false
+        Master1.setValue(false);
+        NestedOption1.setValue(false);
+        assertFalse(Master1.getValue());
+        assertFalse(NestedOption1.getValue());
+        Master1.setValue(true);
+        assertTrue(Master1.getValue());
+        assertFalse(NestedOption1.getValue());
+        // set true
+        Master1.setValue(false);
+        NestedOption1.setValue(true);
+        assertFalse(Master1.getValue());
+        assertTrue(NestedOption1.getValue());
+        Master1.setValue(true);
+        assertTrue(Master1.getValue());
+        assertTrue(NestedOption1.getValue());
+    }
+
+    @Test
+    public void runDefaultFalse() {
+        Master2.setValue(true);
+        assertTrue(Master2.getValue());
+        assertFalse(NestedOption2.getValue());
+        // nested value unset
+        Master2.setValue(false);
+        assertFalse(Master2.getValue());
+        assertFalse(NestedOption2.getValue());
+        // set false
+        Master2.setValue(false);
+        NestedOption2.setValue(false);
+        assertFalse(Master2.getValue());
+        assertFalse(NestedOption2.getValue());
+        Master2.setValue(true);
+        assertTrue(Master2.getValue());
+        assertFalse(NestedOption2.getValue());
+        // set true
+        Master2.setValue(false);
+        NestedOption2.setValue(true);
+        assertFalse(Master2.getValue());
+        assertTrue(NestedOption2.getValue());
+        Master2.setValue(true);
+        assertTrue(Master2.getValue());
+        assertTrue(NestedOption2.getValue());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options.test/src/com/oracle/graal/options/test/TestOptionValue.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+/**
+ * @test
+ * @run junit com.oracle.graal.options.test.TestOptionValue
+ */
+
+package com.oracle.graal.options.test;
+
+import static com.oracle.graal.options.test.TestOptionValue.Options.Mutable;
+import static com.oracle.graal.options.test.TestOptionValue.Options.SecondMutable;
+import static com.oracle.graal.options.test.TestOptionValue.Options.Stable;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+
+import com.oracle.graal.options.OptionDescriptor;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.StableOptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
+
+@SuppressWarnings("try")
+public class TestOptionValue {
+
+    public static class Options {
+        public static final OptionValue<Boolean> Stable = new StableOptionValue<>(true);
+        public static final OptionValue<String> Mutable = new OptionValue<>("original");
+        public static final OptionValue<String> SecondMutable = new OptionValue<>("second");
+    }
+
+    static final OptionDescriptor stable = OptionDescriptor.create("Stable", Boolean.class, "", Options.class, "Stable", Stable);
+    static final OptionDescriptor mutable = OptionDescriptor.create("Mutable", String.class, "", Options.class, "Mutable", Mutable);
+    static final OptionDescriptor secondMutable = OptionDescriptor.create("SecondMutable", String.class, "", Options.class, "SecondMutable", SecondMutable);
+
+    @Test
+    public void testMutable() {
+        assertEquals("original", Mutable.getValue());
+        try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
+            assertEquals("override1", Mutable.getValue());
+            try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
+                assertEquals("override2", Mutable.getValue());
+            }
+            assertEquals("override1", Mutable.getValue());
+            try (OverrideScope s3 = OptionValue.override(Mutable, "override3")) {
+                assertEquals("override3", Mutable.getValue());
+            }
+            assertEquals("override1", Mutable.getValue());
+        }
+        assertEquals("original", Mutable.getValue());
+        try (OverrideScope s1 = OptionValue.override(Mutable, "original")) {
+            assertEquals("original", Mutable.getValue());
+        }
+    }
+
+    @Test
+    public void testMultiple() {
+        assertEquals("original", Mutable.getValue());
+        assertEquals("second", SecondMutable.getValue());
+        try (OverrideScope s1 = OptionValue.override(Mutable, "override1", SecondMutable, "secondOverride1")) {
+            assertEquals("override1", Mutable.getValue());
+            assertEquals("secondOverride1", SecondMutable.getValue());
+            try (OverrideScope s2 = OptionValue.override(Mutable, "override2", SecondMutable, "secondOverride2")) {
+                assertEquals("override2", Mutable.getValue());
+                assertEquals("secondOverride2", SecondMutable.getValue());
+            }
+            assertEquals("override1", Mutable.getValue());
+            assertEquals("secondOverride1", SecondMutable.getValue());
+            try (OverrideScope s3 = OptionValue.override(Mutable, "override3", SecondMutable, "secondOverride3")) {
+                assertEquals("override3", Mutable.getValue());
+                assertEquals("secondOverride3", SecondMutable.getValue());
+            }
+            assertEquals("override1", Mutable.getValue());
+            assertEquals("secondOverride1", SecondMutable.getValue());
+        }
+        assertEquals("original", Mutable.getValue());
+        assertEquals("second", SecondMutable.getValue());
+        try (OverrideScope s1 = OptionValue.override(Mutable, "original", SecondMutable, "second")) {
+            assertEquals("original", Mutable.getValue());
+            assertEquals("second", SecondMutable.getValue());
+        }
+    }
+
+    @Test
+    public void testStable() {
+        assertTrue(Stable.getValue());
+        try (OverrideScope s = OptionValue.override(Stable, false)) {
+            fail("cannot override stable option");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void toStringTest() {
+        assertEquals("com.oracle.graal.options.test.TestOptionValue$Options.Mutable=original", Mutable.toString());
+        try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
+            assertEquals("com.oracle.graal.options.test.TestOptionValue$Options.Mutable=override1", Mutable.toString());
+            try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
+                assertEquals("com.oracle.graal.options.test.TestOptionValue$Options.Mutable=override2", Mutable.toString());
+            }
+        }
+    }
+
+    @Test
+    public void getValuesTest() {
+        assertEquals(Arrays.asList("original"), Mutable.getValues(null));
+        assertEquals(Arrays.asList(true), Stable.getValues(null));
+        try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
+            assertEquals(Arrays.asList("override1", "original"), Mutable.getValues(null));
+            try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
+                assertEquals(Arrays.asList("override2", "override1", "original"), Mutable.getValues(null));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,59 @@
+/*
+ * 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.io.Serializable;
+import java.util.function.Supplier;
+
+import com.oracle.graal.options.OptionValue.OverrideScope;
+
+/**
+ * A cached value that needs to be recomputed when an option changes.
+ */
+public class DerivedOptionValue<T> {
+
+    public interface OptionSupplier<T> extends Supplier<T>, Serializable {
+    }
+
+    private final T initialValue;
+    private final OptionSupplier<T> supplier;
+
+    public DerivedOptionValue(OptionSupplier<T> supplier) {
+        this.supplier = supplier;
+        assert OptionValue.getOverrideScope() == null : "derived option value should be initialized outside any override scope";
+        this.initialValue = createValue();
+    }
+
+    public T getValue() {
+        OverrideScope overrideScope = OptionValue.getOverrideScope();
+        if (overrideScope != null) {
+            return overrideScope.getDerived(this);
+        } else {
+            return initialValue;
+        }
+    }
+
+    T createValue() {
+        return supplier.get();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/GraalJarsOptionDescriptorsProvider.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,129 @@
+/*
+ * 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.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+import com.oracle.graal.options.OptionsParser.OptionDescriptorsProvider;
+
+/**
+ * Access to the {@link OptionDescriptors} declared by
+ * {@code META-INF/services/com.oracle.graal.options.OptionDescriptors} files in
+ * {@code <jre>/lib/jvmci/*.jar}.
+ */
+public final class GraalJarsOptionDescriptorsProvider implements OptionDescriptorsProvider {
+
+    static final String OptionDescriptorsServiceFile = "META-INF/services/" + OptionDescriptors.class.getName();
+
+    private final Iterator<File> jars;
+    private final List<OptionDescriptors> optionsDescriptorsList;
+
+    /**
+     * Creates a {@link GraalJarsOptionDescriptorsProvider} if at least one JVMCI jar is available
+     * otherwise returns null.
+     */
+    public static GraalJarsOptionDescriptorsProvider create() {
+        List<File> jarsList = findJVMCIJars();
+        if (jarsList.isEmpty()) {
+            return null;
+        }
+        return new GraalJarsOptionDescriptorsProvider(jarsList);
+    }
+
+    private GraalJarsOptionDescriptorsProvider(List<File> jarsList) {
+        this.jars = jarsList.iterator();
+        this.optionsDescriptorsList = new ArrayList<>(jarsList.size() * 3);
+    }
+
+    /**
+     * Finds the list of JVMCI jars.
+     */
+    private static List<File> findJVMCIJars() {
+        File javaHome = new File(System.getProperty("java.home"));
+        File lib = new File(javaHome, "lib");
+        File jvmci = new File(lib, "jvmci");
+        if (!jvmci.exists()) {
+            return Collections.emptyList();
+        }
+
+        List<File> jarFiles = new ArrayList<>();
+        for (String fileName : jvmci.list()) {
+            if (fileName.endsWith(".jar")) {
+                File file = new File(jvmci, fileName);
+                if (file.isDirectory()) {
+                    continue;
+                }
+                jarFiles.add(file);
+            }
+        }
+        return jarFiles;
+    }
+
+    public OptionDescriptor get(String name) {
+        // Look up loaded option descriptors first
+        for (OptionDescriptors optionDescriptors : optionsDescriptorsList) {
+            OptionDescriptor desc = optionDescriptors.get(name);
+            if (desc != null) {
+                return desc;
+            }
+        }
+        while (jars.hasNext()) {
+            File path = jars.next();
+            try (JarFile jar = new JarFile(path)) {
+                ZipEntry entry = jar.getEntry(OptionDescriptorsServiceFile);
+                if (entry != null) {
+                    BufferedReader br = new BufferedReader(new InputStreamReader(jar.getInputStream(entry)));
+                    String line = null;
+                    OptionDescriptor desc = null;
+                    while ((line = br.readLine()) != null) {
+                        OptionDescriptors options;
+                        try {
+                            options = (OptionDescriptors) Class.forName(line).newInstance();
+                            optionsDescriptorsList.add(options);
+                            if (desc == null) {
+                                desc = options.get(name);
+                            }
+                        } catch (Exception e) {
+                            throw new InternalError("Error instantiating class " + line + " read from " + path, e);
+                        }
+                    }
+                    if (desc != null) {
+                        return desc;
+                    }
+                }
+            } catch (IOException e) {
+                throw new InternalError("Error reading " + path, e);
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/NestedBooleanOptionValue.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,58 @@
+/*
+ * 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.options;
+
+/**
+ * A nested Boolean {@link OptionValue} that can be overridden by a {@link #masterOption master
+ * option}.
+ * <p>
+ * <li>If the option is present on the command line the specified value is used.
+ * <li>Otherwise {@link #getValue()} depends on the {@link #masterOption} and evaluates as follows:
+ * <ul>
+ * <li>If {@link #masterOption} is set, this value equals to {@link #initialValue}.
+ * <li>Otherwise, if {@link #masterOption} is {@code false}, this option is {@code false}.
+ */
+public class NestedBooleanOptionValue extends OptionValue<Boolean> {
+    private final OptionValue<Boolean> masterOption;
+    private final Boolean initialValue;
+
+    public NestedBooleanOptionValue(OptionValue<Boolean> masterOption, Boolean initialValue) {
+        super(null);
+        this.masterOption = masterOption;
+        this.initialValue = initialValue;
+    }
+
+    public OptionValue<Boolean> getMasterOption() {
+        return masterOption;
+    }
+
+    @Override
+    public Boolean getValue() {
+        Boolean v = super.getValue();
+        if (v == null) {
+            return initialValue && masterOption.getValue();
+        }
+        return v;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/Option.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Describes the attributes of an option whose {@link OptionValue value} is in a static field
+ * annotated by this annotation type.
+ *
+ * @see OptionDescriptor
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.FIELD)
+public @interface Option {
+
+    /**
+     * Gets a help message for the option. New lines can be embedded in the message with
+     * {@code "%n"}.
+     */
+    String help();
+
+    /**
+     * The name of the option. By default, the name of the annotated field should be used.
+     */
+    String name() default "";
+
+    /**
+     * Specifies the type of the option.
+     */
+    OptionType type() default OptionType.Debug;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+/**
+ * Describes the attributes of a static field {@linkplain Option option} and provides access to its
+ * {@linkplain OptionValue value}.
+ */
+public final class OptionDescriptor {
+
+    protected final String name;
+    protected final Class<?> type;
+    protected final String help;
+    protected final OptionValue<?> option;
+    protected final Class<?> declaringClass;
+    protected final String fieldName;
+
+    public static OptionDescriptor create(String name, Class<?> type, String help, Class<?> declaringClass, String fieldName, OptionValue<?> option) {
+        OptionDescriptor result = option.getDescriptor();
+        if (result == null) {
+            result = new OptionDescriptor(name, type, help, declaringClass, fieldName, option);
+            option.setDescriptor(result);
+        }
+        assert result.name.equals(name) && result.type == type && result.declaringClass == declaringClass && result.fieldName.equals(fieldName) && result.option == option;
+        return result;
+    }
+
+    private OptionDescriptor(String name, Class<?> type, String help, Class<?> declaringClass, String fieldName, OptionValue<?> option) {
+        this.name = name;
+        this.type = type;
+        this.help = help;
+        this.option = option;
+        this.declaringClass = declaringClass;
+        this.fieldName = fieldName;
+        assert !type.isPrimitive() : "must used boxed type instead of " + type;
+    }
+
+    /**
+     * Gets the type of values stored in the option. This will be the boxed type for a primitive
+     * option.
+     */
+    public Class<?> getType() {
+        return type;
+    }
+
+    /**
+     * Gets a descriptive help message for the option.
+     */
+    public String getHelp() {
+        return help;
+    }
+
+    /**
+     * Gets the name of the option. It's up to the client of this object how to use the name to get
+     * a user specified value for the option from the environment.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the boxed option value.
+     */
+    public OptionValue<?> getOptionValue() {
+        return option;
+    }
+
+    public Class<?> getDeclaringClass() {
+        return declaringClass;
+    }
+
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Gets a description of the location where this option is stored.
+     */
+    public String getLocation() {
+        return getDeclaringClass().getName() + "." + getFieldName();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptors.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+/**
+ * An interface to a set of {@link OptionDescriptor}s.
+ */
+public interface OptionDescriptors extends Iterable<OptionDescriptor> {
+    /**
+     * Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option
+     * descriptor set doesn't contain a matching option.
+     */
+    OptionDescriptor get(String value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionType.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+/**
+ * Classifies JVMCI options in several categories depending on who this option is relevant for.
+ *
+ */
+public enum OptionType {
+    /**
+     * An option common for users to apply.
+     */
+    User,
+
+    /**
+     * An option only relevant in corner cases and for fine-tuning.
+     */
+    Expert,
+
+    /**
+     * An option only relevant when debugging the compiler.
+     */
+    Debug
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+
+/**
+ * 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
+     * object returned by this method.
+     * <p>
+     * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
+     * used:
+     *
+     * <pre>
+     * try (OverrideScope s = OptionValue.override(myOption, myValue) {
+     *     // code that depends on myOption == myValue
+     * }
+     * </pre>
+     */
+    public static OverrideScope override(OptionValue<?> option, Object value) {
+        OverrideScope current = getOverrideScope();
+        if (current == null) {
+            if (!value.equals(option.getValue())) {
+                return new SingleOverrideScope(option, value);
+            }
+            Map<OptionValue<?>, Object> overrides = Collections.emptyMap();
+            return new MultipleOverridesScope(current, overrides);
+        }
+        return new MultipleOverridesScope(current, option, value);
+    }
+
+    /**
+     * Temporarily changes the values for a set of options. The {@linkplain OptionValue#getValue()
+     * value} of each {@code option} in {@code overrides} is set to the corresponding {@code value}
+     * in {@code overrides} until {@link OverrideScope#close()} is called on the object returned by
+     * this method.
+     * <p>
+     * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
+     * used:
+     *
+     * <pre>
+     * Map&lt;OptionValue, Object&gt; overrides = new HashMap&lt;&gt;();
+     * overrides.put(myOption1, myValue1);
+     * overrides.put(myOption2, myValue2);
+     * try (OverrideScope s = OptionValue.override(overrides) {
+     *     // code that depends on myOption == myValue
+     * }
+     * </pre>
+     */
+    public static OverrideScope override(Map<OptionValue<?>, Object> overrides) {
+        OverrideScope current = getOverrideScope();
+        if (current == null && overrides.size() == 1) {
+            Entry<OptionValue<?>, Object> single = overrides.entrySet().iterator().next();
+            OptionValue<?> option = single.getKey();
+            Object overrideValue = single.getValue();
+            if (!overrideValue.equals(option.getValue())) {
+                return new SingleOverrideScope(option, overrideValue);
+            }
+        }
+        return new MultipleOverridesScope(current, overrides);
+    }
+
+    /**
+     * Temporarily changes the values for a set of options. The {@linkplain OptionValue#getValue()
+     * value} of each {@code option} in {@code overrides} is set to the corresponding {@code value}
+     * in {@code overrides} until {@link OverrideScope#close()} is called on the object returned by
+     * this method.
+     * <p>
+     * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
+     * used:
+     *
+     * <pre>
+     * try (OverrideScope s = OptionValue.override(myOption1, myValue1, myOption2, myValue2) {
+     *     // code that depends on myOption == myValue
+     * }
+     * </pre>
+     *
+     * @param overrides overrides in the form {@code [option1, override1, option2, override2, ...]}
+     */
+    public static OverrideScope override(Object... overrides) {
+        OverrideScope current = getOverrideScope();
+        if (current == null && overrides.length == 2) {
+            OptionValue<?> option = (OptionValue<?>) overrides[0];
+            Object overrideValue = overrides[1];
+            if (!overrideValue.equals(option.getValue())) {
+                return new SingleOverrideScope(option, overrideValue);
+            }
+        }
+        Map<OptionValue<?>, Object> map = Collections.emptyMap();
+        for (int i = 0; i < overrides.length; i += 2) {
+            OptionValue<?> option = (OptionValue<?>) overrides[i];
+            Object overrideValue = overrides[i + 1];
+            if (!overrideValue.equals(option.getValue())) {
+                if (map.isEmpty()) {
+                    map = new HashMap<>();
+                }
+                map.put(option, overrideValue);
+            }
+        }
+        return new MultipleOverridesScope(current, map);
+    }
+
+    private static final ThreadLocal<OverrideScope> overrideScopeTL = new ThreadLocal<>();
+
+    protected static OverrideScope getOverrideScope() {
+        return overrideScopeTL.get();
+    }
+
+    protected static void setOverrideScope(OverrideScope overrideScope) {
+        overrideScopeTL.set(overrideScope);
+    }
+
+    private T defaultValue;
+
+    /**
+     * The raw option value.
+     */
+    protected T value;
+
+    private OptionDescriptor descriptor;
+
+    private long reads;
+    private OptionValue<?> next;
+    private static OptionValue<?> head;
+
+    private static final boolean ShowReadsHistogram = Boolean.getBoolean("jvmci.showOptionValueReadsHistogram");
+
+    private static void addToHistogram(OptionValue<?> option) {
+        if (ShowReadsHistogram) {
+            synchronized (OptionValue.class) {
+                option.next = head;
+                head = option;
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public OptionValue(T value) {
+        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 #defaultValue() lazily}.
+     */
+    @SuppressWarnings("unchecked")
+    protected OptionValue() {
+        this.defaultValue = (T) UNINITIALIZED;
+        this.value = (T) DEFAULT;
+        addToHistogram(this);
+    }
+
+    /**
+     * Lazy initialization of default value.
+     */
+    protected T defaultValue() {
+        throw new InternalError("Option without a default value value must override defaultValue()");
+    }
+
+    /**
+     * Sets the descriptor for this option.
+     */
+    public void setDescriptor(OptionDescriptor descriptor) {
+        assert this.descriptor == null : "Overwriting existing descriptor";
+        this.descriptor = descriptor;
+    }
+
+    /**
+     * Returns the descriptor for this option, if it has been set by
+     * {@link #setDescriptor(OptionDescriptor)}.
+     */
+    public OptionDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    /**
+     * Gets the name of this option. The name for an option value with a null
+     * {@linkplain #setDescriptor(OptionDescriptor) descriptor} is the value of
+     * {@link Object#toString()}.
+     */
+    public String getName() {
+        return descriptor == null ? super.toString() : (descriptor.getDeclaringClass().getName() + "." + descriptor.getName());
+    }
+
+    @Override
+    public String toString() {
+        return getName() + "=" + getValue();
+    }
+
+    /**
+     * The initial value specified in source code. The returned value is not affected by calls to
+     * {@link #setValue(Object)} or registering {@link OverrideScope}s. Therefore, it is also not
+     * affected by options set on the command line.
+     */
+    public T getDefaultValue() {
+        if (defaultValue == UNINITIALIZED) {
+            defaultValue = defaultValue();
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Returns true if the option has the same value that was set in the source code.
+     */
+    public boolean hasDefaultValue() {
+        if (!(this instanceof StableOptionValue)) {
+            getValue(); // ensure initialized
+        }
+        return value == DEFAULT || Objects.equals(value, getDefaultValue());
+    }
+
+    /**
+     * Gets the value of this option.
+     */
+    public T getValue() {
+        if (ShowReadsHistogram) {
+            reads++;
+        }
+        if (!(this instanceof StableOptionValue)) {
+            OverrideScope overrideScope = getOverrideScope();
+            if (overrideScope != null) {
+                T override = overrideScope.getOverride(this);
+                if (override != null) {
+                    return override;
+                }
+            }
+        }
+        if (value != DEFAULT) {
+            return value;
+        } else {
+            return getDefaultValue();
+        }
+    }
+
+    /**
+     * Gets the values of this option including overridden values.
+     *
+     * @param c the collection to which the values are added. If null, one is allocated.
+     * @return the collection to which the values were added in order from most overridden to
+     *         current value
+     */
+    @SuppressWarnings("unchecked")
+    public Collection<T> getValues(Collection<T> c) {
+        Collection<T> values = c == null ? new ArrayList<>() : c;
+        if (!(this instanceof StableOptionValue)) {
+            OverrideScope overrideScope = getOverrideScope();
+            if (overrideScope != null) {
+                overrideScope.getOverrides(this, (Collection<Object>) values);
+            }
+        }
+        if (value != DEFAULT) {
+            values.add(value);
+        } else {
+            values.add(getDefaultValue());
+        }
+        return values;
+    }
+
+    /**
+     * Sets the value of this option.
+     */
+    @SuppressWarnings("unchecked")
+    public void setValue(Object v) {
+        this.value = (T) v;
+    }
+
+    /**
+     * An object whose {@link #close()} method reverts the option value overriding initiated by
+     * {@link OptionValue#override(OptionValue, Object)} or {@link OptionValue#override(Map)}.
+     */
+    public abstract static class OverrideScope implements AutoCloseable {
+
+        private Map<DerivedOptionValue<?>, Object> derivedCache = null;
+
+        public <T> T getDerived(DerivedOptionValue<T> key) {
+            if (derivedCache == null) {
+                derivedCache = new HashMap<>();
+            }
+            @SuppressWarnings("unchecked")
+            T ret = (T) derivedCache.get(key);
+            if (ret == null) {
+                ret = key.createValue();
+                derivedCache.put(key, ret);
+            }
+            return ret;
+        }
+
+        abstract void addToInherited(Map<OptionValue<?>, Object> inherited);
+
+        abstract <T> T getOverride(OptionValue<T> option);
+
+        abstract void getOverrides(OptionValue<?> option, Collection<Object> c);
+
+        public abstract void close();
+    }
+
+    static class SingleOverrideScope extends OverrideScope {
+
+        private final OptionValue<?> option;
+        private final Object value;
+
+        public SingleOverrideScope(OptionValue<?> option, Object value) {
+            if (option instanceof StableOptionValue) {
+                throw new IllegalArgumentException("Cannot override stable option " + option);
+            }
+            this.option = option;
+            this.value = value;
+            setOverrideScope(this);
+        }
+
+        @Override
+        void addToInherited(Map<OptionValue<?>, Object> inherited) {
+            inherited.put(option, value);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        <T> T getOverride(OptionValue<T> key) {
+            if (key == this.option) {
+                return (T) value;
+            }
+            return null;
+        }
+
+        @Override
+        void getOverrides(OptionValue<?> key, Collection<Object> c) {
+            if (key == this.option) {
+                c.add(value);
+            }
+        }
+
+        @Override
+        public void close() {
+            setOverrideScope(null);
+        }
+    }
+
+    static class MultipleOverridesScope extends OverrideScope {
+        final OverrideScope parent;
+        final Map<OptionValue<?>, Object> overrides;
+
+        public MultipleOverridesScope(OverrideScope parent, OptionValue<?> option, Object value) {
+            this.parent = parent;
+            this.overrides = new HashMap<>();
+            if (parent != null) {
+                parent.addToInherited(overrides);
+            }
+            if (option instanceof StableOptionValue) {
+                throw new IllegalArgumentException("Cannot override stable option " + option);
+            }
+            if (!value.equals(option.getValue())) {
+                this.overrides.put(option, value);
+            }
+            if (!overrides.isEmpty()) {
+                setOverrideScope(this);
+            }
+        }
+
+        MultipleOverridesScope(OverrideScope parent, Map<OptionValue<?>, Object> overrides) {
+            this.parent = parent;
+            if (overrides.isEmpty() && parent == null) {
+                this.overrides = Collections.emptyMap();
+                return;
+            }
+            this.overrides = new HashMap<>();
+            if (parent != null) {
+                parent.addToInherited(this.overrides);
+            }
+            for (Map.Entry<OptionValue<?>, Object> e : overrides.entrySet()) {
+                OptionValue<?> option = e.getKey();
+                if (option instanceof StableOptionValue) {
+                    throw new IllegalArgumentException("Cannot override stable option " + option);
+                }
+                if (!e.getValue().equals(option.getValue())) {
+                    this.overrides.put(option, e.getValue());
+                }
+            }
+            if (!this.overrides.isEmpty()) {
+                setOverrideScope(this);
+            }
+        }
+
+        @Override
+        void addToInherited(Map<OptionValue<?>, Object> inherited) {
+            if (parent != null) {
+                parent.addToInherited(inherited);
+            }
+            inherited.putAll(overrides);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        <T> T getOverride(OptionValue<T> option) {
+            return (T) overrides.get(option);
+        }
+
+        @Override
+        void getOverrides(OptionValue<?> option, Collection<Object> c) {
+            Object v = overrides.get(option);
+            if (v != null) {
+                c.add(v);
+            }
+            if (parent != null) {
+                parent.getOverrides(option, c);
+            }
+        }
+
+        @Override
+        public void close() {
+            if (!overrides.isEmpty()) {
+                setOverrideScope(parent);
+            }
+        }
+    }
+
+    static {
+        if (ShowReadsHistogram) {
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                @Override
+                public void run() {
+                    ArrayList<OptionValue<?>> options = new ArrayList<>();
+                    for (OptionValue<?> option = head; option != null; option = option.next) {
+                        options.add(option);
+                    }
+                    Collections.sort(options, new Comparator<OptionValue<?>>() {
+
+                        public int compare(OptionValue<?> o1, OptionValue<?> o2) {
+                            if (o1.reads < o2.reads) {
+                                return -1;
+                            } else if (o1.reads > o2.reads) {
+                                return 1;
+                            } else {
+                                return o1.getName().compareTo(o2.getName());
+                            }
+                        }
+                    });
+                    PrintStream out = System.out;
+                    out.println("=== OptionValue reads histogram ===");
+                    for (OptionValue<?> option : options) {
+                        out.println(option.reads + "\t" + option);
+                    }
+                }
+            });
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsLoader.java	Mon Dec 21 16:19:35 2015 +0100
@@ -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.ServiceLoader;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * 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 (OptionDescriptors opts : ServiceLoader.load(OptionDescriptors.class, OptionsLoader.class.getClassLoader())) {
+            for (OptionDescriptor desc : opts) {
+                String name = desc.getName();
+                OptionDescriptor existing = options.put(name, desc);
+                assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsParser.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,324 @@
+/*
+ * 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.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.SortedMap;
+
+/**
+ * This class contains methods for parsing JVMCI options and matching them against a set of
+ * {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded from JVMCI jars, either
+ * {@linkplain GraalJarsOptionDescriptorsProvider directly} or via a {@link ServiceLoader}.
+ */
+public class OptionsParser {
+
+    private static final OptionValue<Boolean> PrintFlags = new OptionValue<>(false);
+    private static final OptionValue<Boolean> ShowFlags = new OptionValue<>(false);
+
+    /**
+     * A service for looking up {@link OptionDescriptor}s.
+     */
+    public interface OptionDescriptorsProvider {
+        /**
+         * Gets the {@link OptionDescriptor} matching a given option {@linkplain Option#name() name}
+         * or null if no option of that name is provided by this object.
+         */
+        OptionDescriptor get(String name);
+    }
+
+    public interface OptionConsumer {
+        void set(OptionDescriptor desc, Object value);
+    }
+
+    /**
+     * Parses an ordered list of (name, value) pairs assigning values to JVMCI options.
+     *
+     * @param optionSettings JVMCI options as serialized (name, value) pairs
+     * @param setter the object to notify of the parsed option and value
+     * @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s
+     * @param options the options database to use if {@code odp == null}. If
+     *            {@code options == null && odp == null}, {@link OptionsLoader#options} is used.
+     * @throws IllegalArgumentException if there's a problem parsing {@code option}
+     */
+    public static void parseOptions(String[] optionSettings, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
+        if (optionSettings != null && optionSettings.length != 0) {
+            assert optionSettings.length % 2 == 0;
+
+            moveHelpFlagsToTail(optionSettings);
+
+            for (int i = 0; i < optionSettings.length / 2; i++) {
+                String name = optionSettings[i * 2];
+                String value = optionSettings[i * 2 + 1];
+                parseOption(name, value, setter, odp, options);
+            }
+            if (PrintFlags.getValue() || ShowFlags.getValue()) {
+                Set<String> explicitlyAssigned = new HashSet<>(optionSettings.length / 2);
+                for (int i = 0; i < optionSettings.length / 2; i++) {
+                    String name = optionSettings[i * 2];
+                    explicitlyAssigned.add(name);
+                }
+                printFlags(resolveOptions(options), "JVMCI", System.out, explicitlyAssigned);
+                if (PrintFlags.getValue()) {
+                    System.exit(0);
+                }
+            }
+        }
+    }
+
+    /**
+     * Moves all {@code PrintFlags} and {@code ShowFlags} option settings to the back of
+     * {@code optionSettings}. This allows the help message to show which options had their value
+     * explicitly set (even if to their default value).
+     */
+    private static void moveHelpFlagsToTail(String[] optionSettings) {
+        List<String> tail = null;
+        int insert = 0;
+        for (int i = 0; i < optionSettings.length / 2; i++) {
+            String name = optionSettings[i * 2];
+            String value = optionSettings[i * 2 + 1];
+            if (name.equals("ShowFlags") || name.equals("PrintFlags")) {
+                if (tail == null) {
+                    tail = new ArrayList<>(4);
+                    insert = i * 2;
+                }
+                tail.add(name);
+                tail.add(value);
+            } else if (tail != null) {
+                optionSettings[insert++] = name;
+                optionSettings[insert++] = value;
+            }
+        }
+        if (tail != null) {
+            assert tail.size() + insert == optionSettings.length;
+            String[] tailArr = tail.toArray(new String[tail.size()]);
+            System.arraycopy(tailArr, 0, optionSettings, insert, tailArr.length);
+        }
+    }
+
+    /**
+     * Parses a given option setting string to a list of (name, value) pairs.
+     *
+     * @param optionSetting a string matching the pattern {@code <name>=<value>}
+     */
+    public static void parseOptionSettingTo(String optionSetting, List<String> dst) {
+        int eqIndex = optionSetting.indexOf('=');
+        if (eqIndex == -1) {
+            throw new InternalError("Option setting has does not match the pattern <name>=<value>: " + optionSetting);
+        }
+        dst.add(optionSetting.substring(0, eqIndex));
+        dst.add(optionSetting.substring(eqIndex + 1));
+    }
+
+    /**
+     * Resolves {@code options} to a non-null value. This ensures {@link OptionsLoader#options} is
+     * only loaded if necessary.
+     */
+    private static SortedMap<String, OptionDescriptor> resolveOptions(SortedMap<String, OptionDescriptor> options) {
+        return options != null ? options : OptionsLoader.options;
+    }
+
+    /**
+     * Parses a given option name and value.
+     *
+     * @param name the option name
+     * @param valueString the option value as a string
+     * @param setter the object to notify of the parsed option and value
+     * @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s
+     * @param options the options database to use if {@code odp == null}. If
+     *            {@code options == null && odp == null}, {@link OptionsLoader#options} is used.
+     * @throws IllegalArgumentException if there's a problem parsing {@code option}
+     */
+    private static void parseOption(String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
+
+        OptionDescriptor desc = odp != null ? odp.get(name) : resolveOptions(options).get(name);
+        if (desc == null) {
+            if (name.equals("PrintFlags")) {
+                desc = OptionDescriptor.create("PrintFlags", Boolean.class, "Prints all JVMCI flags and exits", OptionsParser.class, "PrintFlags", PrintFlags);
+            } else if (name.equals("ShowFlags")) {
+                desc = OptionDescriptor.create("ShowFlags", Boolean.class, "Prints all JVMCI flags and continues", OptionsParser.class, "ShowFlags", ShowFlags);
+            }
+        }
+        if (desc == null) {
+            List<OptionDescriptor> matches = fuzzyMatch(resolveOptions(options), name);
+            Formatter msg = new Formatter();
+            msg.format("Could not find option %s", name);
+            if (!matches.isEmpty()) {
+                msg.format("%nDid you mean one of the following?");
+                for (OptionDescriptor match : matches) {
+                    msg.format("%n    %s=<value>", match.getName());
+                }
+            }
+            throw new IllegalArgumentException(msg.toString());
+        }
+
+        Class<?> optionType = desc.getType();
+        Object value;
+        if (optionType == Boolean.class) {
+            if ("true".equals(valueString)) {
+                value = Boolean.TRUE;
+            } else if ("false".equals(valueString)) {
+                value = Boolean.FALSE;
+            } else {
+                throw new IllegalArgumentException("Boolean option '" + name + "' must have value \"true\" or \"false\", not \"" + valueString + "\"");
+            }
+        } else if (optionType == Float.class) {
+            value = Float.parseFloat(valueString);
+        } else if (optionType == Double.class) {
+            value = Double.parseDouble(valueString);
+        } else if (optionType == Integer.class) {
+            value = Integer.valueOf((int) parseLong(valueString));
+        } else if (optionType == Long.class) {
+            value = Long.valueOf(parseLong(valueString));
+        } else if (optionType == String.class) {
+            value = valueString;
+        } else {
+            throw new IllegalArgumentException("Wrong value for option '" + name + "'");
+        }
+        if (setter == null) {
+            desc.getOptionValue().setValue(value);
+        } else {
+            setter.set(desc, value);
+        }
+    }
+
+    private static long parseLong(String v) {
+        String valueString = v.toLowerCase();
+        long scale = 1;
+        if (valueString.endsWith("k")) {
+            scale = 1024L;
+        } else if (valueString.endsWith("m")) {
+            scale = 1024L * 1024L;
+        } else if (valueString.endsWith("g")) {
+            scale = 1024L * 1024L * 1024L;
+        } else if (valueString.endsWith("t")) {
+            scale = 1024L * 1024L * 1024L * 1024L;
+        }
+
+        if (scale != 1) {
+            /* Remove trailing scale character. */
+            valueString = valueString.substring(0, valueString.length() - 1);
+        }
+
+        return Long.parseLong(valueString) * scale;
+    }
+
+    /**
+     * Wraps some given text to one or more lines of a given maximum width.
+     *
+     * @param text text to wrap
+     * @param width maximum width of an output line, exception for words in {@code text} longer than
+     *            this value
+     * @return {@code text} broken into lines
+     */
+    private static List<String> wrap(String text, int width) {
+        List<String> lines = Collections.singletonList(text);
+        if (text.length() > width) {
+            String[] chunks = text.split("\\s+");
+            lines = new ArrayList<>();
+            StringBuilder line = new StringBuilder();
+            for (String chunk : chunks) {
+                if (line.length() + chunk.length() > width) {
+                    lines.add(line.toString());
+                    line.setLength(0);
+                }
+                if (line.length() != 0) {
+                    line.append(' ');
+                }
+                String[] embeddedLines = chunk.split("%n", -2);
+                if (embeddedLines.length == 1) {
+                    line.append(chunk);
+                } else {
+                    for (int i = 0; i < embeddedLines.length; i++) {
+                        line.append(embeddedLines[i]);
+                        if (i < embeddedLines.length - 1) {
+                            lines.add(line.toString());
+                            line.setLength(0);
+                        }
+                    }
+                }
+            }
+            if (line.length() != 0) {
+                lines.add(line.toString());
+            }
+        }
+        return lines;
+    }
+
+    private static void printFlags(SortedMap<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out, Set<String> explicitlyAssigned) {
+        out.println("[List of " + prefix + " options]");
+        for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
+            e.getKey();
+            OptionDescriptor desc = e.getValue();
+            Object value = desc.getOptionValue().getValue();
+            List<String> helpLines = wrap(desc.getHelp(), 70);
+            String name = e.getKey();
+            String assign = explicitlyAssigned.contains(name) ? ":=" : " =";
+            out.printf("%9s %-40s %s %-14s %s%n", desc.getType().getSimpleName(), name, assign, value, helpLines.get(0));
+            for (int i = 1; i < helpLines.size(); i++) {
+                out.printf("%67s %s%n", " ", helpLines.get(i));
+            }
+        }
+    }
+
+    /**
+     * 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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java	Mon Dec 21 16:19:35 2015 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+/**
+ * An option that always returns the same {@linkplain #getValue() value}.
+ */
+public class StableOptionValue<T> extends OptionValue<T> {
+
+    /**
+     * Creates a stable option value.
+     */
+    public StableOptionValue(T value) {
+        super(value);
+    }
+
+    /**
+     * Used to assert the invariant for stability. Without using locks, this check is not safe
+     * against races and so it's only an assertion.
+     */
+    private boolean getValueCalled;
+
+    /**
+     * Creates an uninitialized stable option value for a subclass that initializes itself
+     * {@link #defaultValue() lazily}.
+     */
+    public StableOptionValue() {
+    }
+
+    /**
+     * Gets the value of this option.
+     */
+    @Override
+    public final T getValue() {
+        T result = super.getValue();
+        assert initGetValueCalled();
+        return result;
+    }
+
+    private boolean initGetValueCalled() {
+        getValueCalled = true;
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * This must only be called if {@link #getValue()} has never been called.
+     */
+    @Override
+    public final void setValue(Object v) {
+        assert !getValueCalled;
+        super.setValue(v);
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Mon Dec 21 16:19:35 2015 +0100
@@ -24,16 +24,15 @@
 
 import java.util.function.BiConsumer;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
-
 import com.oracle.graal.debug.Debug;
 import com.oracle.graal.debug.DebugMetric;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.NodeFlood;
 import com.oracle.graal.nodes.AbstractEndNode;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.Phase;
 
 public class DeadCodeEliminationPhase extends Phase {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java	Mon Dec 21 16:19:35 2015 +0100
@@ -24,12 +24,11 @@
 
 import java.util.Map;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
-
 import com.oracle.graal.nodes.Invoke;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.common.AbstractInliningPhase;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.common.inlining.policy.GreedyInliningPolicy;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java	Mon Dec 21 16:19:35 2015 +0100
@@ -27,13 +27,13 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import jdk.vm.ci.common.JVMCIError;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.debug.DebugVerifyHandler;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.common.DeadCodeEliminationPhase;
 
 /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Mon Dec 21 16:19:35 2015 +0100
@@ -44,8 +44,6 @@
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.debug.Debug;
@@ -91,6 +89,8 @@
 import com.oracle.graal.nodes.java.MonitorIdNode;
 import com.oracle.graal.nodes.spi.StampProvider;
 import com.oracle.graal.nodes.util.GraphUtil;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.common.inlining.InliningUtil;
 
 /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Dec 21 16:19:35 2015 +0100
@@ -55,8 +55,6 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.Signature;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
 import sun.misc.Launcher;
 
 import com.oracle.graal.api.replacements.ClassSubstitution;
@@ -92,6 +90,8 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode;
 import com.oracle.graal.nodes.spi.Replacements;
 import com.oracle.graal.nodes.spi.StampProvider;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.common.ConvertDeoptimizeToGuardPhase;
--- a/graal/com.oracle.graal.salver/src/com/oracle/graal/salver/SalverOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.salver/src/com/oracle/graal/salver/SalverOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.salver;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 
 public final class SalverOptions {
 
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntimeAccess.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntimeAccess.java	Mon Dec 21 16:19:35 2015 +0100
@@ -25,8 +25,6 @@
 import java.util.function.Supplier;
 
 import jdk.vm.ci.common.JVMCIError;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionValue;
 import jdk.vm.ci.runtime.JVMCI;
 import jdk.vm.ci.runtime.JVMCICompiler;
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
@@ -36,6 +34,8 @@
 import com.oracle.graal.api.runtime.GraalJVMCICompiler;
 import com.oracle.graal.api.runtime.GraalRuntime;
 import com.oracle.graal.hotspot.HotSpotGraalCompilerFactory;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.truffle.api.TruffleRuntime;
 import com.oracle.truffle.api.TruffleRuntimeAccess;
 
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -24,15 +24,14 @@
 
 import java.util.Random;
 
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.OptionValue.OverrideScope;
-
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionValue.OverrideScope;
 import com.oracle.graal.truffle.PartialEvaluator;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/LazyInitializationTest.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/LazyInitializationTest.java	Mon Dec 21 16:19:35 2015 +0100
@@ -30,15 +30,17 @@
 import java.util.HashSet;
 import java.util.List;
 
-import jdk.vm.ci.options.OptionDescriptor;
-import jdk.vm.ci.options.OptionDescriptors;
-import jdk.vm.ci.options.OptionValue;
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
 
 import org.junit.Assert;
 import org.junit.Test;
 
 import com.oracle.graal.compiler.CompilerThreadFactory;
+import com.oracle.graal.options.OptionDescriptor;
+import com.oracle.graal.options.OptionDescriptors;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.OptionsParser;
+import com.oracle.graal.options.OptionsParser.OptionDescriptorsProvider;
 import com.oracle.graal.test.SubprocessUtil;
 
 /**
@@ -171,11 +173,16 @@
             return true;
         }
 
-        if (OptionDescriptors.class.isAssignableFrom(cls)) {
+        if (OptionDescriptors.class.isAssignableFrom(cls) || OptionDescriptor.class.isAssignableFrom(cls)) {
             // If options are specified, the corresponding *_OptionDescriptors classes are loaded.
             return true;
         }
 
+        if (OptionDescriptorsProvider.class.isAssignableFrom(cls) || cls == OptionsParser.class) {
+            // Classes implementing Graal option loading
+            return true;
+        }
+
         if (OptionValue.class.isAssignableFrom(cls)) {
             // If options are specified, that may implicitly load a custom OptionValue subclass.
             return true;
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGetOptionBuiltin.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGetOptionBuiltin.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,8 +22,7 @@
  */
 package com.oracle.graal.truffle.test.builtins;
 
-import jdk.vm.ci.options.OptionDescriptor;
-
+import com.oracle.graal.options.OptionDescriptor;
 import com.oracle.graal.truffle.TruffleCompilerOptions;
 import com.oracle.graal.truffle.TruffleCompilerOptions_OptionDescriptors;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLSetOptionBuiltin.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLSetOptionBuiltin.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,8 +22,7 @@
  */
 package com.oracle.graal.truffle.test.builtins;
 
-import jdk.vm.ci.options.OptionDescriptor;
-
+import com.oracle.graal.options.OptionDescriptor;
 import com.oracle.graal.truffle.TruffleCompilerOptions;
 import com.oracle.graal.truffle.TruffleCompilerOptions_OptionDescriptors;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Dec 21 16:19:35 2015 +0100
@@ -40,9 +40,6 @@
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
 import jdk.vm.ci.service.Services;
 
 import com.oracle.graal.api.replacements.SnippetReflectionProvider;
@@ -69,6 +66,9 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode;
 import com.oracle.graal.nodes.virtual.VirtualInstanceNode;
 import com.oracle.graal.nodes.virtual.VirtualObjectNode;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.PhaseSuite;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Dec 21 16:19:35 2015 +0100
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.truffle;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
-import jdk.vm.ci.options.StableOptionValue;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
+import com.oracle.graal.options.StableOptionValue;
 
 /**
  * Options for the Truffle compiler.
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Mon Dec 21 00:20:11 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Mon Dec 21 16:19:35 2015 +0100
@@ -27,15 +27,14 @@
 
 import java.util.Set;
 
-import jdk.vm.ci.options.Option;
-import jdk.vm.ci.options.OptionType;
-import jdk.vm.ci.options.OptionValue;
-
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
 import com.oracle.graal.nodes.spi.VirtualizableAllocation;
 import com.oracle.graal.nodes.virtual.VirtualObjectNode;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.BasePhase;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.schedule.SchedulePhase;
--- a/mx.graal/mx_graal_8.py	Mon Dec 21 00:20:11 2015 +0100
+++ b/mx.graal/mx_graal_8.py	Mon Dec 21 16:19:35 2015 +0100
@@ -31,14 +31,16 @@
 import re
 
 import mx
-from mx_jvmci import JvmciJDKDeployedDist, jdkDeployedDists, add_bootclasspath_prepend, buildvms, get_jvmci_jdk, run_vm, VM, relativeVmLibDirInJdk, isJVMCIEnabled
+from mx_jvmci import JvmciJDKDeployedDist, JVMCIArchiveParticipant, jdkDeployedDists, add_bootclasspath_prepend, buildvms, get_jvmci_jdk, VM, relativeVmLibDirInJdk, isJVMCIEnabled
 from mx_jvmci import get_vm as _jvmci_get_vm
+from mx_jvmci import run_vm as _jvmci_run_vm
 from mx_gate import Task
 from sanitycheck import _noneAsEmptyList
 
 from mx_unittest import unittest
 from mx_graal_bench import dacapo
 import mx_gate
+import mx_unittest
 
 _suite = mx.suite('graal')
 
@@ -85,6 +87,7 @@
                 fp.write(os.linesep.join(content))
 
 jdkDeployedDists += [
+    JvmciJDKDeployedDist('GRAAL_OPTIONS'),
     JvmciJDKDeployedDist('GRAAL_NODEINFO'),
     JvmciJDKDeployedDist('GRAAL_API'),
     JvmciJDKDeployedDist('GRAAL_COMPILER'),
@@ -169,7 +172,6 @@
 
     if args.ctwopts:
         # Replace spaces  with '#' since -G: options cannot contain spaces
-        # when they are collated in the "jvmci.options" system property
         vmargs.append('-G:CompileTheWorldConfig=' + re.sub(r'\s+', '#', args.ctwopts))
 
     if args.cp:
@@ -376,12 +378,64 @@
     else:
         print '{:>10}  {}'.format('<missing>', jvmLib)
 
+# Support for -G: options
+def _translateGOption(arg):
+    if arg.startswith('-G:+'):
+        if '=' in arg:
+            mx.abort('Mixing + and = in -G: option specification: ' + arg)
+        arg = '-Dgraal.option.' + arg[len('-G:+'):] + '=true'
+    elif arg.startswith('-G:-'):
+        if '=' in arg:
+            mx.abort('Mixing - and = in -G: option specification: ' + arg)
+        arg = '-Dgraal.option.' + arg[len('-G:+'):] + '=false'
+    elif arg.startswith('-G:'):
+        arg = '-Dgraal.option.' + arg[len('-G:'):]
+    return arg
+
+def run_vm(*positionalargs, **kwargs):
+    """run a Java program by executing the java executable in a Graal JDK"""
+
+    # convert positional args to a list so the first element can be updated
+    positionalargs = list(positionalargs)
+    args = positionalargs[0]
+    if '-G:+PrintFlags' in args and '-Xcomp' not in args:
+        mx.warn('Using -G:+PrintFlags may have no effect without -Xcomp as Graal initialization is lazy')
+    positionalargs[0] = map(_translateGOption, args)
+    return _jvmci_run_vm(*positionalargs, **kwargs)
+
+def _unittest_config_participant(config):
+    vmArgs, mainClass, mainClassArgs = config
+    if isJVMCIEnabled(get_vm()):
+        return (map(_translateGOption, vmArgs), mainClass, mainClassArgs)
+    return config
+
+mx_unittest.add_config_participant(_unittest_config_participant)
+
 mx.update_commands(_suite, {
+    'vm': [run_vm, '[-options] class [args...]'],
     'jdkartifactstats' : [jdkartifactstats, ''],
     'ctw': [ctw, '[-vmoptions|noinline|nocomplex|full]'],
     'microbench' : [microbench, '[VM options] [-- [JMH options]]'],
 })
 
+class GraalArchiveParticipant(JVMCIArchiveParticipant):
+    def __init__(self, dist):
+        JVMCIArchiveParticipant.__init__(self, dist)
+
+    def __add__(self, arcname, contents):
+        if arcname.endswith('_OptionDescriptors.class'):
+            # Need to create service files for the providers of the
+            # com.oracle.graal.options.Options service created by
+            # com.oracle.graal.options.processor.OptionProcessor.
+            provider = arcname[:-len('.class'):].replace('/', '.')
+            self.services.setdefault('com.oracle.graal.options.OptionDescriptors', []).append(provider)
+        return JVMCIArchiveParticipant.__add__(self, arcname, contents)
 
 def mx_post_parse_cmd_line(opts):
     add_bootclasspath_prepend(mx.distribution('truffle:TRUFFLE_API'))
+
+    for jdkDist in jdkDeployedDists:
+        dist = jdkDist.dist()
+        # Replace archive participant for Graal suites
+        if isinstance(jdkDist, JvmciJDKDeployedDist) and dist.suite.name != 'jvmci':
+            dist.set_archiveparticipant(GraalArchiveParticipant(dist))
--- a/mx.graal/mx_graal_9.py	Mon Dec 21 00:20:11 2015 +0100
+++ b/mx.graal/mx_graal_9.py	Mon Dec 21 16:19:35 2015 +0100
@@ -96,6 +96,7 @@
 
 _compilers = ['graal-economy', 'graal']
 _bootClasspathDists = [
+    BootClasspathDist('GRAAL_OPTIONS'),
     BootClasspathDist('GRAAL_NODEINFO'),
     BootClasspathDist('GRAAL_API'),
     BootClasspathDist('GRAAL_COMPILER'),
@@ -182,7 +183,6 @@
 
     if args.ctwopts:
         # Replace spaces  with '#' since -G: options cannot contain spaces
-        # when they are collated in the "jvmci.options" system property
         vmargs.append('-G:CompileTheWorldConfig=' + re.sub(r'\s+', '#', args.ctwopts))
 
     if args.cp:
@@ -322,16 +322,19 @@
         if arg.startswith('-G:+'):
             if '=' in arg:
                 mx.abort('Mixing + and = in -G: option specification: ' + arg)
-            arg = '-Djvmci.option.' + arg[len('-G:+'):] + '=true'
+            arg = '-Dgraal.option.' + arg[len('-G:+'):] + '=true'
         elif arg.startswith('-G:-'):
             if '=' in arg:
                 mx.abort('Mixing - and = in -G: option specification: ' + arg)
-            arg = '-Djvmci.option.' + arg[len('-G:+'):] + '=false'
+            arg = '-Dgraal.option.' + arg[len('-G:+'):] + '=false'
         elif arg.startswith('-G:'):
-            arg = '-Djvmci.option.' + arg[len('-G:'):]
+            arg = '-Dgraal.option.' + arg[len('-G:'):]
         return arg
     args = map(translateGOption, args)
 
+    if '-G:+PrintFlags' in args and '-Xcomp' not in args:
+        mx.warn('Using -G:+PrintFlags may have no effect without -Xcomp as Graal initialization is lazy')
+
     bcp = [mx.distribution('truffle:TRUFFLE_API').classpath_repr()]
     if _jvmciModes[_vm.jvmciMode]:
         bcp.extend([d.get_classpath_repr() for d in _bootClasspathDists])
@@ -400,7 +403,7 @@
             # jdk.vm.ci.options.Options service created by
             # jdk.vm.ci.options.processor.OptionProcessor.
             provider = arcname[:-len('.class'):].replace('/', '.')
-            self.services.setdefault('jdk.vm.ci.options.OptionDescriptors', []).append(provider)
+            self.services.setdefault('com.oracle.graal.options.OptionDescriptors', []).append(provider)
         return False
 
     def __addsrc__(self, arcname, contents):
--- a/mx.graal/suite.py	Mon Dec 21 00:20:11 2015 +0100
+++ b/mx.graal/suite.py	Mon Dec 21 16:19:35 2015 +0100
@@ -39,7 +39,7 @@
             {
                "name" : "jvmci",
                "optional" : "true",
-               "version" : "f4c4cc22a31ccc6efec87a3335047722710cf540",
+               "version" : "a130b51efb072b754f9ecad316dcda01bd2f0e9f",
                "urls" : [
                     {"url" : "http://lafo.ssw.uni-linz.ac.at/hg/graal-jvmci-8", "kind" : "hg"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
@@ -126,16 +126,49 @@
 
     # ------------- Graal -------------
 
+    "com.oracle.graal.options" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "checkstyle" : "com.oracle.graal.graph",
+      "dependencies" : ["jvmci:JVMCI_API"],
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal",
+    },
+
+    "com.oracle.graal.options.processor" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "com.oracle.graal.options",
+      ],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI,Codegen",
+    },
+
+    "com.oracle.graal.options.test" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "com.oracle.graal.options",
+        "mx:JUNIT",
+      ],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "JVMCI",
+    },
+
     "com.oracle.graal.debug" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
       "checkstyle" : "com.oracle.graal.graph",
       "dependencies" : deps([
         "jvmci:JVMCI_API",
+        "com.oracle.graal.options"
       ]),
-      "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]),
+      "annotationProcessors" : deps(["GRAAL_OPTIONS_PROCESSOR"]),
       "javaCompliance" : "1.8",
-      "workingSets" : "JVMCI,Debug",
+      "workingSets" : "Graal,Debug",
     },
 
     "com.oracle.graal.debug.test" : {
@@ -147,7 +180,7 @@
       ],
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
-      "workingSets" : "JVMCI,Debug,Test",
+      "workingSets" : "Graal,Debug,Test",
     },
 
     "com.oracle.graal.code" : {
@@ -237,7 +270,7 @@
         "GRAAL_NODEINFO_PROCESSOR",
         "GRAAL_COMPILER_MATCH_PROCESSOR",
         "GRAAL_REPLACEMENTS_VERIFIER",
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
         "jvmci:JVMCI_SERVICE_PROCESSOR",
       ]),
       "javaCompliance" : "1.8",
@@ -330,7 +363,7 @@
       ],
       "javaCompliance" : "1.8",
       "annotationProcessors" : deps([
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
         "GRAAL_NODEINFO_PROCESSOR"
       ]),
       "workingSets" : "Graal,Graph",
@@ -421,7 +454,7 @@
         "com.oracle.graal.compiler.common",
         "com.oracle.graal.asm",
       ],
-      "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]),
+      "annotationProcessors" : deps(["GRAAL_OPTIONS_PROCESSOR"]),
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,LIR",
@@ -459,7 +492,7 @@
         "com.oracle.graal.lir",
         "com.oracle.graal.asm.amd64",
       ],
-      "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]),
+      "annotationProcessors" : deps(["GRAAL_OPTIONS_PROCESSOR"]),
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,LIR,AMD64",
@@ -499,7 +532,7 @@
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "annotationProcessors" : deps([
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
         "GRAAL_REPLACEMENTS_VERIFIER",
         "GRAAL_NODEINFO_PROCESSOR",
       ]),
@@ -595,7 +628,7 @@
       "subDir" : "graal",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.graal.nodes"],
-      "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]),
+      "annotationProcessors" : deps(["GRAAL_OPTIONS_PROCESSOR"]),
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,Phases",
@@ -607,7 +640,7 @@
       "dependencies" : ["com.oracle.graal.phases"],
       "annotationProcessors" : deps([
         "GRAAL_NODEINFO_PROCESSOR",
-        "jvmci:JVMCI_OPTIONS_PROCESSOR"
+        "GRAAL_OPTIONS_PROCESSOR"
       ]),
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
@@ -632,7 +665,7 @@
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.graal.phases.common"],
       "annotationProcessors" : deps([
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
         "GRAAL_NODEINFO_PROCESSOR"
       ]),
       "checkstyle" : "com.oracle.graal.graph",
@@ -669,7 +702,7 @@
       "subDir" : "graal",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.graal.nodes"],
-      "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]),
+      "annotationProcessors" : deps(["GRAAL_OPTIONS_PROCESSOR"]),
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal",
@@ -682,7 +715,7 @@
 	 "com.oracle.graal.loop",
 	 "com.oracle.graal.phases.common",
        ],
-      "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]),
+      "annotationProcessors" : deps(["GRAAL_OPTIONS_PROCESSOR"]),
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,Phases",
@@ -699,7 +732,7 @@
       "javaCompliance" : "1.8",
       "annotationProcessors" : deps([
         "jvmci:JVMCI_SERVICE_PROCESSOR",
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
       ]),
       "workingSets" : "Graal",
     },
@@ -789,7 +822,7 @@
       "dependencies" : [
         "com.oracle.graal.phases",
       ],
-      "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]),
+      "annotationProcessors" : deps(["GRAAL_OPTIONS_PROCESSOR"]),
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,Java",
@@ -801,7 +834,7 @@
       "dependencies" : [
         "com.oracle.graal.debug",
       ],
-      "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]),
+      "annotationProcessors" : deps(["GRAAL_OPTIONS_PROCESSOR"]),
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,Java",
@@ -816,7 +849,7 @@
         "com.oracle.graal.compiler",
       ],
       "annotationProcessors" : deps([
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
         "jvmci:JVMCI_SERVICE_PROCESSOR"
       ]),
       "checkstyle" : "com.oracle.graal.graph",
@@ -881,7 +914,7 @@
       "annotationProcessors" : deps([
         "GRAAL_NODEINFO_PROCESSOR",
         "GRAAL_REPLACEMENTS_VERIFIER",
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
         "jvmci:JVMCI_SERVICE_PROCESSOR",
         "truffle:TRUFFLE_DSL_PROCESSOR",
       ]),
@@ -919,7 +952,7 @@
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "annotationProcessors" : deps([
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
         "jvmci:JVMCI_SERVICE_PROCESSOR"
       ]),
       "workingSets" : "Graal,Truffle",
@@ -962,7 +995,7 @@
         "com.oracle.graal.java",
       ],
       "annotationProcessors" : deps([
-        "jvmci:JVMCI_OPTIONS_PROCESSOR",
+        "GRAAL_OPTIONS_PROCESSOR",
         "jvmci:JVMCI_SERVICE_PROCESSOR",
       ]),
       "checkstyle" : "com.oracle.graal.graph",
@@ -975,6 +1008,22 @@
 
     # ------------- Distributions -------------
 
+    "GRAAL_OPTIONS" : {
+      "subDir" : "graal",
+      "dependencies" : ["com.oracle.graal.options"],
+      "distDependencies" : deps([
+        "jvmci:JVMCI_API",
+      ]),
+    },
+
+    "GRAAL_OPTIONS_PROCESSOR" : {
+      "subDir" : "graal",
+      "dependencies" : ["com.oracle.graal.options.processor"],
+      "distDependencies" : [
+        "GRAAL_OPTIONS",
+      ],
+    },
+
     "GRAAL_NODEINFO" : {
       "subDir" : "graal",
       "dependencies" : [
@@ -993,6 +1042,7 @@
       "distDependencies" : deps([
         "jvmci:JVMCI_API",
         "GRAAL_NODEINFO",
+        "GRAAL_OPTIONS",
       ]),
     },
 
@@ -1051,6 +1101,7 @@
         "com.oracle.graal.compiler.amd64.test",
         "com.oracle.graal.compiler.sparc.test",
         "com.oracle.graal.hotspot.amd64.test",
+        "com.oracle.graal.options.test",
         "com.oracle.graal.jtt",
         "com.oracle.graal.lir.jtt",
         "com.oracle.graal.lir.test",