changeset 18702:d854f8a5256f

Merge
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Tue, 16 Dec 2014 23:37:35 +0100
parents 28e46ea20c93 08b17b738500
children 41d12b67bc9e
files
diffstat 63 files changed, 1002 insertions(+), 520 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Tue Dec 16 23:37:35 2014 +0100
@@ -313,7 +313,8 @@
         "getLocalVariableTable",
         "isInVirtualMethodTable",
         "toParameterTypes",
-        "getParameterAnnotation"
+        "getParameterAnnotation",
+        "$jacocoInit"
     };
     // @formatter:on
 
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Tue Dec 16 23:37:35 2014 +0100
@@ -847,7 +847,8 @@
         "isJavaLangObject",
         "isMember",
         "getElementalType",
-        "getEnclosingType"
+        "getEnclosingType",
+        "$jacocoInit"
     };
     // @formatter:on
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Tue Dec 16 23:37:35 2014 +0100
@@ -24,6 +24,8 @@
 
 import java.lang.reflect.*;
 
+//JaCoCo Exclude
+
 /**
  * Denotes the basic kinds of types in CRI, including the all the Java primitive types, for example,
  * {@link Kind#Int} for {@code int} and {@link Kind#Object} for all object types. A kind has a
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Tue Dec 16 23:37:35 2014 +0100
@@ -50,8 +50,9 @@
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        AllocatableValue targetAddress = AMD64.rax.asValue();
-        gen.emitMove(targetAddress, operand(callTarget.computedAddress()));
+        Value targetAddressSrc = operand(callTarget.computedAddress());
+        AllocatableValue targetAddress = AMD64.rax.asValue(targetAddressSrc.getLIRKind());
+        gen.emitMove(targetAddress, targetAddressSrc);
         append(new AMD64Call.IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, targetAddress, callState));
     }
 
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Tue Dec 16 23:37:35 2014 +0100
@@ -30,317 +30,317 @@
 // @formatter:off
 public final class GraalOptions {
 
-    @Option(help = "Use experimental baseline compiler configuration.")
+    @Option(help = "Use experimental baseline compiler configuration.", type = OptionType.Debug)
     public static final OptionValue<Boolean> UseBaselineCompiler = new OptionValue<>(false);
 
-    @Option(help = "Use compiler intrinsifications.")
+    @Option(help = "Use compiler intrinsifications.", type = OptionType.Debug)
     public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true);
 
-    @Option(help = "Inline calls with monomorphic type profile.")
+    @Option(help = "Inline calls with monomorphic type profile.", type = OptionType.Expert)
     public static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true);
 
-    @Option(help = "Inline calls with polymorphic type profile.")
+    @Option(help = "Inline calls with polymorphic type profile.", type = OptionType.Expert)
     public static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true);
 
-    @Option(help = "Inline calls with megamorphic type profile (i.e., not all types could be recorded).")
+    @Option(help = "Inline calls with megamorphic type profile (i.e., not all types could be recorded).", type = OptionType.Expert)
     public static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true);
 
-    @Option(help = "Maximum desired size of the compiler graph in nodes.")
+    @Option(help = "Maximum desired size of the compiler graph in nodes.", type = OptionType.User)
     public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(20000);
 
-    @Option(help = "Minimum probability for methods to be inlined for megamorphic type profiles.")
+    @Option(help = "Minimum probability for methods to be inlined for megamorphic type profiles.", type = OptionType.Expert)
     public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D);
 
-    @Option(help = "Maximum level of recursive inlining.")
+    @Option(help = "Maximum level of recursive inlining.", type = OptionType.Expert)
     public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(5);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> IterativeInlining = new OptionValue<>(false);
 
-    @Option(help = "Graphs with less than this number of nodes are trivial and therefore always inlined.")
+    @Option(help = "Graphs with less than this number of nodes are trivial and therefore always inlined.", type = OptionType.Expert)
     public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10);
 
-    @Option(help = "Inlining is explored up to this number of nodes in the graph for each call site.")
+    @Option(help = "Inlining is explored up to this number of nodes in the graph for each call site.", type = OptionType.Expert)
     public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300);
 
-    @Option(help = "If the previous low-level graph size of the method exceeds the threshold, it is not inlined.")
+    @Option(help = "If the previous low-level graph size of the method exceeds the threshold, it is not inlined.", type = OptionType.Expert)
     public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Boolean> InlineEverything = new OptionValue<>(false);
 
     // escape analysis settings
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1);
 
-    // profiling information
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40);
 
-    // graph caching
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Boolean> CacheGraphs = new OptionValue<>(false);
 
-    //loop transform settings TODO (gd) tune
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Integer> FullUnrollMaxNodes = new OptionValue<>(300);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Integer> ExactFullUnrollMaxNodes = new OptionValue<>(1200);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(50);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Integer> LoopUnswitchUncertaintyBoost = new OptionValue<>(5);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true);
 
     // debugging settings
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<String> PrintFilter = new OptionValue<>(null);
 
     // Debug settings:
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> BootstrapReplacements = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Integer> GCDebugStartCycle = new OptionValue<>(-1);
 
+    @Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug)
+    public static final OptionValue<Boolean> VerifyHeapAtReturn = new OptionValue<>(false);
+
     // Ideal graph visualizer output settings
-    @Option(help = "Dump IdealGraphVisualizer output in binary format")
+    @Option(help = "Dump IdealGraphVisualizer output in binary format", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintBinaryGraphs = new OptionValue<>(true);
 
-    @Option(help = "Output probabilities for fixed nodes during binary graph dumping")
+    @Option(help = "Output probabilities for fixed nodes during binary graph dumping", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintGraphProbabilities = new OptionValue<>(false);
 
-    @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.")
+    @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintCFG = new OptionValue<>(false);
 
-    @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.")
+    @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintBackendCFG = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintIdealGraphFile = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<String> PrintIdealGraphAddress = new OptionValue<>("127.0.0.1");
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Integer> PrintIdealGraphPort = new OptionValue<>(4444);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Integer> PrintBinaryGraphPort = new OptionValue<>(4445);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintIdealGraphSchedule = new OptionValue<>(false);
 
     // Other printing settings
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false);
 
-    @Option(help = "Print profiling information when parsing a method's bytecode")
+    @Option(help = "Print profiling information when parsing a method's bytecode", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintCodeBytes = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceEscapeAnalysis = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
 
-    @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required")
+    @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required", type = OptionType.Debug)
     public static final OptionValue<String> DecompileAfterPhase = new OptionValue<>(null);
 
     // HotSpot command line options
-    @Option(help = "Print inlining optimizations")
+    @Option(help = "Print inlining optimizations", type = OptionType.Debug)
     public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false);
 
     // Register allocator debugging
-    @Option(help = "Comma separated list of register that the allocation is limited to.")
+    @Option(help = "Comma separated list of register that the allocation is limited to.", type = OptionType.Debug)
     public static final OptionValue<String> RegisterPressure = new OptionValue<>(null);
 
     // Code generator settings
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> FlowSensitiveReduction = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true);
 
     // Ahead of time compilation
-    @Option(help = "Try to avoid emitting code where patching is required")
+    @Option(help = "Try to avoid emitting code where patching is required", type = OptionType.Expert)
     public static final OptionValue<Boolean> ImmutableCode = new OptionValue<>(false);
 
-    @Option(help = "Generate position independent code")
+    @Option(help = "Generate position independent code", type = OptionType.Expert)
     public static final OptionValue<Boolean> GeneratePIC = new OptionValue<>(false);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Boolean> CallArrayCopy = new OptionValue<>(true);
 
     // Runtime settings
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Boolean> SupportJsrBytecodes = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptDeoptimizationGrouping = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true);
 
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
 
-    @Option(help = "Allow backend to match complex expressions.")
+    @Option(help = "Allow backend to match complex expressions.", type = OptionType.Debug)
     public static final OptionValue<Boolean> MatchExpressions = new OptionValue<>(true);
 
-    @Option(help = "Constant fold final fields with default values.")
+    @Option(help = "Constant fold final fields with default values.", type = OptionType.Debug)
     public static final OptionValue<Boolean> TrustFinalDefaultFields = new OptionValue<>(true);
 
-    @Option(help = "Mark well-known stable fields as such.")
+    @Option(help = "Mark well-known stable fields as such.", type = OptionType.Debug)
     public static final OptionValue<Boolean> ImplicitStableValues = new OptionValue<>(true);
 
 
     /**
      * Counts the various paths taken through snippets.
      */
-    @Option(help = "")
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> SnippetCounters = new OptionValue<>(false);
 }
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java	Tue Dec 16 23:37:35 2014 +0100
@@ -354,6 +354,10 @@
          * Apply the operation to a {@link Stamp}.
          */
         public abstract Stamp foldStamp(Stamp stamp);
+
+        public UnaryOp<T> unwrap() {
+            return this;
+        }
     }
 
     /**
@@ -479,6 +483,10 @@
             return null;
         }
 
+        public BinaryOp<T> unwrap() {
+            return this;
+        }
+
         @Override
         public String toString() {
             if (associative) {
@@ -506,6 +514,11 @@
         public FloatConvert getFloatConvert() {
             return op;
         }
+
+        @Override
+        public FloatConvertOp unwrap() {
+            return this;
+        }
     }
 
     public abstract static class IntegerConvertOp<T> extends Op {
@@ -538,5 +551,9 @@
         public abstract Constant foldConstant(int inputBits, int resultBits, Constant value);
 
         public abstract Stamp foldStamp(int inputBits, int resultBits, Stamp stamp);
+
+        public IntegerConvertOp<T> unwrap() {
+            return this;
+        }
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Dec 16 23:37:35 2014 +0100
@@ -84,13 +84,13 @@
          */
         @Option(help = "Pattern for method(s) to which intrinsification (if available) will be applied. " +
                        "By default, all available intrinsifications are applied except for methods matched " +
-                       "by IntrinsificationsDisabled. See MethodFilter class for pattern syntax.")
+                       "by IntrinsificationsDisabled. See MethodFilter class for pattern syntax.", type = OptionType.Debug)
         public static final OptionValue<String> IntrinsificationsEnabled = new OptionValue<>(null);
         /**
          * @see MethodFilter
          */
         @Option(help = "Pattern for method(s) to which intrinsification will not be applied. " +
-                       "See MethodFilter class for pattern syntax.")
+                       "See MethodFilter class for pattern syntax.", type = OptionType.Debug)
         public static final OptionValue<String> IntrinsificationsDisabled = new OptionValue<>(null);
         // @formatter:on
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Dec 16 23:37:35 2014 +0100
@@ -38,31 +38,31 @@
 public class GraalDebugConfig implements DebugConfig {
 
     // @formatter:off
-    @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)")
+    @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug)
     public static final OptionValue<String> Dump = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) in which metering is enabled (see DebugFilter and Debug.metric)")
+    @Option(help = "Pattern for scope(s) in which metering is enabled (see DebugFilter and Debug.metric)", type = OptionType.Debug)
     public static final OptionValue<String> Meter = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify)")
+    @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify)", type = OptionType.Debug)
     public static final OptionValue<String> Verify = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.metric)")
+    @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.metric)", type = OptionType.Debug)
     public static final OptionValue<String> TrackMemUse = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer)")
+    @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer)", type = OptionType.Debug)
     public static final OptionValue<String> Time = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)")
+    @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug)
     public static final OptionValue<String> Log = new OptionValue<>(null);
-    @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)")
+    @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug)
     public static final OptionValue<String> MethodFilter = new OptionValue<>(null);
     @Option(help = "How to print metric and timing values:%n" +
                    "Name - aggregate by unqualified name%n" +
                    "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" +
                    "Complete - aggregate by qualified name%n" +
-                   "Thread - aggregate by qualified name and thread")
+                   "Thread - aggregate by qualified name and thread", type = OptionType.Debug)
     public static final OptionValue<String> DebugValueSummary = new OptionValue<>("Name");
-    @Option(help = "Omit reporting 0-value metrics")
+    @Option(help = "Omit reporting 0-value metrics", type = OptionType.Debug)
     public static final OptionValue<Boolean> SuppressZeroDebugValues = new OptionValue<>(false);
-    @Option(help = "Send Graal IR to dump handlers on error")
+    @Option(help = "Send Graal IR to dump handlers on error", type = OptionType.Debug)
     public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false);
-    @Option(help = "Enable expensive assertions")
+    @Option(help = "Enable expensive assertions", type = OptionType.Debug)
     public static final OptionValue<Boolean> DetailedAsserts = new StableOptionValue<Boolean>() {
         @Override
         protected Boolean initialValue() {
@@ -72,7 +72,7 @@
             return enabled;
         }
     };
-    @Option(help = "Enable more verbose log output when available")
+    @Option(help = "Enable more verbose log output when available", type = OptionType.Debug)
     public static final OptionValue<Boolean> LogVerbose = new OptionValue<>(false);
     // @formatter:on
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Dec 16 23:37:35 2014 +0100
@@ -73,7 +73,7 @@
 
     public static class Options {
         // @formatter:off
-        @Option(help = "Enable spill position optimization")
+        @Option(help = "Enable spill position optimization", type = OptionType.Debug)
         public static final OptionValue<Boolean> LSRAOptimizeSpillPosition = new OptionValue<>(true);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LocationMarker.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LocationMarker.java	Tue Dec 16 23:37:35 2014 +0100
@@ -40,7 +40,7 @@
 
     public static class Options {
         // @formatter:off
-        @Option(help = "Use decoupled pass for location marking (instead of using LSRA marking)")
+        @Option(help = "Use decoupled pass for location marking (instead of using LSRA marking)", type = OptionType.Debug)
         public static final OptionValue<Boolean> UseLocationMarker = new OptionValue<>(false);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/OptimizingLinearScanWalker.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/OptimizingLinearScanWalker.java	Tue Dec 16 23:37:35 2014 +0100
@@ -38,9 +38,9 @@
 
     public static class Options {
         // @formatter:off
-        @Option(help = "Enable LSRA optimization")
+        @Option(help = "Enable LSRA optimization", type = OptionType.Debug)
         public static final OptionValue<Boolean> LSRAOptimization = new OptionValue<>(true);
-        @Option(help = "LSRA optimization: Only split but do not reassign")
+        @Option(help = "LSRA optimization: Only split but do not reassign", type = OptionType.Debug)
         public static final OptionValue<Boolean> LSRAOptSplitOnly = new OptionValue<>(false);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Tue Dec 16 23:37:35 2014 +0100
@@ -41,7 +41,7 @@
     public static class Options {
 
         // @formatter:off
-        @Option(help = "Enable inlining")
+        @Option(help = "Enable inlining", type = OptionType.Expert)
         public static final OptionValue<Boolean> Inline = new OptionValue<>(true);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Tue Dec 16 23:37:35 2014 +0100
@@ -36,7 +36,7 @@
     static class Options {
 
         // @formatter:off
-        @Option(help = "")
+        @Option(help = "", type = OptionType.Debug)
         public static final OptionValue<Boolean> ProfileCompiledMethods = new OptionValue<>(false);
         // @formatter:on
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Dec 16 23:37:35 2014 +0100
@@ -81,6 +81,10 @@
 
         appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new GuardLoweringPhase()));
 
+        if (VerifyHeapAtReturn.getValue()) {
+            appendPhase(new VerifyHeapAtReturnPhase());
+        }
+
         appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER));
 
         appendPhase(new FrameStateAssignmentPhase());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TopLevelDebugConfig.java	Tue Dec 16 23:37:35 2014 +0100
@@ -0,0 +1,31 @@
+/*
+ * 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.debug;
+
+/**
+ * A marker class for a scoped debug configuration covering a compilation region. Useful for
+ * programmatically enabling debug config features.
+ *
+ */
+public class TopLevelDebugConfig extends DelegatingDebugConfig {
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Tue Dec 16 23:37:35 2014 +0100
@@ -169,6 +169,58 @@
         return currentDumpLevel >= dumpLevel;
     }
 
+    /**
+     * Enable dumping at the new {@code dumpLevel} for remainder of compile. Requires a
+     * TopLevelDebugConfig
+     *
+     * @param dumpLevel
+     */
+    public static void setDumpLevel(int dumpLevel) {
+        TopLevelDebugConfig config = fetchTopLevelDebugConfig("setLogLevel");
+        if (config != null) {
+            config.override(DelegatingDebugConfig.Level.DUMP, dumpLevel);
+            recursiveUpdateFlags();
+        }
+    }
+
+    /**
+     * Enable logging at the new {@code logLevel} for remainder of compile. Requires a
+     * TopLevelDebugConfig
+     *
+     * @param logLevel
+     */
+    public static void setLogLevel(int logLevel) {
+        TopLevelDebugConfig config = fetchTopLevelDebugConfig("setLogLevel");
+        if (config != null) {
+            config.override(DelegatingDebugConfig.Level.LOG, logLevel);
+            config.delegate(DelegatingDebugConfig.Feature.LOG_METHOD);
+            recursiveUpdateFlags();
+        }
+    }
+
+    private static void recursiveUpdateFlags() {
+        DebugScope c = DebugScope.getInstance();
+        while (c != null) {
+            c.updateFlags();
+            c = c.parent;
+        }
+    }
+
+    private static TopLevelDebugConfig fetchTopLevelDebugConfig(String msg) {
+        DebugConfig config = getConfig();
+        if (config instanceof TopLevelDebugConfig) {
+            return (TopLevelDebugConfig) config;
+        } else {
+            PrintStream out = System.out;
+            if (config == null) {
+                out.printf("DebugScope.%s ignored because debugging is disabled%n", msg);
+            } else {
+                out.printf("DebugScope.%s ignored because top level delegate config missing%n", msg);
+            }
+            return null;
+        }
+    }
+
     public boolean isVerifyEnabled() {
         return verifyEnabled;
     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Dec 16 23:37:35 2014 +0100
@@ -40,7 +40,7 @@
 public class Graph {
 
     static class Options {
-        @Option(help = "Verify graphs often during compilation when assertions are turned on")//
+        @Option(help = "Verify graphs often during compilation when assertions are turned on", type = OptionType.Debug)//
         public static final OptionValue<Boolean> VerifyGraalGraphs = new OptionValue<>(true);
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Dec 16 23:37:35 2014 +0100
@@ -377,8 +377,9 @@
         getResult().getFrameMapBuilder().callsMethod(nativeCallingConvention);
         // TODO(mg): in case a native function uses floating point varargs, the ABI requires that
         // RAX contains the length of the varargs
-        AllocatableValue numberOfFloatingPointArgumentsRegister = AMD64.rax.asValue();
-        emitMove(numberOfFloatingPointArgumentsRegister, JavaConstant.forInt(numberOfFloatingPointArguments));
+        PrimitiveConstant intConst = JavaConstant.forInt(numberOfFloatingPointArguments);
+        AllocatableValue numberOfFloatingPointArgumentsRegister = AMD64.rax.asValue(intConst.getLIRKind());
+        emitMove(numberOfFloatingPointArgumentsRegister, intConst);
         for (int i = 0; i < args.length; i++) {
             Value arg = args[i];
             AllocatableValue loc = nativeCallingConvention.getArgument(i);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Tue Dec 16 23:37:35 2014 +0100
@@ -163,11 +163,13 @@
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
         if (callTarget instanceof HotSpotIndirectCallTargetNode) {
-            AllocatableValue metaspaceMethod = AMD64.rbx.asValue();
-            gen.emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
-            AllocatableValue targetAddress = AMD64.rax.asValue();
-            gen.emitMove(targetAddress, operand(callTarget.computedAddress()));
-            append(new AMD64IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
+            Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod());
+            Value targetAddressSrc = operand(callTarget.computedAddress());
+            AllocatableValue metaspaceMethodDst = AMD64.rbx.asValue(metaspaceMethodSrc.getLIRKind());
+            AllocatableValue targetAddressDst = AMD64.rax.asValue(targetAddressSrc.getLIRKind());
+            gen.emitMove(metaspaceMethodDst, metaspaceMethodSrc);
+            gen.emitMove(targetAddressDst, targetAddressSrc);
+            append(new AMD64IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethodDst, targetAddressDst, callState));
         } else {
             super.emitIndirectCall(callTarget, result, parameters, temps, callState);
         }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Tue Dec 16 23:37:35 2014 +0100
@@ -89,7 +89,7 @@
     public static class Options {
 
         // @formatter:off
-        @Option(help = "Number of TLABs used for HSAIL kernels which allocate")
+        @Option(help = "Number of TLABs used for HSAIL kernels which allocate", type = OptionType.Debug)
         public static  final OptionValue<Integer> HsailKernelTlabs = new OptionValue<>(4);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Tue Dec 16 23:37:35 2014 +0100
@@ -59,13 +59,13 @@
     public static class Options {
 
         // @formatter:off
-        @Option(help = "In HSAIL allocation, allow allocation from eden as fallback if TLAB is full")
+        @Option(help = "In HSAIL allocation, allow allocation from eden as fallback if TLAB is full", type = OptionType.Debug)
         static final OptionValue<Boolean> HsailUseEdenAllocate = new OptionValue<>(false);
 
-        @Option(help = "In HSAIL allocation, allow GPU to allocate a new tlab if TLAB is full")
+        @Option(help = "In HSAIL allocation, allow GPU to allocate a new tlab if TLAB is full", type = OptionType.Debug)
         static final OptionValue<Boolean> HsailNewTlabAllocate = new OptionValue<>(true);
 
-        @Option(help = "Estimate of number of bytes allocated by each HSAIL workitem, used to size TLABs")
+        @Option(help = "Estimate of number of bytes allocated by each HSAIL workitem, used to size TLABs", type = OptionType.Debug)
         public  static  final OptionValue<Integer> HsailAllocBytesPerWorkitem = new OptionValue<>(64);
 
         // @formatter:on
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Tue Dec 16 23:37:35 2014 +0100
@@ -111,11 +111,13 @@
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        AllocatableValue metaspaceMethod = g5.asValue();
-        gen.emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
+        Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod());
+        AllocatableValue metaspaceMethod = g5.asValue(metaspaceMethodSrc.getLIRKind());
+        gen.emitMove(metaspaceMethod, metaspaceMethodSrc);
 
-        AllocatableValue targetAddress = o7.asValue();
-        gen.emitMove(targetAddress, operand(callTarget.computedAddress()));
+        Value targetAddressSrc = operand(callTarget.computedAddress());
+        AllocatableValue targetAddress = o7.asValue(targetAddressSrc.getLIRKind());
+        gen.emitMove(targetAddress, targetAddressSrc);
         append(new SPARCIndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Dec 16 23:37:35 2014 +0100
@@ -27,6 +27,7 @@
 import static com.oracle.graal.compiler.GraalCompiler.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+import static com.oracle.graal.debug.Debug.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.InitTimer.*;
 import static com.oracle.graal.hotspot.meta.HotSpotSuitesProvider.*;
@@ -365,7 +366,9 @@
     static void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long ctask, int id) {
         HotSpotBackend backend = runtime().getHostBackend();
         CompilationTask task = new CompilationTask(backend, method, entryBCI, ctask, id, true);
-        task.runCompilation();
+        try (DebugConfigScope dcs = setConfig(new TopLevelDebugConfig())) {
+            task.runCompilation();
+        }
         return;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Tue Dec 16 23:37:35 2014 +0100
@@ -38,9 +38,9 @@
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.hotspot.HotSpotOptions.OptionConsumer;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.options.*;
+import com.oracle.graal.options.OptionUtils.OptionConsumer;
 import com.oracle.graal.options.OptionValue.OverrideScope;
 import com.oracle.graal.replacements.*;
 
@@ -56,19 +56,19 @@
 
     public static class Options {
         // @formatter:off
-        @Option(help = "Compile all methods in all classes on given class path")
+        @Option(help = "Compile all methods in all classes on given class path", type = OptionType.Debug)
         public static final OptionValue<String> CompileTheWorldClasspath = new OptionValue<>(SUN_BOOT_CLASS_PATH);
-        @Option(help = "Verbose CompileTheWorld operation")
+        @Option(help = "Verbose CompileTheWorld operation", type = OptionType.Debug)
         public static final OptionValue<Boolean> CompileTheWorldVerbose = new OptionValue<>(true);
-        @Option(help = "The number of CompileTheWorld iterations to perform")
+        @Option(help = "The number of CompileTheWorld iterations to perform", type = OptionType.Debug)
         public static final OptionValue<Integer> CompileTheWorldIterations = new OptionValue<>(1);
-        @Option(help = "First class to consider when using -XX:+CompileTheWorld")
+        @Option(help = "First class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug)
         public static final OptionValue<Integer> CompileTheWorldStartAt = new OptionValue<>(1);
-        @Option(help = "Last class to consider when using -XX:+CompileTheWorld")
+        @Option(help = "Last class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug)
         public static final OptionValue<Integer> CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE);
         @Option(help = "Option value overrides to use during compile the world. For example, " +
                        "to disable inlining and partial escape analysis specify '-PartialEscapeAnalysis -Inline'. " +
-                       "The format for each option is the same as on the command line just without the '-G:' prefix.")
+                       "The format for each option is the same as on the command line just without the '-G:' prefix.", type = OptionType.Debug)
         public static final OptionValue<String> CompileTheWorldConfig = new OptionValue<>(null);
         // @formatter:on
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Dec 16 23:37:35 2014 +0100
@@ -189,10 +189,10 @@
     public static class Options {
 
         // @formatter:off
-        @Option(help = "The runtime configuration to use")
+        @Option(help = "The runtime configuration to use", type = OptionType.Expert)
         static final OptionValue<String> GraalRuntime = new OptionValue<>("");
 
-        @Option(help = "File to which logging is sent.  A %p in the name will be replaced with a string identifying the process, usually the process id.")
+        @Option(help = "File to which logging is sent.  A %p in the name will be replaced with a string identifying the process, usually the process id.", type = OptionType.Expert)
         public static final PrintStreamOption LogFile = new PrintStreamOption();
         // @formatter:on
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Tue Dec 16 23:37:35 2014 +0100
@@ -27,22 +27,24 @@
 import static java.lang.Double.*;
 
 import java.lang.reflect.*;
-import java.util.*;
 
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.options.*;
+import com.oracle.graal.options.OptionUtils.OptionConsumer;
 import com.oracle.graal.phases.common.inlining.*;
 
 //JaCoCo Exclude
 
 /**
- * Sets Graal options from the HotSpot command line. Such options are distinguished by a
- * {@code "-G:"} prefix.
+ * Sets Graal options from the HotSpot command line. Such options are distinguished by the
+ * {@link #GRAAL_OPTION_PREFIX} prefix.
  */
 public class HotSpotOptions {
 
+    private static final String GRAAL_OPTION_PREFIX = "-G:";
+
     /**
      * Parses the Graal specific options specified to HotSpot (e.g., on the command line).
      *
@@ -69,10 +71,6 @@
     public static void initialize() {
     }
 
-    interface OptionConsumer {
-        void set(OptionDescriptor desc, Object value);
-    }
-
     /**
      * Helper for the VM code called by {@link #parseVMOptions()}.
      *
@@ -89,10 +87,10 @@
                 option.setValue(Boolean.FALSE);
                 break;
             case '?':
-                printFlags();
+                OptionUtils.printFlags(options, GRAAL_OPTION_PREFIX);
                 break;
             case ' ':
-                printNoMatchMessage(name);
+                OptionUtils.printNoMatchMessage(options, name, GRAAL_OPTION_PREFIX);
                 break;
             case 'i':
                 option.setValue((int) primitiveValue);
@@ -118,104 +116,7 @@
      *            instead.
      */
     public static boolean parseOption(String option, OptionConsumer setter) {
-        if (option.length() == 0) {
-            return false;
-        }
-
-        Object value = null;
-        String optionName = null;
-        String valueString = null;
-
-        if (option.equals("+PrintFlags")) {
-            printFlags();
-            return true;
-        }
-
-        char first = option.charAt(0);
-        if (first == '+' || first == '-') {
-            optionName = option.substring(1);
-            value = (first == '+');
-        } else {
-            int index = option.indexOf('=');
-            if (index == -1) {
-                optionName = option;
-                valueString = null;
-            } else {
-                optionName = option.substring(0, index);
-                valueString = option.substring(index + 1);
-            }
-        }
-
-        OptionDescriptor desc = options.get(optionName);
-        if (desc == null) {
-            printNoMatchMessage(optionName);
-            return false;
-        }
-
-        Class<?> optionType = desc.getType();
-
-        if (value == null) {
-            if (optionType == Boolean.TYPE || optionType == Boolean.class) {
-                System.err.println("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format");
-                return false;
-            }
-
-            if (valueString == null) {
-                System.err.println("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
-                return false;
-            }
-
-            if (optionType == Float.class) {
-                value = Float.parseFloat(valueString);
-            } else if (optionType == Double.class) {
-                value = Double.parseDouble(valueString);
-            } else if (optionType == Integer.class) {
-                value = Integer.parseInt(valueString);
-            } else if (optionType == String.class) {
-                value = valueString;
-            }
-        } else {
-            if (optionType != Boolean.class) {
-                System.err.println("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
-                return false;
-            }
-        }
-
-        if (value != null) {
-            if (setter != null) {
-                setter.set(desc, value);
-            } else {
-                OptionValue<?> optionValue = desc.getOptionValue();
-                optionValue.setValue(value);
-                // System.err.println("Set option " + desc.getName() + " to " + value);
-            }
-        } else {
-            System.err.println("Wrong value \"" + valueString + "\" for option " + optionName);
-            return false;
-        }
-
-        return true;
-    }
-
-    protected static void printNoMatchMessage(String optionName) {
-        OptionDescriptor desc = options.get(optionName);
-        if (desc != null) {
-            if (desc.getType() == Boolean.class) {
-                System.err.println("Boolean option " + optionName + " must be prefixed with '+' or '-'");
-            } else {
-                System.err.println(desc.getType().getSimpleName() + " option " + optionName + " must not be prefixed with '+' or '-'");
-            }
-        } else {
-            System.err.println("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)");
-            List<OptionDescriptor> matches = fuzzyMatch(optionName);
-            if (!matches.isEmpty()) {
-                System.err.println("Did you mean one of the following?");
-                for (OptionDescriptor match : matches) {
-                    boolean isBoolean = match.getType() == Boolean.class;
-                    System.err.println(String.format("    %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=<value>"));
-                }
-            }
-        }
+        return OptionUtils.parseOption(options, option, GRAAL_OPTION_PREFIX, setter);
     }
 
     /**
@@ -246,97 +147,4 @@
             throw new GraalInternalError(e);
         }
     }
-
-    /**
-     * 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() {
-        System.out.println("[Graal flags]");
-        SortedMap<String, OptionDescriptor> sortedOptions = options;
-        for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
-            e.getKey();
-            OptionDescriptor desc = e.getValue();
-            Object value = desc.getOptionValue().getValue();
-            List<String> helpLines = wrap(desc.getHelp(), 70);
-            System.out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
-            for (int i = 1; i < helpLines.size(); i++) {
-                System.out.println(String.format("%67s %s", " ", helpLines.get(i)));
-            }
-        }
-
-        System.exit(0);
-    }
-
-    /**
-     * Compute string similarity based on Dice's coefficient.
-     *
-     * Ported from str_similar() in globals.cpp.
-     */
-    static float stringSimiliarity(String str1, String str2) {
-        int hit = 0;
-        for (int i = 0; i < str1.length() - 1; ++i) {
-            for (int j = 0; j < str2.length() - 1; ++j) {
-                if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) {
-                    ++hit;
-                    break;
-                }
-            }
-        }
-        return 2.0f * hit / (str1.length() + str2.length());
-    }
-
-    private static final float FUZZY_MATCH_THRESHOLD = 0.7F;
-
-    /**
-     * Returns the set of options that fuzzy match a given option name.
-     */
-    private static List<OptionDescriptor> fuzzyMatch(String optionName) {
-        List<OptionDescriptor> matches = new ArrayList<>();
-        for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
-            float score = stringSimiliarity(e.getKey(), optionName);
-            if (score >= FUZZY_MATCH_THRESHOLD) {
-                matches.add(e.getValue());
-            }
-        }
-        return matches;
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java	Tue Dec 16 23:37:35 2014 +0100
@@ -168,11 +168,11 @@
     }
 
     public BitSet getFrameMap() {
-        return (BitSet) frameRefMap.clone();
+        return frameRefMap == null ? null : (BitSet) frameRefMap.clone();
     }
 
     public BitSet getRegisterMap() {
-        return (BitSet) registerRefMap.clone();
+        return registerRefMap == null ? null : (BitSet) registerRefMap.clone();
     }
 
     // clear
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Dec 16 23:37:35 2014 +0100
@@ -67,6 +67,11 @@
      */
     public final int maxFrameSize = 16 * 1024;
 
+    @Override
+    public String toString() {
+        return getClass().getSimpleName();
+    }
+
     HotSpotVMConfig(CompilerToVM compilerToVm) {
         compilerToVm.initializeConfiguration(this);
         assert verifyInitialization();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Tue Dec 16 23:37:35 2014 +0100
@@ -84,16 +84,16 @@
     static class Options {
 
         //@formatter:off
-        @Option(help = "Turn on the benchmark counters, and displays the results on VM shutdown")
+        @Option(help = "Turn on the benchmark counters, and displays the results on VM shutdown", type = OptionType.Debug)
         private static final OptionValue<Boolean> GenericDynamicCounters = new OptionValue<>(false);
-        @Option(help = "Turn on the benchmark counters, and displays the results every n milliseconds")
+        @Option(help = "Turn on the benchmark counters, and displays the results every n milliseconds", type = OptionType.Debug)
         private static final OptionValue<Integer> TimedDynamicCounters = new OptionValue<>(-1);
 
         @Option(help = "Turn on the benchmark counters, and listen for specific patterns on System.out/System.err:%n" +
                        "Format: (err|out),start pattern,end pattern (~ matches multiple digits)%n" +
                        "Examples:%n" +
                        "  dacapo = 'err, starting =====, PASSED in'%n" +
-                       "  specjvm2008 = 'out,Iteration ~ (~s) begins:,Iteration ~ (~s) ends:'")
+                       "  specjvm2008 = 'out,Iteration ~ (~s) begins:,Iteration ~ (~s) ends:'", type = OptionType.Debug)
         private static final OptionValue<String> BenchmarkDynamicCounters = new OptionValue<>(null);
         //@formatter:on
     }
@@ -374,6 +374,8 @@
         }
     }
 
+    private static final LocationIdentity COUNTER_LOCATION = NamedLocationIdentity.mutable("COUNTER_LOCATION");
+
     public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) {
         StructuredGraph graph = counter.graph();
 
@@ -383,9 +385,9 @@
         if (index >= config.graalCountersSize) {
             throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")");
         }
-        ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, config.graalCountersThreadOffset, graph);
+        ConstantLocationNode arrayLocation = ConstantLocationNode.create(COUNTER_LOCATION, config.graalCountersThreadOffset, graph);
         ReadNode readArray = graph.add(ReadNode.create(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE));
-        ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
+        ConstantLocationNode location = ConstantLocationNode.create(COUNTER_LOCATION, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
         ReadNode read = graph.add(ReadNode.create(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE));
         AddNode add = graph.unique(AddNode.create(read, counter.getIncrement()));
         WriteNode write = graph.add(WriteNode.create(readArray, add, location, BarrierType.NONE));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Tue Dec 16 23:37:35 2014 +0100
@@ -137,6 +137,10 @@
             if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
                 newObjectSnippets.lower((DynamicNewArrayNode) n, registers, tool);
             }
+        } else if (n instanceof VerifyHeapNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
+                newObjectSnippets.lower((VerifyHeapNode) n, registers, runtime, tool);
+            }
         } else if (n instanceof MonitorEnterNode) {
             if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
                 monitorSnippets.lower((MonitorEnterNode) n, registers, tool);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Tue Dec 16 23:37:35 2014 +0100
@@ -210,8 +210,7 @@
                 } else {
                     Class<?> clazz = object.getClass();
                     if (StableOptionValue.class.isAssignableFrom(clazz)) {
-                        if (hotspotField.isInObject(object)) {
-                            assert hotspotField.getName().equals("value") : "Unexpected field in " + StableOptionValue.class.getName() + " hierarchy:" + this;
+                        if (hotspotField.isInObject(object) && hotspotField.getName().equals("value")) {
                             StableOptionValue<?> option = (StableOptionValue<?>) object;
                             return HotSpotObjectConstantImpl.forObject(option.getValue());
                         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AssertionSnippets.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AssertionSnippets.java	Tue Dec 16 23:37:35 2014 +0100
@@ -65,7 +65,7 @@
     }
 
     @NodeIntrinsic(ForeignCallNode.class)
-    private static native void vmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
+    static native void vmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
 
     public static class Templates extends AbstractTemplates {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Tue Dec 16 23:37:35 2014 +0100
@@ -198,11 +198,11 @@
 
         // @formatter:off
         @Option(help = "If the probability that a type check will hit one the profiled types (up to " +
-                       "TypeCheckMaxHints) is below this value, the type check will be compiled without profiling info")
+                       "TypeCheckMaxHints) is below this value, the type check will be compiled without profiling info", type = OptionType.Expert)
         static final OptionValue<Double> TypeCheckMinProfileHitProbability = new OptionValue<>(0.5);
 
         @Option(help = "The maximum number of profiled types that will be used when compiling a profiled type check. " +
-                        "Note that TypeCheckMinProfileHitProbability also influences whether profiling info is used in compiled type checks.")
+                        "Note that TypeCheckMinProfileHitProbability also influences whether profiling info is used in compiled type checks.", type = OptionType.Expert)
         static final OptionValue<Integer> TypeCheckMaxHints = new OptionValue<>(2);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Tue Dec 16 23:37:35 2014 +0100
@@ -70,7 +70,7 @@
     public static class Options {
 
         //@formatter:off
-        @Option(help = "")
+        @Option(help = "", type = OptionType.Debug)
         private static final OptionValue<Boolean> ProfileMonitors = new OptionValue<>(false);
         //@formatter:on
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Dec 16 23:37:35 2014 +0100
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.code.UnsignedMath.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.hotspot.nodes.CStringNode.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.Options.*;
 import static com.oracle.graal.nodes.PiArrayNode.*;
@@ -49,6 +50,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -69,7 +71,7 @@
     static class Options {
 
         //@formatter:off
-        @Option(help = "")
+        @Option(help = "", type = OptionType.Debug)
         static final OptionValue<Boolean> ProfileAllocations = new OptionValue<>(false);
         //@formatter:on
     }
@@ -354,6 +356,18 @@
         return memory.toObject();
     }
 
+    @Snippet
+    protected static void verifyHeap(@ConstantParameter Register threadRegister) {
+        Word thread = registerAsWord(threadRegister);
+        Word topValue = readTlabTop(thread);
+        if (!topValue.equal(Word.zero())) {
+            Word topValueContents = topValue.readWord(0, MARK_WORD_LOCATION);
+            if (topValueContents.equal(Word.zero())) {
+                AssertionSnippets.vmMessageC(AssertionSnippets.ASSERTION_VM_MESSAGE_C, true, cstring("overzeroing of TLAB detected"), 0L, 0L, 0L);
+            }
+        }
+    }
+
     /**
      * Formats some allocated memory with an object header and zeroes out the rest.
      */
@@ -378,6 +392,7 @@
         private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic");
         private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic");
         private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray");
+        private final SnippetInfo verifyHeap = snippet(NewObjectSnippets.class, "verifyHeap");
 
         public Templates(HotSpotProviders providers, TargetDescription target) {
             super(providers, providers.getSnippetReflection(), target);
@@ -482,6 +497,28 @@
             assert size >= 0;
             return size;
         }
+
+        static class WarnOnce {
+            static {
+                System.out.println("VerifyHeapNode requires a VM with asserts enabled.");
+            }
+
+            static void warn() {
+            }
+        }
+
+        public void lower(VerifyHeapNode verifyHeapNode, HotSpotRegistersProvider registers, HotSpotGraalRuntimeProvider runtime, LoweringTool tool) {
+            if (runtime.getConfig().cAssertions) {
+                Arguments args = new Arguments(verifyHeap, verifyHeapNode.graph().getGuardsStage(), tool.getLoweringStage());
+                args.addConst("threadRegister", registers.getThreadRegister());
+
+                SnippetTemplate template = template(args);
+                template.instantiate(providers.getMetaAccess(), verifyHeapNode, DEFAULT_REPLACER, args);
+            } else {
+                WarnOnce.warn();
+                GraphUtil.removeFixedWithUnusedInputs(verifyHeapNode);
+            }
+        }
     }
 
     private static final SnippetCounter.Group countersNew = SnippetCounters.getValue() ? new SnippetCounter.Group("NewInstance") : null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Tue Dec 16 23:37:35 2014 +0100
@@ -114,7 +114,7 @@
 
     @Snippet(removeAllFrameStates = true)
     public static Object[] objectArrayClone(Object[] src) {
-        Object[] result = (Object[]) DynamicNewArrayNode.newUninitializedArray(GuardingPiNode.guardingNonNull(src.getClass().getComponentType()), src.length);
+        Object[] result = (Object[]) DynamicNewArrayNode.newUninitializedArray(GuardingPiNode.guardingNonNull(src.getClass().getComponentType()), src.length, Kind.Object);
         ArrayCopyCallNode.disjointUninitializedArraycopy(src, 0, result, 0, src.length, Kind.Object);
         return result;
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Tue Dec 16 23:37:35 2014 +0100
@@ -44,7 +44,7 @@
 
     static class Options {
         // @formatter:off
-        @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode")
+        @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug)
         public static final OptionValue<Integer> TraceBytecodeParserLevel = new OptionValue<>(0);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Tue Dec 16 23:37:35 2014 +0100
@@ -49,7 +49,7 @@
 
     public static class Options {
         // @formatter:off
-        @Option(help = "Enable constant load optimization.")
+        @Option(help = "Enable constant load optimization.", type = OptionType.Debug)
         public static final OptionValue<Boolean> ConstantLoadOptimization = new OptionValue<>(true);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Tue Dec 16 23:37:35 2014 +0100
@@ -48,9 +48,9 @@
 
     public static class Options {
         // @formatter:off
-        @Option(help = "Print HIR along side LIR as the latter is generated")
+        @Option(help = "Print HIR along side LIR as the latter is generated", type = OptionType.Debug)
         public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false);
-        @Option(help = "The trace level for the LIR generator")
+        @Option(help = "The trace level for the LIR generator", type = OptionType.Debug)
         public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0);
         // @formatter:on
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/VerifyHeapNode.java	Tue Dec 16 23:37:35 2014 +0100
@@ -0,0 +1,60 @@
+/*
+ * 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.nodes.debug;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * A node for platform dependent verification of the Java heap. Intended to be used for debugging
+ * heap corruption issues.
+ */
+@NodeInfo
+public class VerifyHeapNode extends FixedWithNextNode implements Lowerable {
+
+    public static VerifyHeapNode create() {
+        return new VerifyHeapNode();
+    }
+
+    protected VerifyHeapNode() {
+        super(StampFactory.forVoid());
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
+    public static void addBefore(FixedNode position) {
+        StructuredGraph graph = position.graph();
+        graph.addBeforeFixed(position, graph.add(VerifyHeapNode.create()));
+    }
+
+    public static void addAfter(FixedWithNextNode position) {
+        StructuredGraph graph = position.graph();
+        graph.addAfterFixed(position, graph.add(VerifyHeapNode.create()));
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Dec 16 23:37:35 2014 +0100
@@ -156,6 +156,6 @@
         if (defaultSuccessorIndex() == -1) {
             throw new GraalInternalError("unexpected");
         }
-        return defaultSuccessorIndex() == -1 ? null : successors.get(defaultSuccessorIndex());
+        return successors.get(defaultSuccessorIndex());
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Tue Dec 16 23:37:35 2014 +0100
@@ -42,27 +42,38 @@
 
     @Input ValueNode elementType;
 
+    /**
+     * A non-null value indicating the worst case element type. Mainly useful for distinguishing
+     * Object arrays from primitive arrays.
+     */
+    protected final Kind knownElementKind;
+
     public static DynamicNewArrayNode create(ValueNode elementType, ValueNode length) {
         return new DynamicNewArrayNode(elementType, length);
     }
 
     protected DynamicNewArrayNode(ValueNode elementType, ValueNode length) {
-        this(elementType, length, true);
+        this(elementType, length, true, null);
     }
 
-    public static DynamicNewArrayNode create(ValueNode elementType, ValueNode length, boolean fillContents) {
-        return new DynamicNewArrayNode(elementType, length, fillContents);
+    public static DynamicNewArrayNode create(ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind) {
+        return new DynamicNewArrayNode(elementType, length, fillContents, knownElementKind);
     }
 
-    protected DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents) {
+    protected DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind) {
         super(StampFactory.objectNonNull(), length, fillContents);
         this.elementType = elementType;
+        this.knownElementKind = knownElementKind;
     }
 
     public ValueNode getElementType() {
         return elementType;
     }
 
+    public Kind getKnownElementKind() {
+        return knownElementKind;
+    }
+
     protected NewArrayNode forConstantType(ResolvedJavaType type) {
         ValueNode len = length();
         NewArrayNode ret = graph().add(NewArrayNode.create(type, len.isAlive() ? len : graph().addOrUniqueWithInputs(len), fillContents()));
@@ -94,10 +105,10 @@
     }
 
     @NodeIntrinsic
-    private static native Object newArray(Class<?> componentType, int length, @ConstantNodeParameter boolean fillContents);
+    private static native Object newArray(Class<?> componentType, int length, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter Kind knownElementKind);
 
-    public static Object newUninitializedArray(Class<?> componentType, int length) {
-        return newArray(componentType, length, false);
+    public static Object newUninitializedArray(Class<?> componentType, int length, Kind knownElementKind) {
+        return newArray(componentType, length, false, knownElementKind);
     }
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Tue Dec 16 23:37:35 2014 +0100
@@ -112,20 +112,52 @@
             }
 
             // check if the type of the receiver can narrow the result
-            if (tryToResolveMethod(tool)) {
-                return;
+            ValueNode receiver = receiver();
+            ResolvedJavaType type = StampTool.typeOrNull(receiver);
+            if (type == null && invokeKind == InvokeKind.Virtual) {
+                // For virtual calls, we are guaranteed to receive a correct receiver type.
+                type = targetMethod.getDeclaringClass();
             }
+            if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) {
+                /*
+                 * either the holder class is exact, or the receiver object has an exact type, or
+                 * it's an array type
+                 */
+                ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(targetMethod(), invoke().getContextType());
+                if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) {
+                    setInvokeKind(InvokeKind.Special);
+                    setTargetMethod(resolvedMethod);
+                    return;
+                }
+                if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) {
+                    ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype();
+                    if (uniqueConcreteType != null) {
+                        ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod(), invoke().getContextType());
+                        if (methodFromUniqueType != null) {
+                            tool.assumptions().recordConcreteSubtype(type, uniqueConcreteType);
+                            setInvokeKind(InvokeKind.Special);
+                            setTargetMethod(methodFromUniqueType);
+                            return;
+                        }
+                    }
 
-            ValueNode receiver = receiver();
-
-            // try to turn an interface call into a virtual call
+                    ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod());
+                    if (uniqueConcreteMethod != null) {
+                        tool.assumptions().recordConcreteMethod(targetMethod(), type, uniqueConcreteMethod);
+                        setInvokeKind(InvokeKind.Special);
+                        setTargetMethod(uniqueConcreteMethod);
+                        return;
+                    }
+                }
+            }
+            // try to turn a interface call into a virtual call
             ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass();
             /*
              * We need to check the invoke kind to avoid recursive simplification for virtual
              * interface methods calls.
              */
             if (declaredReceiverType.isInterface() && !invokeKind().equals(InvokeKind.Virtual)) {
-                tryCheckCastSingleImplementor(tool, receiver, declaredReceiverType);
+                tryCheckCastSingleImplementor(receiver, declaredReceiverType);
             }
 
             if (invokeKind().equals(InvokeKind.Interface) && receiver instanceof UncheckedInterfaceProvider) {
@@ -134,62 +166,14 @@
                 if (uncheckedStamp != null) {
                     ResolvedJavaType uncheckedReceiverType = StampTool.typeOrNull(uncheckedStamp);
                     if (uncheckedReceiverType.isInterface()) {
-                        tryCheckCastSingleImplementor(tool, receiver, uncheckedReceiverType);
+                        tryCheckCastSingleImplementor(receiver, uncheckedReceiverType);
                     }
                 }
             }
         }
     }
 
-    /**
-     * Try to use receiver type information to statically bind the method.
-     *
-     * @param tool
-     * @return true if successfully converted to InvokeKind.Special
-     */
-    private boolean tryToResolveMethod(SimplifierTool tool) {
-        ValueNode receiver = receiver();
-        ResolvedJavaType type = StampTool.typeOrNull(receiver);
-        if (type == null && invokeKind == InvokeKind.Virtual) {
-            // For virtual calls, we are guaranteed to receive a correct receiver type.
-            type = targetMethod.getDeclaringClass();
-        }
-        if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) {
-            /*
-             * either the holder class is exact, or the receiver object has an exact type, or it's
-             * an array type
-             */
-            ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(targetMethod(), invoke().getContextType());
-            if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) {
-                setInvokeKind(InvokeKind.Special);
-                setTargetMethod(resolvedMethod);
-                return true;
-            }
-            if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) {
-                ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype();
-                if (uniqueConcreteType != null) {
-                    ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod(), invoke().getContextType());
-                    if (methodFromUniqueType != null) {
-                        tool.assumptions().recordConcreteSubtype(type, uniqueConcreteType);
-                        setInvokeKind(InvokeKind.Special);
-                        setTargetMethod(methodFromUniqueType);
-                        return true;
-                    }
-                }
-
-                ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod());
-                if (uniqueConcreteMethod != null) {
-                    tool.assumptions().recordConcreteMethod(targetMethod(), type, uniqueConcreteMethod);
-                    setInvokeKind(InvokeKind.Special);
-                    setTargetMethod(uniqueConcreteMethod);
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private void tryCheckCastSingleImplementor(SimplifierTool tool, ValueNode receiver, ResolvedJavaType declaredReceiverType) {
+    private void tryCheckCastSingleImplementor(ValueNode receiver, ResolvedJavaType declaredReceiverType) {
         ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor();
         if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) {
             ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType(), true);
@@ -214,8 +198,6 @@
                 arguments().set(0, piNode);
                 setInvokeKind(InvokeKind.Virtual);
                 setTargetMethod(singleImplementorMethod);
-                // Now try to bind the method exactly.
-                tryToResolveMethod(tool);
             }
         }
     }
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/Option.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/Option.java	Tue Dec 16 23:37:35 2014 +0100
@@ -27,7 +27,7 @@
 /**
  * Describes the attributes of an option whose {@link OptionValue value} is in a static field
  * annotated by this annotation type.
- * 
+ *
  * @see OptionProcessor
  * @see OptionDescriptor
  */
@@ -45,4 +45,9 @@
      * 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/OptionType.java	Tue Dec 16 23:37:35 2014 +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 Graal 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/OptionUtils.java	Tue Dec 16 23:37:35 2014 +0100
@@ -0,0 +1,234 @@
+/*
+ * 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.*;
+
+public class OptionUtils {
+
+    public interface OptionConsumer {
+        void set(OptionDescriptor desc, Object value);
+    }
+
+    /**
+     * Parses a given option value specification.
+     *
+     * @param option the specification of an option and its value
+     * @param setter the object to notify of the parsed option and value. If null, the
+     *            {@link OptionValue#setValue(Object)} method of the specified option is called
+     *            instead.
+     */
+    public static boolean parseOption(SortedMap<String, OptionDescriptor> options, String option, String prefix, OptionConsumer setter) {
+        if (option.length() == 0) {
+            return false;
+        }
+
+        Object value = null;
+        String optionName = null;
+        String valueString = null;
+
+        if (option.equals("+PrintFlags")) {
+            printFlags(options, prefix);
+            return true;
+        }
+
+        char first = option.charAt(0);
+        if (first == '+' || first == '-') {
+            optionName = option.substring(1);
+            value = (first == '+');
+        } else {
+            int index = option.indexOf('=');
+            if (index == -1) {
+                optionName = option;
+                valueString = null;
+            } else {
+                optionName = option.substring(0, index);
+                valueString = option.substring(index + 1);
+            }
+        }
+
+        OptionDescriptor desc = options.get(optionName);
+        if (desc == null) {
+            printNoMatchMessage(options, optionName, prefix);
+            return false;
+        }
+
+        Class<?> optionType = desc.getType();
+
+        if (value == null) {
+            if (optionType == Boolean.TYPE || optionType == Boolean.class) {
+                System.err.println("Value for boolean option '" + optionName + "' must use '" + prefix + "+" + optionName + "' or '" + prefix + "-" + optionName + "' format");
+                return false;
+            }
+
+            if (valueString == null) {
+                System.err.println("Value for option '" + optionName + "' must use '" + prefix + optionName + "=<value>' format");
+                return false;
+            }
+
+            if (optionType == Float.class) {
+                value = Float.parseFloat(valueString);
+            } else if (optionType == Double.class) {
+                value = Double.parseDouble(valueString);
+            } else if (optionType == Integer.class) {
+                value = Integer.parseInt(valueString);
+            } else if (optionType == String.class) {
+                value = valueString;
+            }
+        } else {
+            if (optionType != Boolean.class) {
+                System.err.println("Value for option '" + optionName + "' must use '" + prefix + optionName + "=<value>' format");
+                return false;
+            }
+        }
+
+        if (value != null) {
+            if (setter != null) {
+                setter.set(desc, value);
+            } else {
+                OptionValue<?> optionValue = desc.getOptionValue();
+                optionValue.setValue(value);
+                // System.err.println("Set option " + desc.getName() + " to " + value);
+            }
+        } else {
+            System.err.println("Wrong value \"" + valueString + "\" for option " + optionName);
+            return false;
+        }
+
+        return true;
+    }
+
+    public static void printNoMatchMessage(SortedMap<String, OptionDescriptor> options, String optionName, String prefix) {
+        OptionDescriptor desc = options.get(optionName);
+        if (desc != null) {
+            if (desc.getType() == Boolean.class) {
+                System.err.println("Boolean option " + optionName + " must be prefixed with '+' or '-'");
+            } else {
+                System.err.println(desc.getType().getSimpleName() + " option " + optionName + " must not be prefixed with '+' or '-'");
+            }
+        } else {
+            System.err.println("Could not find option " + optionName + " (use " + prefix + "+PrintFlags to see options)");
+            List<OptionDescriptor> matches = fuzzyMatch(options, optionName);
+            if (!matches.isEmpty()) {
+                System.err.println("Did you mean one of the following?");
+                for (OptionDescriptor match : matches) {
+                    boolean isBoolean = match.getType() == Boolean.class;
+                    System.err.println(String.format("    %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=<value>"));
+                }
+            }
+        }
+    }
+
+    /**
+     * Wraps some given text to one or more lines of a given maximum width.
+     *
+     * @param text text to wrap
+     * @param width maximum width of an output line, exception for words in {@code text} longer than
+     *            this value
+     * @return {@code text} broken into lines
+     */
+    private static List<String> wrap(String text, int width) {
+        List<String> lines = Collections.singletonList(text);
+        if (text.length() > width) {
+            String[] chunks = text.split("\\s+");
+            lines = new ArrayList<>();
+            StringBuilder line = new StringBuilder();
+            for (String chunk : chunks) {
+                if (line.length() + chunk.length() > width) {
+                    lines.add(line.toString());
+                    line.setLength(0);
+                }
+                if (line.length() != 0) {
+                    line.append(' ');
+                }
+                String[] embeddedLines = chunk.split("%n", -2);
+                if (embeddedLines.length == 1) {
+                    line.append(chunk);
+                } else {
+                    for (int i = 0; i < embeddedLines.length; i++) {
+                        line.append(embeddedLines[i]);
+                        if (i < embeddedLines.length - 1) {
+                            lines.add(line.toString());
+                            line.setLength(0);
+                        }
+                    }
+                }
+            }
+            if (line.length() != 0) {
+                lines.add(line.toString());
+            }
+        }
+        return lines;
+    }
+
+    public static void printFlags(SortedMap<String, OptionDescriptor> options, String prefix) {
+        System.out.println("[List of " + prefix + " options]");
+        SortedMap<String, OptionDescriptor> sortedOptions = options;
+        for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
+            e.getKey();
+            OptionDescriptor desc = e.getValue();
+            Object value = desc.getOptionValue().getValue();
+            List<String> helpLines = wrap(desc.getHelp(), 70);
+            System.out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
+            for (int i = 1; i < helpLines.size(); i++) {
+                System.out.println(String.format("%67s %s", " ", helpLines.get(i)));
+            }
+        }
+
+        System.exit(0);
+    }
+
+    /**
+     * Compute string similarity based on Dice's coefficient.
+     *
+     * Ported from str_similar() in globals.cpp.
+     */
+    static float stringSimiliarity(String str1, String str2) {
+        int hit = 0;
+        for (int i = 0; i < str1.length() - 1; ++i) {
+            for (int j = 0; j < str2.length() - 1; ++j) {
+                if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) {
+                    ++hit;
+                    break;
+                }
+            }
+        }
+        return 2.0f * hit / (str1.length() + str2.length());
+    }
+
+    private static final float FUZZY_MATCH_THRESHOLD = 0.7F;
+
+    /**
+     * Returns the set of options that fuzzy match a given option name.
+     */
+    private static List<OptionDescriptor> fuzzyMatch(SortedMap<String, OptionDescriptor> options, String optionName) {
+        List<OptionDescriptor> matches = new ArrayList<>();
+        for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
+            float score = stringSimiliarity(e.getKey(), optionName);
+            if (score >= FUZZY_MATCH_THRESHOLD) {
+                matches.add(e.getValue());
+            }
+        }
+        return matches;
+    }
+}
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Tue Dec 16 23:37:35 2014 +0100
@@ -130,6 +130,8 @@
 
     static final ThreadLocal<OverrideScope> overrideScopes = new ThreadLocal<>();
 
+    private T initialValue;
+
     /**
      * The raw option value.
      */
@@ -152,8 +154,10 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
     public OptionValue(T value) {
-        this.value = value;
+        this.initialValue = value;
+        this.value = (T) UNINITIALIZED;
         addToHistogram(this);
     }
 
@@ -165,6 +169,7 @@
      */
     @SuppressWarnings("unchecked")
     protected OptionValue() {
+        this.initialValue = (T) UNINITIALIZED;
         this.value = (T) UNINITIALIZED;
         addToHistogram(this);
     }
@@ -184,6 +189,14 @@
     }
 
     /**
+     * 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()}.
@@ -198,6 +211,34 @@
     }
 
     /**
+     * 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 getInitialValue() {
+        if (initialValue == UNINITIALIZED) {
+            initialValue = initialValue();
+        }
+        return initialValue;
+    }
+
+    /**
+     * Returns true if the option has the same value that was set in the source code.
+     */
+    public boolean hasInitialValue() {
+        if (!(this instanceof StableOptionValue)) {
+            OverrideScope overrideScope = overrideScopes.get();
+            if (overrideScope != null) {
+                T override = overrideScope.getOverride(this);
+                if (override != null) {
+                    return false;
+                }
+            }
+        }
+        return value == UNINITIALIZED || Objects.equals(value, getInitialValue());
+    }
+
+    /**
      * Gets the value of this option.
      */
     public T getValue() {
@@ -213,10 +254,11 @@
                 }
             }
         }
-        if (value == UNINITIALIZED) {
-            value = initialValue();
+        if (value != UNINITIALIZED) {
+            return value;
+        } else {
+            return getInitialValue();
         }
-        return value;
     }
 
     /**
@@ -235,7 +277,11 @@
                 overrideScope.getOverrides(this, (Collection<Object>) values);
             }
         }
-        values.add(value);
+        if (value != UNINITIALIZED) {
+            values.add(value);
+        } else {
+            values.add(getInitialValue());
+        }
         return values;
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Tue Dec 16 23:37:35 2014 +0100
@@ -34,7 +34,7 @@
 
     public static class Options {
         // @formatter:off
-        @Option(help = "Disable optional dead code eliminations")
+        @Option(help = "Disable optional dead code eliminations", type = OptionType.Debug)
         public static final OptionValue<Boolean> ReduceDCE = new OptionValue<>(true);
         // @formatter:on
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/VerifyHeapAtReturnPhase.java	Tue Dec 16 23:37:35 2014 +0100
@@ -0,0 +1,37 @@
+/*
+ * 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.phases.common;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.debug.*;
+import com.oracle.graal.phases.*;
+
+public class VerifyHeapAtReturnPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) {
+            VerifyHeapNode.addBefore(returnNode);
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java	Tue Dec 16 23:37:35 2014 +0100
@@ -37,7 +37,7 @@
     public static class Options {
 
         // @formatter:off
-        @Option(help = "Unconditionally inline intrinsics")
+        @Option(help = "Unconditionally inline intrinsics", type = OptionType.Debug)
         public static final OptionValue<Boolean> AlwaysInlineIntrinsics = new OptionValue<>(false);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Tue Dec 16 23:37:35 2014 +0100
@@ -36,7 +36,7 @@
     static class Options {
 
         // @formatter:off
-        @Option(help = "The compiler configuration to use")
+        @Option(help = "The compiler configuration to use", type = OptionType.User)
         static final OptionValue<String> CompilerConfiguration = new OptionValue<>("");
         // @formatter:on
     }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java	Tue Dec 16 23:37:35 2014 +0100
@@ -48,7 +48,7 @@
 
     static class Options {
         // @formatter:off
-        @Option(help = "Run level for NoDeadCodeVerifyHandler (0 = off, 1 = info, 2 = verbose, 3 = fatal)")
+        @Option(help = "Run level for NoDeadCodeVerifyHandler (0 = off, 1 = info, 2 = verbose, 3 = fatal)", type = OptionType.Debug)
         public static final OptionValue<Integer> NDCV = new OptionValue<>(0);
         // @formatter:on
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Tue Dec 16 23:37:35 2014 +0100
@@ -177,7 +177,7 @@
         if (value.isConstant()) {
             JavaConstant sourceConstant = value.asJavaConstant();
             JavaConstant boxedConstant = constantReflection.boxPrimitive(sourceConstant);
-            if (boxedConstant != null && boxedConstant.getKind() == box.getBoxingKind()) {
+            if (boxedConstant != null && sourceConstant.getKind() == box.getBoxingKind()) {
                 return ConstantNode.forConstant(boxedConstant, metaAccess, box.graph());
             }
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Tue Dec 16 23:37:35 2014 +0100
@@ -40,10 +40,12 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.util.*;
 
@@ -99,11 +101,17 @@
             boxingSnippets.lower((BoxNode) n, tool);
         } else if (n instanceof UnboxNode) {
             boxingSnippets.lower((UnboxNode) n, tool);
+        } else if (n instanceof VerifyHeapNode) {
+            lowerVerifyHeap((VerifyHeapNode) n);
         } else {
             throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n);
         }
     }
 
+    protected void lowerVerifyHeap(VerifyHeapNode n) {
+        GraphUtil.removeFixedWithUnusedInputs(n);
+    }
+
     protected void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) {
         assert loadField.getKind() != Kind.Illegal;
         StructuredGraph graph = loadField.graph();
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Dec 16 23:37:35 2014 +0100
@@ -224,10 +224,29 @@
         PhaseContext phaseContext = new PhaseContext(providers, assumptions);
         boolean changed = false;
         boolean changedInIteration;
+        ArrayDeque<MethodCallTargetNode> queue = new ArrayDeque<>();
+        MetaAccessProvider metaAccess = providers.getMetaAccess();
+        ResolvedJavaType profileClass = metaAccess.lookupJavaType(NodeCloneable.class);
         do {
             changedInIteration = false;
             for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class)) {
                 InvokeKind kind = methodCallTargetNode.invokeKind();
+                if (kind == InvokeKind.Static || kind == InvokeKind.Special) {
+                    ValueNode receiver = methodCallTargetNode.receiver();
+                    if (receiver != null && receiver.isConstant() && profileClass.isAssignableFrom(receiver.stamp().javaType(metaAccess))) {
+                        queue.addFirst(methodCallTargetNode);
+                    } else {
+                        queue.addLast(methodCallTargetNode);
+                    }
+                }
+            }
+
+            while (!queue.isEmpty()) {
+                MethodCallTargetNode methodCallTargetNode = queue.removeFirst();
+                if (!methodCallTargetNode.isAlive()) {
+                    continue;
+                }
+                InvokeKind kind = methodCallTargetNode.invokeKind();
                 try (Indent id1 = Debug.logAndIndent("try inlining %s, kind = %s", methodCallTargetNode.targetMethod(), kind)) {
                     if (kind == InvokeKind.Static || kind == InvokeKind.Special) {
                         if ((TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) && kind == InvokeKind.Special && methodCallTargetNode.receiver().isConstant()) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Tue Dec 16 23:37:35 2014 +0100
@@ -41,99 +41,137 @@
      * Element = Include | '~' Exclude ;
      * </pre>
      */
-    @Option(help = "Restrict compilation to comma-separated list of includes (or excludes prefixed with tilde)")
+    @Option(help = "Restrict compilation to comma-separated list of includes (or excludes prefixed with tilde)", type = OptionType.Debug)
     public static final OptionValue<String> TruffleCompileOnly = new OptionValue<>(null);
-    @Option(help = "Compile call target when call count exceeds this threshold")
+
+    @Option(help = "Compile call target when call count exceeds this threshold", type = OptionType.User)
     public static final OptionValue<Integer> TruffleCompilationThreshold = new OptionValue<>(1000);
-    @Option(help = "Defines the maximum timespan in milliseconds that is required for a call target to be queued for compilation.")
+
+    @Option(help = "Defines the maximum timespan in milliseconds that is required for a call target to be queued for compilation.", type = OptionType.User)
     public static final OptionValue<Integer> TruffleTimeThreshold = new OptionValue<>(25000);
-    @Option(help = "Minimum number of calls before a call target is compiled")
+
+    @Option(help = "Minimum number of calls before a call target is compiled", type = OptionType.Expert)
     public static final OptionValue<Integer> TruffleMinInvokeThreshold = new OptionValue<>(3);
-    @Option(help = "Delay compilation after an invalidation to allow for reprofiling")
+
+    @Option(help = "Delay compilation after an invalidation to allow for reprofiling", type = OptionType.Expert)
     public static final OptionValue<Integer> TruffleInvalidationReprofileCount = new OptionValue<>(3);
-    @Option(help = "Delay compilation after a node replacement")
+
+    @Option(help = "Delay compilation after a node replacement", type = OptionType.Expert)
     public static final OptionValue<Integer> TruffleReplaceReprofileCount = new OptionValue<>(10);
-    @Option(help = "Enable automatic inlining of call targets")
+
+    @Option(help = "Enable automatic inlining of call targets", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleFunctionInlining = new OptionValue<>(true);
-    @Option(help = "Enable an expansion cache per CallTarget. Only functionable with TruffleContextSensitiveInlining enabled.")
+
+    @Option(help = "Enable an expansion cache per CallTarget. Only functionable with TruffleContextSensitiveInlining enabled.", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleFunctionInliningCache = new OptionValue<>(true);
-    @Option(help = "Maximum number of Graal IR nodes during partial evaluation")
+
+    @Option(help = "Maximum number of Graal IR nodes during partial evaluation", type = OptionType.Expert)
     public static final OptionValue<Integer> TruffleGraphMaxNodes = new OptionValue<>(200000);
-    @Option(help = "Stop inlining if caller's cumulative tree size would exceed this limit")
+
+    @Option(help = "Stop inlining if caller's cumulative tree size would exceed this limit", type = OptionType.Expert)
     public static final OptionValue<Integer> TruffleInliningMaxCallerSize = new OptionValue<>(2250);
 
-    @Option(help = "Defines the number of graal nodes that triggers a performance warning.")
+    @Option(help = "Defines the number of graal nodes that triggers a performance warning.", type = OptionType.Debug)
     public static final OptionValue<Integer> TrufflePerformanceWarningGraalNodeCount = new OptionValue<>(1000);
 
-    @Option(help = "Enable call target splitting")
+    @Option(help = "Enable call target splitting", type = OptionType.Expert)
     public static final OptionValue<Boolean> TruffleSplitting = new OptionValue<>(true);
-    @Option(help = "Experimental: Enable the new version of truffle splitting.")
+
+    @Option(help = "Experimental: Enable the new version of truffle splitting.", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleSplittingNew = new OptionValue<>(false);
-    @Option(help = "Experimental. New splitting only: Whether or not splitting should be based instance comparisons of non TypedObjects")
+
+    @Option(help = "Experimental. New splitting only: Whether or not splitting should be based instance comparisons of non TypedObjects", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleSplittingClassInstanceStamps = new OptionValue<>(false);
-    @Option(help = "Experimental. New splitting only: Whether or not splitting should be based instance comparisons of TypedObjects")
+
+    @Option(help = "Experimental. New splitting only: Whether or not splitting should be based instance comparisons of TypedObjects", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleSplittingTypeInstanceStamps = new OptionValue<>(true);
-    @Option(help = "Experimental. New splitting only: The number of calls until splitting is performed. ")
+
+    @Option(help = "Experimental. New splitting only: The number of calls until splitting is performed. ", type = OptionType.Debug)
     public static final OptionValue<Integer> TruffleSplittingStartCallCount = new OptionValue<>(3);
-    @Option(help = "Experimental. New splitting only: Split everything aggressively. ")
+
+    @Option(help = "Experimental. New splitting only: Split everything aggressively. ", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleSplittingAggressive = new OptionValue<>(false);
 
+    @Option(help = "Disable call target splitting if tree size exceeds this limit", type = OptionType.Debug)
+    public static final OptionValue<Integer> TruffleSplittingMaxCalleeSize = new OptionValue<>(100);
 
-    @Option(help = "Disable call target splitting if tree size exceeds this limit")
-    public static final OptionValue<Integer> TruffleSplittingMaxCalleeSize = new OptionValue<>(100);
-    @Option(help = "Number of most recently used methods in truffle cache")
+    @Option(help = "Number of most recently used methods in truffle cache", type = OptionType.Debug)
     public static final OptionValue<Integer> TruffleMaxCompilationCacheSize = new OptionValue<>(512);
-    @Option(help = "Enable asynchronous truffle compilation in background thread")
+
+    @Option(help = "Enable asynchronous truffle compilation in background thread", type = OptionType.Expert)
     public static final OptionValue<Boolean> TruffleBackgroundCompilation = new OptionValue<>(true);
-    @Option(help = "")
+
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Integer> TruffleCompilationDecisionTime = new OptionValue<>(100);
-    @Option(help = "")
+
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleCompilationDecisionTimePrintFail = new OptionValue<>(false);
-    @Option(help = "")
+
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleReturnTypeSpeculation = new StableOptionValue<>(true);
-    @Option(help = "")
+
+    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleArgumentTypeSpeculation = new StableOptionValue<>(true);
 
     // tracing
-    @Option(help = "Print potential performance problems")
+    @Option(help = "Print potential performance problems", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTrufflePerformanceWarnings = new OptionValue<>(false);
-    @Option(help = "Print information for compilation results")
+
+    @Option(help = "Print information for compilation results", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleCompilation = new OptionValue<>(false);
-    @Option(help = "Print information for compilation queuing")
+
+    @Option(help = "Print information for compilation queuing", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleCompilationDetails = new OptionValue<>(false);
-    @Option(help = "Print a node count histogram after each compilation")
+
+    @Option(help = "Print a node count histogram after each compilation", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleCompilationHistogram = new OptionValue<>(false);
-    @Option(help = "Print all polymorphic and generic nodes after each compilation")
+
+    @Option(help = "Print all polymorphic and generic nodes after each compilation", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleCompilationPolymorphism = new OptionValue<>(false);
-    @Option(help = "Print all polymorphic and generic nodes after each compilation")
+
+    @Option(help = "Print all polymorphic and generic nodes after each compilation", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleCompilationAST = new OptionValue<>(false);
-    @Option(help = "Print the inlined call tree for each compiled method")
+
+    @Option(help = "Print the inlined call tree for each compiled method", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleCompilationCallTree = new OptionValue<>(false);
-    @Option(help = "Print the expansion trees for each compilation")
+
+    @Option(help = "Print the expansion trees for each compilation", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleExpansion = new OptionValue<>(false);
-    @Option(help = "Print source secions for printed expansion trees")
+
+    @Option(help = "Print source secions for printed expansion trees", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleExpansionSource = new OptionValue<>(false);
-    @Option(help = "Print detailed information for the Truffle compilation cache")
+
+    @Option(help = "Print detailed information for the Truffle compilation cache", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleCacheDetails = new OptionValue<>(false);
-    @Option(help = "Treat compilation exceptions as fatal exceptions that will exit the application")
+
+    @Option(help = "Treat compilation exceptions as fatal exceptions that will exit the application", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleCompilationExceptionsAreFatal = new OptionValue<>(false);
-    @Option(help = "Treat compilation exceptions as thrown runtime exceptions")
+
+    @Option(help = "Treat compilation exceptions as thrown runtime exceptions", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleCompilationExceptionsAreThrown = new OptionValue<>(false);
-    @Option(help = "Print information for inlining for each compilation.")
+
+    @Option(help = "Print information for inlining for each compilation.", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleInlining = new OptionValue<>(false);
-    @Option(help = "Print information for each splitted call site.")
+
+    @Option(help = "Print information for each splitted call site.", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleSplitting = new OptionValue<>(false);
-    @Option(help = "Print stack trace on transfer to interpreter")
+
+    @Option(help = "Print stack trace on transfer to interpreter", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleTransferToInterpreter = new StableOptionValue<>(false);
-    @Option(help = "Print stack trace on assumption invalidation")
+
+    @Option(help = "Print stack trace on assumption invalidation", type = OptionType.Debug)
     public static final OptionValue<Boolean> TraceTruffleAssumptions = new StableOptionValue<>(false);
-    @Option(help = "Number of stack trace elements printed by TraceTruffleTransferToInterpreter and TraceTruffleAssumptions")
+
+    @Option(help = "Number of stack trace elements printed by TraceTruffleTransferToInterpreter and TraceTruffleAssumptions", type = OptionType.Debug)
     public static final OptionValue<Integer> TraceTruffleStackTraceLimit = new OptionValue<>(20);
-    @Option(help = "Print a summary of execution counts for all executed CallTargets. Introduces counter overhead for each call.")
+
+    @Option(help = "Print a summary of execution counts for all executed CallTargets. Introduces counter overhead for each call.", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleCallTargetProfiling = new StableOptionValue<>(false);
-    @Option(help = "Print Truffle compilation statistics at the end of a run.")
+
+    @Option(help = "Print Truffle compilation statistics at the end of a run.", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleCompilationStatistics = new OptionValue<>(false);
-    @Option(help = "Print additional more verbose Truffle compilation statistics at the end of a run.")
+
+    @Option(help = "Print additional more verbose Truffle compilation statistics at the end of a run.", type = OptionType.Debug)
     public static final OptionValue<Boolean> TruffleCompilationStatisticDetails = new OptionValue<>(false);
     // @formatter:on
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Tue Dec 16 23:37:35 2014 +0100
@@ -45,7 +45,7 @@
 
     static class Options {
         //@formatter:off
-        @Option(help = "")
+        @Option(help = "", type = OptionType.Debug)
         public static final OptionValue<Boolean> OptEarlyReadElimination = new OptionValue<>(true);
         //@formatter:on
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Tue Dec 16 23:37:35 2014 +0100
@@ -62,7 +62,7 @@
                 LoadCacheEntry identifier = new LoadCacheEntry(object, access.field());
                 ValueNode cachedValue = state.getCacheEntry(identifier);
                 if (node instanceof LoadFieldNode) {
-                    if (cachedValue != null) {
+                    if (cachedValue != null && access.stamp().isCompatible(cachedValue.stamp())) {
                         effects.replaceAtUsages(access, cachedValue);
                         addScalarAlias(access, cachedValue);
                         deleted = true;
@@ -87,7 +87,7 @@
                 ValueNode object = GraphUtil.unproxify(read.object());
                 ReadCacheEntry identifier = new ReadCacheEntry(object, read.location());
                 ValueNode cachedValue = state.getCacheEntry(identifier);
-                if (cachedValue != null) {
+                if (cachedValue != null && read.stamp().isCompatible(cachedValue.stamp())) {
                     if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
                         effects.addFixedNodeBefore(ValueAnchorNode.create((ValueNode) read.getGuard()), read);
                     }
@@ -122,7 +122,7 @@
                     ValueNode object = GraphUtil.unproxify(load.object());
                     UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity());
                     ValueNode cachedValue = state.getCacheEntry(identifier);
-                    if (cachedValue != null) {
+                    if (cachedValue != null && load.stamp().isCompatible(cachedValue.stamp())) {
                         effects.replaceAtUsages(load, cachedValue);
                         addScalarAlias(load, cachedValue);
                         deleted = true;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Tue Dec 16 23:37:35 2014 +0100
@@ -35,7 +35,7 @@
  * <ul>
  * <li><strong>Literal:</strong> A named text string. These are not indexed and should be considered
  * value objects; equality is defined based on contents. <br>
- * See {@link Source#fromText(String, String)}</li>
+ * See {@link Source#fromText(CharSequence, String)}</li>
  * <p>
  * <li><strong>File:</strong> Each file is represented as a canonical object, indexed by the
  * absolute, canonical path name of the file. File contents are <em>read lazily</em> and contents
@@ -53,7 +53,7 @@
  * <p>
  * <li><strong>Pseudo File:</strong> A literal text string that can be retrieved by name as if it
  * were a file, unlike literal sources; useful for testing. <br>
- * See {@link Source#asPseudoFile(String, String)}</li>
+ * See {@link Source#asPseudoFile(CharSequence, String)}</li>
  * </ul>
  * <p>
  * <strong>File cache:</strong>
@@ -122,27 +122,28 @@
     }
 
     /**
-     * Creates a non-canonical source from literal text.
+     * Creates a non-canonical source from literal text. If an already created literal source must
+     * be retrievable by name, use {@link #asPseudoFile(CharSequence, String)}.
      *
-     * @param code textual source code
+     * @param chars textual source code
      * @param description a note about the origin, for error messages and debugging
      * @return a newly created, non-indexed source representation
      */
-    public static Source fromText(String code, String description) {
-        assert code != null;
-        return new LiteralSource(description, code);
+    public static Source fromText(CharSequence chars, String description) {
+        assert chars != null;
+        return new LiteralSource(description, chars.toString());
     }
 
     /**
      * Creates a source whose contents will be read immediately from a URL and cached.
      *
      * @param url
-     * @param name identifies the origin, possibly useful for debugging
+     * @param description identifies the origin, possibly useful for debugging
      * @return a newly created, non-indexed source representation
      * @throws IOException if reading fails
      */
-    public static Source fromURL(URL url, String name) throws IOException {
-        return URLSource.get(url, name);
+    public static Source fromURL(URL url, String description) throws IOException {
+        return URLSource.get(url, description);
     }
 
     /**
@@ -192,12 +193,12 @@
      * Creates a source from literal text, but which acts as a file and can be retrieved by name
      * (unlike other literal sources); intended for testing.
      *
-     * @param code textual source code
+     * @param chars textual source code
      * @param pseudoFileName string to use for indexing/lookup
      * @return a newly created, source representation, canonical with respect to its name
      */
-    public static Source asPseudoFile(String code, String pseudoFileName) {
-        final Source source = new LiteralSource(pseudoFileName, code);
+    public static Source asPseudoFile(CharSequence chars, String pseudoFileName) {
+        final Source source = new LiteralSource(pseudoFileName, chars.toString());
         filePathToSource.put(pseudoFileName, new WeakReference<>(source));
         return source;
     }
@@ -212,11 +213,12 @@
     }
 
     private static String read(Reader reader) throws IOException {
+        final BufferedReader bufferedReader = new BufferedReader(reader);
         final StringBuilder builder = new StringBuilder();
         final char[] buffer = new char[1024];
 
         while (true) {
-            final int n = reader.read(buffer);
+            final int n = bufferedReader.read(buffer);
             if (n == -1) {
                 break;
             }
@@ -597,6 +599,23 @@
         }
 
         @Override
+        public int hashCode() {
+            return path.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof FileSource) {
+                FileSource other = (FileSource) obj;
+                return path.equals(other.path);
+            }
+            return false;
+        }
+
+        @Override
         protected void reset() {
             this.code = null;
         }
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java	Tue Dec 16 23:36:29 2014 +0100
+++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java	Tue Dec 16 23:37:35 2014 +0100
@@ -156,24 +156,25 @@
     }
 
     public final void copyProperties(DynamicObject fromObject, Shape ancestor) {
-        Shape fromShape = fromObject.getShape();
-        Shape toShape = getShape();
+        ShapeImpl fromShape = (ShapeImpl) fromObject.getShape();
+        ShapeImpl toShape = getShape();
         assert toShape.isRelated(ancestor);
         assert toShape.isValid();
         assert ancestor.isValid();
         for (; toShape != ancestor; toShape = toShape.getParent()) {
-            Property toProperty = toShape.getLastProperty();
-            // assumption: hidden properties won't change and don't need copying
-            if (!toProperty.isHidden()) {
-                assert fromShape.hasProperty(toProperty.getKey());
+            Transition transitionFromParent = toShape.getTransitionFromParent();
+            if (transitionFromParent instanceof Transition.AddPropertyTransition) {
+                Property toProperty = ((Transition.AddPropertyTransition) transitionFromParent).getProperty();
                 Property fromProperty = fromShape.getProperty(toProperty.getKey());
+
                 // copy only if property has a location and it's not the same as the source location
                 if (toProperty.getLocation() != null && !(toProperty.getLocation() instanceof ValueLocation) && !toProperty.getLocation().equals(fromProperty.getLocation())) {
                     toProperty.setInternal(this, fromProperty.get(fromObject, false));
                     assert toShape.isValid();
                 }
 
-                if (fromShape.getLastProperty() == fromProperty) {
+                if (fromShape.getTransitionFromParent() instanceof Transition.AddPropertyTransition &&
+                                ((Transition.AddPropertyTransition) fromShape.getTransitionFromParent()).getProperty() == fromProperty) {
                     // no property is looked up twice, so we can skip over to parent
                     fromShape = fromShape.getParent();
                 }
--- a/src/share/vm/compiler/compilerOracle.cpp	Tue Dec 16 23:36:29 2014 +0100
+++ b/src/share/vm/compiler/compilerOracle.cpp	Tue Dec 16 23:37:35 2014 +0100
@@ -397,7 +397,8 @@
   int match = MethodMatcher::Exact;
   while (name[0] == '*') {
     match |= MethodMatcher::Suffix;
-    strcpy(name, name + 1);
+    // Copy remaining string plus NUL to the beginning
+    memmove(name, name + 1, strlen(name + 1) + 1);
   }
 
   if (strcmp(name, "*") == 0) return MethodMatcher::Any;
--- a/src/share/vm/graal/graalEnv.cpp	Tue Dec 16 23:36:29 2014 +0100
+++ b/src/share/vm/graal/graalEnv.cpp	Tue Dec 16 23:37:35 2014 +0100
@@ -428,7 +428,9 @@
     if (witness != NULL) {
       return false;
     }
-    deps.log_dependency();
+    if (LogCompilation) {
+      deps.log_dependency();
+    }
   }
 
   return true;
--- a/src/share/vm/memory/threadLocalAllocBuffer.cpp	Tue Dec 16 23:36:29 2014 +0100
+++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp	Tue Dec 16 23:37:35 2014 +0100
@@ -42,6 +42,9 @@
 
 void ThreadLocalAllocBuffer::clear_before_allocation() {
   _slow_refill_waste += (unsigned)remaining();
+  // In debug mode we expect the storage above top to be uninitialized
+  // or filled with a padding object.
+  assert(top() == NULL || *(intptr_t*)top() != 0, "overzeroing detected");
   make_parsable(true);   // also retire the TLAB
 }