changeset 14850:fbae9be45c95

Merge.
author Josef Eisl <josef.eisl@jku.at>
date Wed, 26 Mar 2014 20:44:11 +0100
parents 97a0878202c2 (current diff) 5823c399e28f (diff)
children a5373295d454
files graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRGenerator.java graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRGenerator.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRGenerator.java graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeMappableLIRGenerator.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java mx/projects
diffstat 175 files changed, 8439 insertions(+), 1344 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Mar 26 17:02:45 2014 +0100
+++ b/.hgtags	Wed Mar 26 20:44:11 2014 +0100
@@ -408,3 +408,4 @@
 050a626a88951140df874f7b163e304d07b6c296 jdk9-b01
 b188446de75bda5fc52d102cddf242c3ef5ecbdf jdk9-b02
 b2fee789d23f3cdabb3db4e51af43038e5692d3a jdk9-b03
+483d05bf77a7c2a762aca1e06c4191bc06647176 graal-0.2
--- a/CHANGELOG.md	Wed Mar 26 17:02:45 2014 +0100
+++ b/CHANGELOG.md	Wed Mar 26 20:44:11 2014 +0100
@@ -2,30 +2,42 @@
 
 ## `tip`
 ### Graal
-* New methods for querying memory usage of individual objects and object graphs in Graal API (MetaAccessProvider#getMemorySize, MetaUtil#getMemorySizeRecursive).
-* New (tested) invariant that equality comparisons for JavaType/JavaMethod/JavaField values use .equals() instead of '=='.
+* ...
+### Truffle
+* ...
+
+## Version 0.2
+25-Mar-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.2)
+
+### Graal
+* Use HotSpot stubs for certain array copy operations.
+* New methods for querying memory usage of individual objects and object graphs in Graal API (`MetaAccessProvider#getMemorySize`, `MetaUtil#getMemorySizeRecursive`).
+* Added tiered configuration (C1 + Graal).
+* Initial security model for Graal [GRAAL-22](https://bugs.openjdk.java.net/browse/GRAAL-22).
+* New (tested) invariant that equality comparisons for `JavaType`/`JavaMethod`/`JavaField` values use `.equals()` instead of `==`.
 * Made graph caching compilation-local.
+* Added AllocSpy tool for analyzing allocation in Graal using the [Java Allocation Instrumenter](https://code.google.com/p/java-allocation-instrumenter/).
+* Initial support for memory arithmetic operations on x86
 
 ### Truffle
-* New API TruffleRuntime#createCallNode to create call nodes and to give the runtime system control over its implementation.
-* New API RootNode#getCachedCallNodes to get a weak set of CallNodes that have registered to call the RootNode.
-* New API to split the AST of a call-site context sensitively. CallNode#split, CallNode#isSplittable, CallNode#getSplitCallTarget, CallNode#getCurrentCallTarget, RootNode#isSplittable, RootNode#split.
-* New API to inline a call-site into the call-graph. CallNode#isInlinable, CallNode#inline, CallNode#isInlined.
-* New API for the runtime environment to register CallTargets as caller to the RootNode. CallNode#registerCallTarget.
-* Improved API for counting nodes in Truffle ASTS. NodeUtil#countNodes can be used with a NodeFilter filter Nodes.
-* New API to declare the cost of a Node for use in runtime environment specific heuristics. See NodeCost, Node#getCost() and NodeInfo#cost().
-* Removed old API for NodeInfo#Kind and NodeInfo#kind(). As a replacement the new Node cost API can be used.
-* Changed Node#replace reason parameter type to CharSequence (to allow for lazy string building)
-* Deprecated Node#adoptChild and Node#adoptChild, no longer needed in node constructor
-* New Node#insert method for inserting new nodes into the tree (formerly adoptChild)
-* New Node#adoptChildren() helper method that adopts all (direct and indirect) children of a node
-* New API Node#atomic for atomic tree operations
-* Made Node#replace thread-safe
-
+* New API `TruffleRuntime#createCallNode` to create call nodes and to give the runtime system control over its implementation.
+* New API `RootNode#getCachedCallNodes` to get a weak set of `CallNode`s that have registered to call the `RootNode`.
+* New API to split the AST of a call-site context sensitively. `CallNode#split`, `CallNode#isSplittable`, `CallNode#getSplitCallTarget`, `CallNode#getCurrentCallTarget`, `RootNode#isSplittable`, `RootNode#split`.
+* New API to inline a call-site into the call-graph. `CallNode#isInlinable`, `CallNode#inline`, `CallNode#isInlined`.
+* New API for the runtime environment to register `CallTarget`s as caller to the `RootNode`. `CallNode#registerCallTarget`.
+* Improved API for counting nodes in Truffle ASTs. `NodeUtil#countNodes` can be used with a `NodeFilter`.
+* New API to declare the cost of a Node for use in runtime environment specific heuristics. See `NodeCost`, `Node#getCost` and `NodeInfo#cost`.
+* Removed old API for `NodeInfo#Kind` and `NodeInfo#kind`. As a replacement the new `NodeCost` API can be used.
+* Changed `Node#replace` reason parameter type to `CharSequence` (to enable lazy string building)
+* Deprecated `Node#adoptChild` and `Node#adoptChild`, no longer needed in node constructor
+* New `Node#insert` method for inserting new nodes into the tree (formerly `adoptChild`)
+* New `Node#adoptChildren` helper method that adopts all (direct and indirect) children of a node
+* New API `Node#atomic` for atomic tree operations
+* Made `Node#replace` thread-safe
 
 
 ## Version 0.1
-5-Feb-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/b124e22eb772)
+5-Feb-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.1)
 
 ### Graal
 
--- a/README.md	Wed Mar 26 17:02:45 2014 +0100
+++ b/README.md	Wed Mar 26 20:44:11 2014 +0100
@@ -23,10 +23,11 @@
    Compilation with Graal is only done by explicit requests to the
    Graal API. This is how Truffle uses Graal.
    
-2. The 'graal' configuration is a VM where all compilation is performed
-   by Graal and no other compilers are built into the VM binary. This
-   VM will bootstrap Graal itself at startup unless the -XX:-BootstrapGraal
-   VM option is given.   
+2. The 'graal' configuration is a VM where normal compilations are performed
+   by Graal. This VM will bootstrap Graal itself at startup unless the
+   -XX:-BootstrapGraal. Note that if tiered compilation is enabled, Graal
+   will be used at the last tier while C1 will be used for the first compiled
+   tiers.
 
 Unless you use the --vm option with the build command, you will be presented
 with a dialogue to choose one of the above VM configurations for the build
@@ -78,5 +79,3 @@
 
 These configurations aim to match as closely as possible the
 VM(s) included in the OpenJDK binaries one can download.
- No newline at end of file
-
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Mar 26 20:44:11 2014 +0100
@@ -160,68 +160,79 @@
         public abstract void emit(TargetDescription target, ByteBuffer buffer);
     }
 
+    public abstract static class ConstantData extends Data {
+
+        private final Constant constant;
+
+        protected ConstantData(Constant constant, int alignment) {
+            super(alignment);
+            this.constant = constant;
+        }
+
+        public Constant getConstant() {
+            return constant;
+        }
+    }
+
     /**
      * Represents a Java primitive value used in a {@link DataPatch}. This implementation uses
      * {@link Kind#getByteCount()} bytes to encode each value.
      */
-    public static final class PrimitiveData extends Data {
-
-        public final Constant constant;
+    public static final class PrimitiveData extends ConstantData {
 
         public PrimitiveData(Constant constant, int alignment) {
-            super(alignment);
+            super(constant, alignment);
             assert constant.getKind().isPrimitive();
-            this.constant = constant;
         }
 
         @Override
         public int getSize(TargetDescription target) {
-            return constant.getKind().getByteCount();
+            return getConstant().getKind().getByteCount();
         }
 
         @Override
         public Kind getKind() {
-            return constant.getKind();
+            return getConstant().getKind();
         }
 
         @Override
         public void emit(TargetDescription target, ByteBuffer buffer) {
-            switch (constant.getKind()) {
+            switch (getConstant().getKind()) {
                 case Boolean:
-                    buffer.put(constant.asBoolean() ? (byte) 1 : (byte) 0);
+                    buffer.put(getConstant().asBoolean() ? (byte) 1 : (byte) 0);
                     break;
                 case Byte:
-                    buffer.put((byte) constant.asInt());
+                    buffer.put((byte) getConstant().asInt());
                     break;
                 case Char:
-                    buffer.putChar((char) constant.asInt());
+                    buffer.putChar((char) getConstant().asInt());
                     break;
                 case Short:
-                    buffer.putShort((short) constant.asInt());
+                    buffer.putShort((short) getConstant().asInt());
                     break;
                 case Int:
-                    buffer.putInt(constant.asInt());
+                    buffer.putInt(getConstant().asInt());
                     break;
                 case Long:
-                    buffer.putLong(constant.asLong());
+                    buffer.putLong(getConstant().asLong());
                     break;
                 case Float:
-                    buffer.putFloat(constant.asFloat());
+                    buffer.putFloat(getConstant().asFloat());
                     break;
                 case Double:
-                    buffer.putDouble(constant.asDouble());
+                    buffer.putDouble(getConstant().asDouble());
                     break;
             }
         }
 
         @Override
         public String toString() {
-            return constant.toString();
+            return getConstant().toString();
         }
 
         @Override
         public int hashCode() {
-            return constant.hashCode();
+            return getConstant().hashCode();
         }
 
         @Override
@@ -231,7 +242,7 @@
             }
             if (obj instanceof PrimitiveData) {
                 PrimitiveData other = (PrimitiveData) obj;
-                return constant.equals(other.constant);
+                return getConstant().equals(other.getConstant());
             } else {
                 return false;
             }
@@ -591,7 +602,15 @@
         addInfopoint(new Infopoint(codePos, debugInfo, reason));
     }
 
-    private void addInfopoint(Infopoint infopoint) {
+    /**
+     * Records a custom infopoint in the code section.
+     * 
+     * Compiler implementations can use this method to record non-standard infopoints, which are not
+     * handled by the dedicated methods like {@link #recordCall}.
+     * 
+     * @param infopoint the infopoint to record, usually a derived class from {@link Infopoint}
+     */
+    public void addInfopoint(Infopoint infopoint) {
         // The infopoints list must always be sorted
         if (!infopoints.isEmpty() && infopoints.get(infopoints.size() - 1).pcOffset >= infopoint.pcOffset) {
             // This re-sorting should be very rare
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Wed Mar 26 20:44:11 2014 +0100
@@ -1213,6 +1213,7 @@
         emitByte(0xD0 | encode);
     }
 
+    @Override
     public final void ensureUniquePC() {
         nop();
     }
@@ -1669,6 +1670,13 @@
         emitInt(imm32);
     }
 
+    public final void testl(AMD64Address dst, int imm32) {
+        prefixq(dst);
+        emitByte(0xF7);
+        emitOperandHelper(0, dst);
+        emitInt(imm32);
+    }
+
     public final void testl(Register dst, Register src) {
         prefixAndEncode(dst.encoding, src.encoding);
         emitArith(0x85, 0xC0, dst, src);
@@ -2064,6 +2072,13 @@
         emitOperandHelper(dst, src);
     }
 
+    public final void cmpq(AMD64Address dst, int imm32) {
+        prefixq(dst);
+        emitByte(0x81);
+        emitOperandHelper(7, dst);
+        emitInt(imm32);
+    }
+
     public final void cmpq(Register dst, int imm32) {
         prefixqAndEncode(dst.encoding);
         emitArith(0x81, 0xF8, dst, imm32);
@@ -2410,6 +2425,13 @@
         emitOperandHelper(dst, src);
     }
 
+    public final void testq(AMD64Address dst, int imm32) {
+        prefixq(dst);
+        emitByte(0xF7);
+        emitOperandHelper(0, dst);
+        emitInt(imm32);
+    }
+
     public final void xorq(Register dst, int imm32) {
         prefixqAndEncode(dst.encoding);
         emitArith(0x81, 0xF0, dst, imm32);
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Wed Mar 26 20:44:11 2014 +0100
@@ -68,6 +68,11 @@
         return null;
     }
 
+    @Override
+    public final void ensureUniquePC() {
+        throw GraalInternalError.unimplemented();
+    }
+
     public final void undefined(String str) {
         emitString("undefined operation " + str);
     }
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Wed Mar 26 20:44:11 2014 +0100
@@ -696,6 +696,11 @@
     }
 
     @Override
+    public final void ensureUniquePC() {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
     public void jmp(Label l) {
         String str = nameOf(l);
         bra(str);
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Wed Mar 26 20:44:11 2014 +0100
@@ -74,6 +74,7 @@
         return Placeholder;
     }
 
+    @Override
     public final void ensureUniquePC() {
         new Nop().emit(this);
     }
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java	Wed Mar 26 20:44:11 2014 +0100
@@ -183,4 +183,9 @@
      * Returns a target specific placeholder address that can be used for code patching.
      */
     public abstract AbstractAddress getPlaceholder();
+
+    /**
+     * Emits a NOP instruction to advance the current PC.
+     */
+    public abstract void ensureUniquePC();
 }
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Wed Mar 26 20:44:11 2014 +0100
@@ -771,7 +771,7 @@
             if (!currentBlock.jsrScope.isEmpty()) {
                 sb.append(' ').append(currentBlock.jsrScope);
             }
-            Debug.log(sb.toString());
+            Debug.log("%s", sb);
         }
     }
 
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -41,6 +41,7 @@
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryCommutative;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryMemory;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegConst;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegReg;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegStack;
@@ -48,7 +49,9 @@
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivRemOp;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.FPDivRemOp;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary1Op;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2MemoryOp;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2Op;
+import com.oracle.graal.lir.amd64.AMD64Compare.CompareMemoryOp;
 import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
@@ -58,6 +61,7 @@
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaOp;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MembarOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
@@ -327,10 +331,46 @@
         }
     }
 
+    protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue left, Value right, LIRFrameState state) {
+        assert kind == right.getKind();
+        switch (kind) {
+            case Int:
+                append(new CompareMemoryOp(ICMP, left, right, state));
+                break;
+            case Long:
+                append(new CompareMemoryOp(LCMP, left, right, state));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    protected void emitCompareRegMemoryOp(Kind kind, Value left, AMD64AddressValue right, LIRFrameState state) {
+        switch (kind) {
+            case Int:
+                append(new CompareMemoryOp(ICMP, left, right, state));
+                break;
+            case Long:
+                append(new CompareMemoryOp(LCMP, left, right, state));
+                break;
+            case Object:
+                append(new CompareMemoryOp(ACMP, left, right, state));
+                break;
+            case Float:
+                append(new CompareMemoryOp(FCMP, left, right, state));
+                break;
+            case Double:
+                append(new CompareMemoryOp(DCMP, left, right, state));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     /**
      * This method emits the compare instruction, and may reorder the operands. It returns true if
      * it did so.
-     * 
+     *
      * @param a the left operand of the comparison
      * @param b the right operand of the comparison
      * @return true if the left and right operands were switched, false otherwise
@@ -492,6 +532,27 @@
         }
     }
 
+    protected Value emitBinaryMemory(AMD64Arithmetic op, Kind kind, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) {
+        Variable result = newVariable(a.getKind());
+        append(new BinaryMemory(op, kind, result, a, location, state));
+        return result;
+    }
+
+    protected Value emitConvert2MemoryOp(PlatformKind kind, AMD64Arithmetic op, AMD64AddressValue address, LIRFrameState state) {
+        Variable result = newVariable(kind);
+        append(new Unary2MemoryOp(op, result, address, state));
+        return result;
+    }
+
+    protected Value emitZeroExtendMemory(Kind memoryKind, int resultBits, AMD64AddressValue address, LIRFrameState state) {
+        assert memoryKind.isUnsigned();
+        // Issue a zero extending load of the proper bit size and set the result to
+        // the proper kind.
+        Variable result = newVariable(resultBits == 32 ? Kind.Int : Kind.Long);
+        append(new LoadOp(memoryKind, result, address, state));
+        return result;
+    }
+
     private void emitDivRem(AMD64Arithmetic op, Value a, Value b, LIRFrameState state) {
         AllocatableValue rax = AMD64.rax.asValue(a.getPlatformKind());
         emitMove(rax, a);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,482 @@
+/*
+ * 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.compiler.amd64;
+
+import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*;
+import static com.oracle.graal.nodes.ConstantNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class AMD64MemoryPeephole implements MemoryArithmeticLIRLowerer {
+    protected final AMD64NodeLIRGenerator gen;
+    protected List<ValueNode> deferredNodes;
+
+    protected AMD64MemoryPeephole(AMD64NodeLIRGenerator gen) {
+        this.gen = gen;
+    }
+
+    public Value setResult(ValueNode x, Value operand) {
+        return gen.setResult(x, operand);
+    }
+
+    @Override
+    public boolean memoryPeephole(Access access, MemoryArithmeticLIRLowerable operation, List<ValueNode> deferred) {
+        this.deferredNodes = deferred;
+        boolean result = operation.generate(this, access);
+        if (result) {
+            Debug.log("merge %s %s with %1s %s %s", access, access.asNode().stamp(), operation, result, access.asNode().graph().method());
+        } else {
+            Debug.log("can't merge %s %s with %1s", access, access.asNode().stamp(), operation);
+        }
+        this.deferredNodes = null;
+        return result;
+    }
+
+    protected LIRFrameState getState(Access access) {
+        if (access instanceof DeoptimizingNode) {
+            return gen.state((DeoptimizingNode) access);
+        }
+        return null;
+    }
+
+    protected AMD64AddressValue makeAddress(Access access) {
+        return (AMD64AddressValue) access.nullCheckLocation().generateAddress(gen, gen.operand(access.object()));
+    }
+
+    protected Value emitBinaryMemory(AMD64Arithmetic op, boolean commutative, ValueNode x, ValueNode y, Access access) {
+        ValueNode other = x;
+        if (other == access) {
+            if (commutative) {
+                other = y;
+            } else {
+                return null;
+            }
+        }
+        ensureEvaluated(other);
+        return gen.getLIRGenerator().emitBinaryMemory(op, access.nullCheckLocation().getValueKind(), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access));
+    }
+
+    /**
+     * Constants with multiple users need to be evaluated in the right location so that later users
+     * can pick up the operand. Make sure that happens when it needs to.
+     */
+    protected void ensureEvaluated(ValueNode node) {
+        evaluateDeferred(node);
+        evaluateDeferred();
+    }
+
+    protected void evaluateDeferred(ValueNode node) {
+        // Ensure the other input value has a generated value.
+        if (ConstantNodeRecordsUsages) {
+            if (!gen.hasOperand(node)) {
+                assert node instanceof ConstantNode : node;
+                ((ConstantNode) node).generate(gen);
+            }
+        }
+    }
+
+    protected void evaluateDeferred() {
+        if (deferredNodes != null) {
+            for (ValueNode node : deferredNodes) {
+                evaluateDeferred(node);
+            }
+        }
+    }
+
+    protected Value emitConvert2MemoryOp(PlatformKind kind, AMD64Arithmetic op, Access access) {
+        AMD64AddressValue address = makeAddress(access);
+        LIRFrameState state = getState(access);
+        evaluateDeferred();
+        return gen.getLIRGenerator().emitConvert2MemoryOp(kind, op, address, state);
+    }
+
+    @Override
+    public Value emitAddMemory(ValueNode x, ValueNode y, Access access) {
+        switch (access.nullCheckLocation().getValueKind()) {
+            case Int:
+                return emitBinaryMemory(IADD, true, x, y, access);
+            case Long:
+                return emitBinaryMemory(LADD, true, x, y, access);
+            case Float:
+                return emitBinaryMemory(FADD, true, x, y, access);
+            case Double:
+                return emitBinaryMemory(DADD, true, x, y, access);
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public Value emitSubMemory(ValueNode x, ValueNode y, Access access) {
+        switch (access.nullCheckLocation().getValueKind()) {
+            case Int:
+                return emitBinaryMemory(ISUB, false, x, y, access);
+            case Long:
+                return emitBinaryMemory(LSUB, false, x, y, access);
+            case Float:
+                return emitBinaryMemory(FSUB, false, x, y, access);
+            case Double:
+                return emitBinaryMemory(DSUB, false, x, y, access);
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public Value emitMulMemory(ValueNode x, ValueNode y, Access access) {
+        switch (access.nullCheckLocation().getValueKind()) {
+            case Int:
+                return emitBinaryMemory(IMUL, true, x, y, access);
+            case Long:
+                return emitBinaryMemory(LMUL, true, x, y, access);
+            case Float:
+                return emitBinaryMemory(FMUL, true, x, y, access);
+            case Double:
+                return emitBinaryMemory(DMUL, true, x, y, access);
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public Value emitDivMemory(ValueNode x, ValueNode y, Access access) {
+        return null;
+    }
+
+    @Override
+    public Value emitRemMemory(ValueNode x, ValueNode y, Access access) {
+        return null;
+    }
+
+    @Override
+    public Value emitAndMemory(ValueNode x, ValueNode y, Access access) {
+        Kind kind = access.nullCheckLocation().getValueKind();
+        switch (kind) {
+            case Int:
+                return emitBinaryMemory(IAND, true, x, y, access);
+            case Long:
+                return emitBinaryMemory(LAND, true, x, y, access);
+            case Short: {
+                ValueNode other = x == access ? y : x;
+                Constant constant = other instanceof ConstantNode ? ((ConstantNode) other).asConstant() : null;
+                if (constant != null && constant.asInt() == IntegerStamp.defaultMask(kind.getBitCount())) {
+                    // Convert to unsigned load
+                    ensureEvaluated(other);
+                    return emitZeroExtendMemory(16, 32, access);
+                }
+                return null;
+            }
+            case Byte: {
+                if (OptFoldMemory.getValue()) {
+                    return null;
+                }
+                ValueNode other = x == access ? y : x;
+                Constant constant = other instanceof ConstantNode ? ((ConstantNode) other).asConstant() : null;
+                if (constant != null && constant.asInt() == IntegerStamp.defaultMask(kind.getBitCount())) {
+                    // Convert to unsigned load
+                    ensureEvaluated(other);
+                    return emitConvert2MemoryOp(Kind.Int, MOV_B2UI, access);
+                }
+                return null;
+            }
+
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public Value emitOrMemory(ValueNode x, ValueNode y, Access access) {
+        switch (access.nullCheckLocation().getValueKind()) {
+            case Int:
+                return emitBinaryMemory(IOR, true, x, y, access);
+            case Long:
+                return emitBinaryMemory(LOR, true, x, y, access);
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public Value emitXorMemory(ValueNode x, ValueNode y, Access access) {
+        switch (access.nullCheckLocation().getValueKind()) {
+            case Int:
+                return emitBinaryMemory(IXOR, true, x, y, access);
+            case Long:
+                return emitBinaryMemory(LXOR, true, x, y, access);
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public Value emitReinterpretMemory(Stamp stamp, Access access) {
+        PlatformKind to = gen.getLIRGenerator().getPlatformKind(stamp);
+        Kind from = access.nullCheckLocation().getValueKind();
+        assert to != from : "should have been eliminated";
+
+        /*
+         * Conversions between integer to floating point types require moves between CPU and FPU
+         * registers.
+         */
+        switch ((Kind) to) {
+            case Int:
+                switch (from) {
+                    case Float:
+                        return emitConvert2MemoryOp(to, MOV_F2I, access);
+                }
+                break;
+            case Long:
+                switch (from) {
+                    case Double:
+                        return emitConvert2MemoryOp(to, MOV_D2L, access);
+                }
+                break;
+            case Float:
+                switch (from) {
+                    case Int:
+                        return emitConvert2MemoryOp(to, MOV_I2F, access);
+                }
+                break;
+            case Double:
+                switch (from) {
+                    case Long:
+                        return emitConvert2MemoryOp(to, MOV_L2D, access);
+                }
+                break;
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public Value emitFloatConvertMemory(FloatConvert op, Access access) {
+        switch (op) {
+            case D2F:
+                return emitConvert2MemoryOp(Kind.Float, D2F, access);
+            case D2I:
+                return emitConvert2MemoryOp(Kind.Int, D2I, access);
+            case D2L:
+                return emitConvert2MemoryOp(Kind.Long, D2L, access);
+            case F2D:
+                return emitConvert2MemoryOp(Kind.Double, F2D, access);
+            case F2I:
+                return emitConvert2MemoryOp(Kind.Int, F2I, access);
+            case F2L:
+                return emitConvert2MemoryOp(Kind.Long, F2L, access);
+            case I2D:
+                return emitConvert2MemoryOp(Kind.Double, I2D, access);
+            case I2F:
+                return emitConvert2MemoryOp(Kind.Float, I2F, access);
+            case L2D:
+                return emitConvert2MemoryOp(Kind.Double, L2D, access);
+            case L2F:
+                return emitConvert2MemoryOp(Kind.Float, L2F, access);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Value emitSignExtendMemory(Access access, int fromBits, int toBits) {
+        assert fromBits <= toBits && toBits <= 64;
+        if (fromBits == toBits) {
+            return null;
+        } else if (toBits > 32) {
+            // sign extend to 64 bits
+            switch (fromBits) {
+                case 8:
+                    return emitConvert2MemoryOp(Kind.Long, B2L, access);
+                case 16:
+                    return emitConvert2MemoryOp(Kind.Long, S2L, access);
+                case 32:
+                    return emitConvert2MemoryOp(Kind.Long, I2L, access);
+                default:
+                    throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
+            }
+        } else {
+
+            // sign extend to 32 bits (smaller values are internally represented as 32 bit values)
+            switch (fromBits) {
+                case 8:
+                    return emitConvert2MemoryOp(Kind.Int, B2I, access);
+                case 16:
+                    return emitConvert2MemoryOp(Kind.Int, S2I, access);
+                case 32:
+                    return null;
+                default:
+                    throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
+            }
+        }
+    }
+
+    @Override
+    public Value emitNarrowMemory(int resultBits, Access access) {
+        // TODO
+        return null;
+    }
+
+    @Override
+    public Value emitZeroExtendMemory(int inputBits, int resultBits, Access access) {
+        assert resultBits == 32 || resultBits == 64;
+        Kind memoryKind = access.nullCheckLocation().getValueKind();
+        if (memoryKind.getBitCount() != inputBits && !memoryKind.isUnsigned()) {
+            // The memory being read from is signed and smaller than the result size so
+            // this is a sign extension to inputBits followed by a zero extension to resultBits
+            // which can't be expressed in a memory operation.
+            return null;
+        }
+        if (memoryKind == Kind.Short) {
+            memoryKind = Kind.Char;
+        }
+        evaluateDeferred();
+        return gen.getLIRGenerator().emitZeroExtendMemory(memoryKind, resultBits, makeAddress(access), getState(access));
+    }
+
+    public boolean emitIfMemory(IfNode x, Access access) {
+        return emitBranchMemory(x.condition(), access, gen.getLIRBlock(x.trueSuccessor()), gen.getLIRBlock(x.falseSuccessor()), x.probability(x.trueSuccessor()));
+    }
+
+    private boolean emitBranchMemory(LogicNode node, Access access, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        if (node instanceof IsNullNode) {
+            // can't do anything interesting.
+            return false;
+        } else if (node instanceof CompareNode) {
+            CompareNode compare = (CompareNode) node;
+            return emitCompareBranchMemory(compare, access, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+        } else if (node instanceof LogicConstantNode) {
+            return false;
+        } else if (node instanceof IntegerTestNode) {
+            return emitIntegerTestBranchMemory((IntegerTestNode) node, access, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+        } else {
+            throw GraalInternalError.unimplemented(node.toString());
+        }
+    }
+
+    public boolean emitCompareBranchMemory(CompareNode compare, Access access, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        return emitCompareBranchMemory(compare.x(), compare.y(), access, compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability);
+    }
+
+    public boolean emitIntegerTestBranchMemory(IntegerTestNode test, Access access, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        return emitIntegerTestBranchMemory(test.x(), test.y(), access, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+    }
+
+    private boolean emitIntegerTestBranchMemory(ValueNode left, ValueNode right, Access access, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) {
+        assert left == access || right == access;
+        ValueNode other = left == access ? right : left;
+        Kind kind = access.nullCheckLocation().getValueKind();
+        if (other.isConstant()) {
+            Constant constant = other.asConstant();
+            if (kind == Kind.Long && !NumUtil.isInt(constant.asLong())) {
+                // Only imm32 as long
+                return false;
+            }
+            ensureEvaluated(other);
+            gen.append(new AMD64TestMemoryOp(makeAddress(access), constant, getState(access)));
+        } else {
+            evaluateDeferred();
+            gen.append(new AMD64TestMemoryOp(makeAddress(access), gen.operand(other), getState(access)));
+        }
+
+        gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability));
+        return true;
+    }
+
+    protected boolean emitCompareBranchMemory(ValueNode left, ValueNode right, Access access, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel,
+                    double trueLabelProbability) {
+        assert left == access || right == access;
+        ValueNode other = left == access ? right : left;
+        Kind kind = access.nullCheckLocation().getValueKind();
+        boolean mirrored = false;
+
+        if (other.isConstant()) {
+            Constant constant = other.asConstant();
+            if (kind == Kind.Long && !NumUtil.isInt(constant.asLong())) {
+                // Only imm32 as long
+                return false;
+            }
+            if (kind.isNumericFloat()) {
+                Debug.log("Skipping constant compares for float kinds");
+                return false;
+            }
+            if (kind == Kind.Object) {
+                if (!access.isCompressible() && !constant.isNull()) {
+                    Debug.log("Skipping constant compares for Object kinds");
+                    return false;
+                }
+            }
+            if (kind != kind.getStackKind()) {
+                Debug.log("Skipping constant compares for stack kinds");
+                return false;
+            }
+            ensureEvaluated(other);
+            gen.getLIRGenerator().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access));
+            mirrored = right == access;
+        } else {
+            if (kind != kind.getStackKind()) {
+                // Register compares only work for stack kinds
+                Debug.log("Register compares only work for stack kinds");
+                return false;
+            } else if (kind == Kind.Object) {
+                // Can't compare against objects since they require encode/decode
+                Debug.log("Skipping compares for Object kinds");
+                return false;
+            }
+
+            evaluateDeferred();
+            gen.getLIRGenerator().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access));
+            mirrored = left == access;
+        }
+
+        Condition finalCondition = mirrored ? cond.mirror() : cond;
+        switch (kind.getStackKind()) {
+            case Long:
+            case Int:
+            case Object:
+                gen.append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
+                return true;
+            case Float:
+            case Double:
+                gen.append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
+                return true;
+            default:
+                throw GraalInternalError.shouldNotReachHere("" + kind.getStackKind());
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -31,6 +31,7 @@
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
 
 public abstract class AMD64NodeLIRGenerator extends NodeLIRGenerator {
 
@@ -38,6 +39,17 @@
         super(graph, res, gen);
     }
 
+    protected MemoryArithmeticLIRLowerer memoryPeephole;
+
+    @Override
+    public MemoryArithmeticLIRLowerer getMemoryLowerer() {
+        if (memoryPeephole == null) {
+            // Use the generic one
+            memoryPeephole = new AMD64MemoryPeephole(this);
+        }
+        return memoryPeephole;
+    }
+
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
         AllocatableValue targetAddress = AMD64.rax.asValue();
@@ -93,4 +105,9 @@
     public void visitInfopointNode(InfopointNode i) {
         append(new InfopointOp(stateFor(i.getState()), i.reason));
     }
+
+    @Override
+    public AMD64LIRGenerator getLIRGenerator() {
+        return (AMD64LIRGenerator) gen;
+    }
 }
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -113,6 +113,10 @@
         }
     }
 
+    public void emitData(AllocatableValue dst, byte[] data) {
+        throw GraalInternalError.unimplemented();
+    }
+
     public HSAILAddressValue asAddressValue(Value address) {
         if (address instanceof HSAILAddressValue) {
             return (HSAILAddressValue) address;
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ObjectPTXTest.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ObjectPTXTest.java	Wed Mar 26 20:44:11 2014 +0100
@@ -66,6 +66,7 @@
         return a.i + i;
     }
 
+    @Ignore("com.oracle.graal.graph.GraalInternalError: should not reach here: unhandled register type v3|z")
     @Test
     public void test2() {
         A a = new A();
@@ -79,6 +80,7 @@
         return a.z;
     }
 
+    @Ignore("[CUDA] Check for malformed PTX kernel or incorrect PTX compilation options")
     @Test
     public void test3() {
         for (byte b : new byte[]{Byte.MIN_VALUE, -10, 0, 1, 2, 10, Byte.MAX_VALUE}) {
@@ -92,6 +94,7 @@
         return a.b + b;
     }
 
+    @Ignore("com.oracle.graal.graph.GraalInternalError: should not reach here: unhandled register type v5|s")
     @Test
     public void test4() {
         for (short s : new short[]{Short.MIN_VALUE, -10, 0, 1, 2, 10, Short.MAX_VALUE}) {
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -167,6 +167,11 @@
     }
 
     @Override
+    public void emitData(AllocatableValue dst, byte[] data) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
     public PTXAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
         long finalDisp = displacement;
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -130,6 +130,11 @@
     }
 
     @Override
+    public void emitData(AllocatableValue dst, byte[] data) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
     public SPARCAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
         long finalDisp = displacement;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Wed Mar 26 20:44:11 2014 +0100
@@ -321,6 +321,7 @@
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+        canonicalizer.apply(graph, context);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
         if (loopPeeling) {
             new LoopTransformHighPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Wed Mar 26 20:44:11 2014 +0100
@@ -158,6 +158,7 @@
         new VerifyUsageWithEquals(JavaType.class).apply(graph, context);
         new VerifyUsageWithEquals(JavaMethod.class).apply(graph, context);
         new VerifyUsageWithEquals(JavaField.class).apply(graph, context);
+        new VerifyDebugUsage().apply(graph, context);
     }
 
     private static boolean matches(String[] filters, String s) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfReorderTest.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.*;
+
+public class IfReorderTest extends GraalCompilerTest {
+
+    private static Object fieldA = Integer.class;
+    private static Object fieldB = Double.class;
+
+    @Test
+    public void test1() {
+        test("test1Snippet", new ArrayList<>());
+    }
+
+    public static Object test1Snippet(Object o) {
+        /*
+         * Serializable and List are not mutually exclusive, so these two IFs should never be
+         * reordered.
+         */
+        if (branchProbability(0.1, o instanceof Serializable)) {
+            return fieldA;
+        }
+        if (branchProbability(0.9, o instanceof List)) {
+            return fieldB;
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class IntegerEqualsCanonicalizerTest extends GraalCompilerTest {
+
+    @Test
+    public void testShiftEquals() {
+        /*
+         * tests the canonicalization of (x >>> const) == 0 to x |test| (-1 << const)
+         */
+        test("testShiftEqualsSnippet", "testShiftEqualsReference");
+    }
+
+    @SuppressWarnings("unused") private static int field;
+
+    public static void testShiftEqualsSnippet(int x, int[] array, int y) {
+        // optimize
+        field = (x >>> 10) == 0 ? 1 : 0;
+        field = (array.length >> 10) == 0 ? 1 : 0;
+        field = (x << 10) == 0 ? 1 : 0;
+        // don't optimize
+        field = (x >> 10) == 0 ? 1 : 0;
+        field = (x >>> y) == 0 ? 1 : 0;
+        field = (x >> y) == 0 ? 1 : 0;
+        field = (x << y) == 0 ? 1 : 0;
+        field = (x >>> y) == 1 ? 1 : 0;
+        field = (x >> y) == 1 ? 1 : 0;
+        field = (x << y) == 1 ? 1 : 0;
+    }
+
+    public static void testShiftEqualsReference(int x, int[] array, int y) {
+        field = (x & 0xfffffc00) == 0 ? 1 : 0;
+        field = (array.length & 0xfffffc00) == 0 ? 1 : 0;
+        field = (x & 0x3fffff) == 0 ? 1 : 0;
+        // don't optimize signed right shifts
+        field = (x >> 10) == 0 ? 1 : 0;
+        // don't optimize no-constant shift amounts
+        field = (x >>> y) == 0 ? 1 : 0;
+        field = (x >> y) == 0 ? 1 : 0;
+        field = (x << y) == 0 ? 1 : 0;
+        // don't optimize non-zero comparisons
+        field = (x >>> y) == 1 ? 1 : 0;
+        field = (x >> y) == 1 ? 1 : 0;
+        field = (x << y) == 1 ? 1 : 0;
+    }
+
+    @Test
+    public void testCompare() {
+        test("testCompareSnippet", "testCompareReference");
+    }
+
+    public static void testCompareSnippet(int x, int y, int[] array1, int[] array2) {
+        int tempX = x;
+        int array1Length = array1.length;
+        int array2Length = array2.length;
+        // optimize
+        field = x == tempX ? 1 : 0;
+        field = x != tempX ? 1 : 0;
+        field = array1Length != (-1 - array2Length) ? 1 : 0;
+        field = array1Length == (-1 - array2Length) ? 1 : 0;
+        // don't optimize
+        field = x == y ? 1 : 0;
+        field = array1Length == array2Length ? 1 : 0;
+        field = array1Length == (-array2Length) ? 1 : 0;
+    }
+
+    public static void testCompareReference(int x, int y, int[] array1, int[] array2) {
+        int array1Length = array1.length;
+        int array2Length = array2.length;
+        // optimize
+        field = 1;
+        field = 0;
+        field = 1;
+        field = 0;
+        // don't optimize (overlapping value ranges)
+        field = x == y ? 1 : 0;
+        field = array1Length == array2Length ? 1 : 0;
+        field = array1Length == (-array2Length) ? 1 : 0;
+    }
+
+    private void test(String snippet, String referenceSnippet) {
+        StructuredGraph graph = getCanonicalizedGraph(snippet);
+        StructuredGraph referenceGraph = getCanonicalizedGraph(referenceSnippet);
+        assertEquals(referenceGraph, graph);
+    }
+
+    private StructuredGraph getCanonicalizedGraph(String snippet) {
+        StructuredGraph graph = parse(snippet);
+        new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders(), null));
+        for (FrameState state : graph.getNodes(FrameState.class).snapshot()) {
+            state.replaceAtUsages(null);
+            state.safeDelete();
+        }
+        return graph;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryArithmeticTest.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,4333 @@
+/*
+ * 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.compiler.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+
+public class MemoryArithmeticTest extends GraalCompilerTest {
+
+    @Override
+    protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) {
+        return super.getCode(method, graph, true);
+    }
+
+    /**
+     * Called before a test is executed.
+     */
+    @Override
+    protected void before(Method method) {
+        // don't let any null exception tracking change the generated code.
+        getMetaAccess().lookupJavaMethod(method).reprofile();
+    }
+
+    /**
+     * A dummy field used by some tests to create side effects.
+     */
+    protected static int count;
+
+    static class FieldObject {
+        boolean booleanValue;
+        byte byteValue;
+        short shortValue;
+        char charValue;
+        int intValue;
+        float floatValue;
+        long longValue;
+        double doubleValue;
+        Object objectValue;
+    }
+
+    static FieldObject maxObject = new FieldObject();
+    static FieldObject minObject;
+
+    static final boolean booleanTestValue1 = false;
+    static final byte byteTestValue1 = 0;
+    static final short shortTestValue1 = 0;
+    static final char charTestValue1 = 0;
+    static final int intTestValue1 = 0;
+    static final float floatTestValue1 = 0;
+    static final long longTestValue1 = 0;
+    static final double doubleTestValue1 = 0;
+    static final Object objectTestValue1 = null;
+
+    static final boolean booleanTestValue2 = true;
+    static final byte byteTestValue2 = Byte.MAX_VALUE;
+    static final short shortTestValue2 = Short.MAX_VALUE;
+    static final char charTestValue2 = Character.MAX_VALUE;
+    static final int intTestValue2 = Integer.MAX_VALUE;
+    static final float floatTestValue2 = Float.MAX_VALUE;
+    static final long longTestValue2 = Long.MAX_VALUE;
+    static final double doubleTestValue2 = Double.MAX_VALUE;
+    static final Object objectTestValue2 = "String";
+
+    static {
+        maxObject.booleanValue = true;
+        maxObject.byteValue = Byte.MAX_VALUE;
+        maxObject.shortValue = Short.MAX_VALUE;
+        maxObject.charValue = Character.MAX_VALUE;
+        maxObject.intValue = Integer.MAX_VALUE;
+        maxObject.floatValue = Float.MAX_VALUE;
+        maxObject.longValue = Long.MAX_VALUE;
+        maxObject.doubleValue = Double.MAX_VALUE;
+        maxObject.objectValue = "String";
+    }
+
+    public static Object testBooleanCompare(FieldObject f, boolean booleanValue) {
+        if (f.booleanValue == booleanValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testBooleanCompareConstant1(FieldObject f) {
+        if (f.booleanValue == booleanTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testBooleanCompareConstant2(FieldObject f) {
+        if (f.booleanValue == booleanTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testBooleanCompares() {
+        FieldObject f = new FieldObject();
+        test("testBooleanCompare", f, booleanTestValue1);
+        test("testBooleanCompareConstant1", f);
+        test("testBooleanCompareConstant2", f);
+    }
+
+    @Test
+    public void testBooleanNullCompares() {
+        test("testBooleanCompare", null, booleanTestValue1);
+    }
+
+    @Test
+    public void testBooleanNullCompares1() {
+        test("testBooleanCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testBooleanNullCompares2() {
+        test("testBooleanCompareConstant2", (Object) null);
+    }
+
+    public static Object testByteCompare(FieldObject f, byte byteValue) {
+        if (f.byteValue == byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareConstant1(FieldObject f) {
+        if (f.byteValue == byteTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareConstant2(FieldObject f) {
+        if (f.byteValue == byteTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteCompares() {
+        FieldObject f = new FieldObject();
+        test("testByteCompare", f, byteTestValue1);
+        test("testByteCompareConstant1", f);
+        test("testByteCompareConstant2", f);
+    }
+
+    @Test
+    public void testByteNullCompares() {
+        test("testByteCompare", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullCompares1() {
+        test("testByteCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullCompares2() {
+        test("testByteCompareConstant2", (Object) null);
+    }
+
+    public static Object testByteCompareLess(FieldObject f, byte byteValue) {
+        if (f.byteValue < byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareLessConstant1(FieldObject f) {
+        if (f.byteValue < byteTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareLessConstant2(FieldObject f) {
+        if (f.byteValue < byteTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testByteCompareLess", f, byteTestValue1);
+        test("testByteCompareLessConstant1", f);
+        test("testByteCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testByteNullComparesLess() {
+        test("testByteCompareLess", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullComparesLess1() {
+        test("testByteCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullComparesLess2() {
+        test("testByteCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testByteSwappedCompareLess(FieldObject f, byte byteValue) {
+        if (byteValue < f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteSwappedCompareLessConstant1(FieldObject f) {
+        if (byteTestValue1 < f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteSwappedCompareLessConstant2(FieldObject f) {
+        if (byteTestValue2 < f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteSwappedComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testByteSwappedCompareLess", f, byteTestValue1);
+        test("testByteSwappedCompareLessConstant1", f);
+        test("testByteSwappedCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesLess() {
+        test("testByteSwappedCompareLess", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesLess1() {
+        test("testByteSwappedCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesLess2() {
+        test("testByteSwappedCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testByteCompareLessEqual(FieldObject f, byte byteValue) {
+        if (f.byteValue <= byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareLessEqualConstant1(FieldObject f) {
+        if (f.byteValue <= byteTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareLessEqualConstant2(FieldObject f) {
+        if (f.byteValue <= byteTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testByteCompareLessEqual", f, byteTestValue1);
+        test("testByteCompareLessEqualConstant1", f);
+        test("testByteCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testByteNullComparesLessEqual() {
+        test("testByteCompareLessEqual", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullComparesLessEqual1() {
+        test("testByteCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullComparesLessEqual2() {
+        test("testByteCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testByteSwappedCompareLessEqual(FieldObject f, byte byteValue) {
+        if (byteValue <= f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteSwappedCompareLessEqualConstant1(FieldObject f) {
+        if (byteTestValue1 <= f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteSwappedCompareLessEqualConstant2(FieldObject f) {
+        if (byteTestValue2 <= f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteSwappedComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testByteSwappedCompareLessEqual", f, byteTestValue1);
+        test("testByteSwappedCompareLessEqualConstant1", f);
+        test("testByteSwappedCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesLessEqual() {
+        test("testByteSwappedCompareLessEqual", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesLessEqual1() {
+        test("testByteSwappedCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesLessEqual2() {
+        test("testByteSwappedCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testByteCompareGreater(FieldObject f, byte byteValue) {
+        if (f.byteValue > byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareGreaterConstant1(FieldObject f) {
+        if (f.byteValue > byteTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareGreaterConstant2(FieldObject f) {
+        if (f.byteValue > byteTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testByteCompareGreater", f, byteTestValue1);
+        test("testByteCompareGreaterConstant1", f);
+        test("testByteCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testByteNullComparesGreater() {
+        test("testByteCompareGreater", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullComparesGreater1() {
+        test("testByteCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullComparesGreater2() {
+        test("testByteCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testByteSwappedCompareGreater(FieldObject f, byte byteValue) {
+        if (byteValue > f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteSwappedCompareGreaterConstant1(FieldObject f) {
+        if (byteTestValue1 > f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteSwappedCompareGreaterConstant2(FieldObject f) {
+        if (byteTestValue2 > f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteSwappedComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testByteSwappedCompareGreater", f, byteTestValue1);
+        test("testByteSwappedCompareGreaterConstant1", f);
+        test("testByteSwappedCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesGreater() {
+        test("testByteSwappedCompareGreater", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesGreater1() {
+        test("testByteSwappedCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesGreater2() {
+        test("testByteSwappedCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testByteCompareGreaterEqual(FieldObject f, byte byteValue) {
+        if (f.byteValue >= byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareGreaterEqualConstant1(FieldObject f) {
+        if (f.byteValue >= byteTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteCompareGreaterEqualConstant2(FieldObject f) {
+        if (f.byteValue >= byteTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testByteCompareGreaterEqual", f, byteTestValue1);
+        test("testByteCompareGreaterEqualConstant1", f);
+        test("testByteCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testByteNullComparesGreaterEqual() {
+        test("testByteCompareGreaterEqual", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullComparesGreaterEqual1() {
+        test("testByteCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullComparesGreaterEqual2() {
+        test("testByteCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testByteSwappedCompareGreaterEqual(FieldObject f, byte byteValue) {
+        if (byteValue >= f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteSwappedCompareGreaterEqualConstant1(FieldObject f) {
+        if (byteTestValue1 >= f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testByteSwappedCompareGreaterEqualConstant2(FieldObject f) {
+        if (byteTestValue2 >= f.byteValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testByteSwappedComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testByteSwappedCompareGreaterEqual", f, byteTestValue1);
+        test("testByteSwappedCompareGreaterEqualConstant1", f);
+        test("testByteSwappedCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesGreaterEqual() {
+        test("testByteSwappedCompareGreaterEqual", null, byteTestValue1);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesGreaterEqual1() {
+        test("testByteSwappedCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testByteNullSwappedComparesGreaterEqual2() {
+        test("testByteSwappedCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testShortCompare(FieldObject f, short shortValue) {
+        if (f.shortValue == shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareConstant1(FieldObject f) {
+        if (f.shortValue == shortTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareConstant2(FieldObject f) {
+        if (f.shortValue == shortTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortCompares() {
+        FieldObject f = new FieldObject();
+        test("testShortCompare", f, shortTestValue1);
+        test("testShortCompareConstant1", f);
+        test("testShortCompareConstant2", f);
+    }
+
+    @Test
+    public void testShortNullCompares() {
+        test("testShortCompare", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullCompares1() {
+        test("testShortCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullCompares2() {
+        test("testShortCompareConstant2", (Object) null);
+    }
+
+    public static Object testShortCompareLess(FieldObject f, short shortValue) {
+        if (f.shortValue < shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareLessConstant1(FieldObject f) {
+        if (f.shortValue < shortTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareLessConstant2(FieldObject f) {
+        if (f.shortValue < shortTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testShortCompareLess", f, shortTestValue1);
+        test("testShortCompareLessConstant1", f);
+        test("testShortCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testShortNullComparesLess() {
+        test("testShortCompareLess", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullComparesLess1() {
+        test("testShortCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullComparesLess2() {
+        test("testShortCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testShortSwappedCompareLess(FieldObject f, short shortValue) {
+        if (shortValue < f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortSwappedCompareLessConstant1(FieldObject f) {
+        if (shortTestValue1 < f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortSwappedCompareLessConstant2(FieldObject f) {
+        if (shortTestValue2 < f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortSwappedComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testShortSwappedCompareLess", f, shortTestValue1);
+        test("testShortSwappedCompareLessConstant1", f);
+        test("testShortSwappedCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesLess() {
+        test("testShortSwappedCompareLess", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesLess1() {
+        test("testShortSwappedCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesLess2() {
+        test("testShortSwappedCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testShortCompareLessEqual(FieldObject f, short shortValue) {
+        if (f.shortValue <= shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareLessEqualConstant1(FieldObject f) {
+        if (f.shortValue <= shortTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareLessEqualConstant2(FieldObject f) {
+        if (f.shortValue <= shortTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testShortCompareLessEqual", f, shortTestValue1);
+        test("testShortCompareLessEqualConstant1", f);
+        test("testShortCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testShortNullComparesLessEqual() {
+        test("testShortCompareLessEqual", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullComparesLessEqual1() {
+        test("testShortCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullComparesLessEqual2() {
+        test("testShortCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testShortSwappedCompareLessEqual(FieldObject f, short shortValue) {
+        if (shortValue <= f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortSwappedCompareLessEqualConstant1(FieldObject f) {
+        if (shortTestValue1 <= f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortSwappedCompareLessEqualConstant2(FieldObject f) {
+        if (shortTestValue2 <= f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortSwappedComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testShortSwappedCompareLessEqual", f, shortTestValue1);
+        test("testShortSwappedCompareLessEqualConstant1", f);
+        test("testShortSwappedCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesLessEqual() {
+        test("testShortSwappedCompareLessEqual", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesLessEqual1() {
+        test("testShortSwappedCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesLessEqual2() {
+        test("testShortSwappedCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testShortCompareGreater(FieldObject f, short shortValue) {
+        if (f.shortValue > shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareGreaterConstant1(FieldObject f) {
+        if (f.shortValue > shortTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareGreaterConstant2(FieldObject f) {
+        if (f.shortValue > shortTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testShortCompareGreater", f, shortTestValue1);
+        test("testShortCompareGreaterConstant1", f);
+        test("testShortCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testShortNullComparesGreater() {
+        test("testShortCompareGreater", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullComparesGreater1() {
+        test("testShortCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullComparesGreater2() {
+        test("testShortCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testShortSwappedCompareGreater(FieldObject f, short shortValue) {
+        if (shortValue > f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortSwappedCompareGreaterConstant1(FieldObject f) {
+        if (shortTestValue1 > f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortSwappedCompareGreaterConstant2(FieldObject f) {
+        if (shortTestValue2 > f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortSwappedComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testShortSwappedCompareGreater", f, shortTestValue1);
+        test("testShortSwappedCompareGreaterConstant1", f);
+        test("testShortSwappedCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesGreater() {
+        test("testShortSwappedCompareGreater", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesGreater1() {
+        test("testShortSwappedCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesGreater2() {
+        test("testShortSwappedCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testShortCompareGreaterEqual(FieldObject f, short shortValue) {
+        if (f.shortValue >= shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareGreaterEqualConstant1(FieldObject f) {
+        if (f.shortValue >= shortTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortCompareGreaterEqualConstant2(FieldObject f) {
+        if (f.shortValue >= shortTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testShortCompareGreaterEqual", f, shortTestValue1);
+        test("testShortCompareGreaterEqualConstant1", f);
+        test("testShortCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testShortNullComparesGreaterEqual() {
+        test("testShortCompareGreaterEqual", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullComparesGreaterEqual1() {
+        test("testShortCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullComparesGreaterEqual2() {
+        test("testShortCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testShortSwappedCompareGreaterEqual(FieldObject f, short shortValue) {
+        if (shortValue >= f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortSwappedCompareGreaterEqualConstant1(FieldObject f) {
+        if (shortTestValue1 >= f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testShortSwappedCompareGreaterEqualConstant2(FieldObject f) {
+        if (shortTestValue2 >= f.shortValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testShortSwappedComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testShortSwappedCompareGreaterEqual", f, shortTestValue1);
+        test("testShortSwappedCompareGreaterEqualConstant1", f);
+        test("testShortSwappedCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesGreaterEqual() {
+        test("testShortSwappedCompareGreaterEqual", null, shortTestValue1);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesGreaterEqual1() {
+        test("testShortSwappedCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testShortNullSwappedComparesGreaterEqual2() {
+        test("testShortSwappedCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testCharCompare(FieldObject f, char charValue) {
+        if (f.charValue == charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareConstant1(FieldObject f) {
+        if (f.charValue == charTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareConstant2(FieldObject f) {
+        if (f.charValue == charTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharCompares() {
+        FieldObject f = new FieldObject();
+        test("testCharCompare", f, charTestValue1);
+        test("testCharCompareConstant1", f);
+        test("testCharCompareConstant2", f);
+    }
+
+    @Test
+    public void testCharNullCompares() {
+        test("testCharCompare", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullCompares1() {
+        test("testCharCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullCompares2() {
+        test("testCharCompareConstant2", (Object) null);
+    }
+
+    public static Object testCharCompareLess(FieldObject f, char charValue) {
+        if (f.charValue < charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareLessConstant1(FieldObject f) {
+        if (f.charValue < charTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareLessConstant2(FieldObject f) {
+        if (f.charValue < charTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testCharCompareLess", f, charTestValue1);
+        test("testCharCompareLessConstant1", f);
+        test("testCharCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testCharNullComparesLess() {
+        test("testCharCompareLess", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullComparesLess1() {
+        test("testCharCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullComparesLess2() {
+        test("testCharCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testCharSwappedCompareLess(FieldObject f, char charValue) {
+        if (charValue < f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharSwappedCompareLessConstant1(FieldObject f) {
+        if (charTestValue1 < f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharSwappedCompareLessConstant2(FieldObject f) {
+        if (charTestValue2 < f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharSwappedComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testCharSwappedCompareLess", f, charTestValue1);
+        test("testCharSwappedCompareLessConstant1", f);
+        test("testCharSwappedCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesLess() {
+        test("testCharSwappedCompareLess", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesLess1() {
+        test("testCharSwappedCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesLess2() {
+        test("testCharSwappedCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testCharCompareLessEqual(FieldObject f, char charValue) {
+        if (f.charValue <= charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareLessEqualConstant1(FieldObject f) {
+        if (f.charValue <= charTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareLessEqualConstant2(FieldObject f) {
+        if (f.charValue <= charTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testCharCompareLessEqual", f, charTestValue1);
+        test("testCharCompareLessEqualConstant1", f);
+        test("testCharCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testCharNullComparesLessEqual() {
+        test("testCharCompareLessEqual", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullComparesLessEqual1() {
+        test("testCharCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullComparesLessEqual2() {
+        test("testCharCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testCharSwappedCompareLessEqual(FieldObject f, char charValue) {
+        if (charValue <= f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharSwappedCompareLessEqualConstant1(FieldObject f) {
+        if (charTestValue1 <= f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharSwappedCompareLessEqualConstant2(FieldObject f) {
+        if (charTestValue2 <= f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharSwappedComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testCharSwappedCompareLessEqual", f, charTestValue1);
+        test("testCharSwappedCompareLessEqualConstant1", f);
+        test("testCharSwappedCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesLessEqual() {
+        test("testCharSwappedCompareLessEqual", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesLessEqual1() {
+        test("testCharSwappedCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesLessEqual2() {
+        test("testCharSwappedCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testCharCompareGreater(FieldObject f, char charValue) {
+        if (f.charValue > charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareGreaterConstant1(FieldObject f) {
+        if (f.charValue > charTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareGreaterConstant2(FieldObject f) {
+        if (f.charValue > charTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testCharCompareGreater", f, charTestValue1);
+        test("testCharCompareGreaterConstant1", f);
+        test("testCharCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testCharNullComparesGreater() {
+        test("testCharCompareGreater", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullComparesGreater1() {
+        test("testCharCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullComparesGreater2() {
+        test("testCharCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testCharSwappedCompareGreater(FieldObject f, char charValue) {
+        if (charValue > f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharSwappedCompareGreaterConstant1(FieldObject f) {
+        if (charTestValue1 > f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharSwappedCompareGreaterConstant2(FieldObject f) {
+        if (charTestValue2 > f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharSwappedComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testCharSwappedCompareGreater", f, charTestValue1);
+        test("testCharSwappedCompareGreaterConstant1", f);
+        test("testCharSwappedCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesGreater() {
+        test("testCharSwappedCompareGreater", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesGreater1() {
+        test("testCharSwappedCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesGreater2() {
+        test("testCharSwappedCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testCharCompareGreaterEqual(FieldObject f, char charValue) {
+        if (f.charValue >= charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareGreaterEqualConstant1(FieldObject f) {
+        if (f.charValue >= charTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharCompareGreaterEqualConstant2(FieldObject f) {
+        if (f.charValue >= charTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testCharCompareGreaterEqual", f, charTestValue1);
+        test("testCharCompareGreaterEqualConstant1", f);
+        test("testCharCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testCharNullComparesGreaterEqual() {
+        test("testCharCompareGreaterEqual", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullComparesGreaterEqual1() {
+        test("testCharCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullComparesGreaterEqual2() {
+        test("testCharCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testCharSwappedCompareGreaterEqual(FieldObject f, char charValue) {
+        if (charValue >= f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharSwappedCompareGreaterEqualConstant1(FieldObject f) {
+        if (charTestValue1 >= f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testCharSwappedCompareGreaterEqualConstant2(FieldObject f) {
+        if (charTestValue2 >= f.charValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testCharSwappedComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testCharSwappedCompareGreaterEqual", f, charTestValue1);
+        test("testCharSwappedCompareGreaterEqualConstant1", f);
+        test("testCharSwappedCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesGreaterEqual() {
+        test("testCharSwappedCompareGreaterEqual", null, charTestValue1);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesGreaterEqual1() {
+        test("testCharSwappedCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testCharNullSwappedComparesGreaterEqual2() {
+        test("testCharSwappedCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testIntCompare(FieldObject f, int intValue) {
+        if (f.intValue == intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareConstant1(FieldObject f) {
+        if (f.intValue == intTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareConstant2(FieldObject f) {
+        if (f.intValue == intTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntCompares() {
+        FieldObject f = new FieldObject();
+        test("testIntCompare", f, intTestValue1);
+        test("testIntCompareConstant1", f);
+        test("testIntCompareConstant2", f);
+    }
+
+    @Test
+    public void testIntNullCompares() {
+        test("testIntCompare", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullCompares1() {
+        test("testIntCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullCompares2() {
+        test("testIntCompareConstant2", (Object) null);
+    }
+
+    public static Object testIntCompareLess(FieldObject f, int intValue) {
+        if (f.intValue < intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareLessConstant1(FieldObject f) {
+        if (f.intValue < intTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareLessConstant2(FieldObject f) {
+        if (f.intValue < intTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testIntCompareLess", f, intTestValue1);
+        test("testIntCompareLessConstant1", f);
+        test("testIntCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testIntNullComparesLess() {
+        test("testIntCompareLess", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullComparesLess1() {
+        test("testIntCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullComparesLess2() {
+        test("testIntCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testIntSwappedCompareLess(FieldObject f, int intValue) {
+        if (intValue < f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntSwappedCompareLessConstant1(FieldObject f) {
+        if (intTestValue1 < f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntSwappedCompareLessConstant2(FieldObject f) {
+        if (intTestValue2 < f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntSwappedComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testIntSwappedCompareLess", f, intTestValue1);
+        test("testIntSwappedCompareLessConstant1", f);
+        test("testIntSwappedCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesLess() {
+        test("testIntSwappedCompareLess", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesLess1() {
+        test("testIntSwappedCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesLess2() {
+        test("testIntSwappedCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testIntCompareLessEqual(FieldObject f, int intValue) {
+        if (f.intValue <= intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareLessEqualConstant1(FieldObject f) {
+        if (f.intValue <= intTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareLessEqualConstant2(FieldObject f) {
+        if (f.intValue <= intTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testIntCompareLessEqual", f, intTestValue1);
+        test("testIntCompareLessEqualConstant1", f);
+        test("testIntCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testIntNullComparesLessEqual() {
+        test("testIntCompareLessEqual", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullComparesLessEqual1() {
+        test("testIntCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullComparesLessEqual2() {
+        test("testIntCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testIntSwappedCompareLessEqual(FieldObject f, int intValue) {
+        if (intValue <= f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntSwappedCompareLessEqualConstant1(FieldObject f) {
+        if (intTestValue1 <= f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntSwappedCompareLessEqualConstant2(FieldObject f) {
+        if (intTestValue2 <= f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntSwappedComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testIntSwappedCompareLessEqual", f, intTestValue1);
+        test("testIntSwappedCompareLessEqualConstant1", f);
+        test("testIntSwappedCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesLessEqual() {
+        test("testIntSwappedCompareLessEqual", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesLessEqual1() {
+        test("testIntSwappedCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesLessEqual2() {
+        test("testIntSwappedCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testIntCompareGreater(FieldObject f, int intValue) {
+        if (f.intValue > intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareGreaterConstant1(FieldObject f) {
+        if (f.intValue > intTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareGreaterConstant2(FieldObject f) {
+        if (f.intValue > intTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testIntCompareGreater", f, intTestValue1);
+        test("testIntCompareGreaterConstant1", f);
+        test("testIntCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testIntNullComparesGreater() {
+        test("testIntCompareGreater", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullComparesGreater1() {
+        test("testIntCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullComparesGreater2() {
+        test("testIntCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testIntSwappedCompareGreater(FieldObject f, int intValue) {
+        if (intValue > f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntSwappedCompareGreaterConstant1(FieldObject f) {
+        if (intTestValue1 > f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntSwappedCompareGreaterConstant2(FieldObject f) {
+        if (intTestValue2 > f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntSwappedComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testIntSwappedCompareGreater", f, intTestValue1);
+        test("testIntSwappedCompareGreaterConstant1", f);
+        test("testIntSwappedCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesGreater() {
+        test("testIntSwappedCompareGreater", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesGreater1() {
+        test("testIntSwappedCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesGreater2() {
+        test("testIntSwappedCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testIntCompareGreaterEqual(FieldObject f, int intValue) {
+        if (f.intValue >= intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareGreaterEqualConstant1(FieldObject f) {
+        if (f.intValue >= intTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntCompareGreaterEqualConstant2(FieldObject f) {
+        if (f.intValue >= intTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testIntCompareGreaterEqual", f, intTestValue1);
+        test("testIntCompareGreaterEqualConstant1", f);
+        test("testIntCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testIntNullComparesGreaterEqual() {
+        test("testIntCompareGreaterEqual", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullComparesGreaterEqual1() {
+        test("testIntCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullComparesGreaterEqual2() {
+        test("testIntCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testIntSwappedCompareGreaterEqual(FieldObject f, int intValue) {
+        if (intValue >= f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntSwappedCompareGreaterEqualConstant1(FieldObject f) {
+        if (intTestValue1 >= f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testIntSwappedCompareGreaterEqualConstant2(FieldObject f) {
+        if (intTestValue2 >= f.intValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testIntSwappedComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testIntSwappedCompareGreaterEqual", f, intTestValue1);
+        test("testIntSwappedCompareGreaterEqualConstant1", f);
+        test("testIntSwappedCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesGreaterEqual() {
+        test("testIntSwappedCompareGreaterEqual", null, intTestValue1);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesGreaterEqual1() {
+        test("testIntSwappedCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testIntNullSwappedComparesGreaterEqual2() {
+        test("testIntSwappedCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testFloatCompare(FieldObject f, float floatValue) {
+        if (f.floatValue == floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareConstant1(FieldObject f) {
+        if (f.floatValue == floatTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareConstant2(FieldObject f) {
+        if (f.floatValue == floatTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatCompares() {
+        FieldObject f = new FieldObject();
+        test("testFloatCompare", f, floatTestValue1);
+        test("testFloatCompareConstant1", f);
+        test("testFloatCompareConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullCompares() {
+        test("testFloatCompare", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullCompares1() {
+        test("testFloatCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullCompares2() {
+        test("testFloatCompareConstant2", (Object) null);
+    }
+
+    public static Object testFloatCompareLess(FieldObject f, float floatValue) {
+        if (f.floatValue < floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareLessConstant1(FieldObject f) {
+        if (f.floatValue < floatTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareLessConstant2(FieldObject f) {
+        if (f.floatValue < floatTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testFloatCompareLess", f, floatTestValue1);
+        test("testFloatCompareLessConstant1", f);
+        test("testFloatCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullComparesLess() {
+        test("testFloatCompareLess", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullComparesLess1() {
+        test("testFloatCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullComparesLess2() {
+        test("testFloatCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testFloatSwappedCompareLess(FieldObject f, float floatValue) {
+        if (floatValue < f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatSwappedCompareLessConstant1(FieldObject f) {
+        if (floatTestValue1 < f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatSwappedCompareLessConstant2(FieldObject f) {
+        if (floatTestValue2 < f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatSwappedComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testFloatSwappedCompareLess", f, floatTestValue1);
+        test("testFloatSwappedCompareLessConstant1", f);
+        test("testFloatSwappedCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesLess() {
+        test("testFloatSwappedCompareLess", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesLess1() {
+        test("testFloatSwappedCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesLess2() {
+        test("testFloatSwappedCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testFloatCompareLessEqual(FieldObject f, float floatValue) {
+        if (f.floatValue <= floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareLessEqualConstant1(FieldObject f) {
+        if (f.floatValue <= floatTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareLessEqualConstant2(FieldObject f) {
+        if (f.floatValue <= floatTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testFloatCompareLessEqual", f, floatTestValue1);
+        test("testFloatCompareLessEqualConstant1", f);
+        test("testFloatCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullComparesLessEqual() {
+        test("testFloatCompareLessEqual", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullComparesLessEqual1() {
+        test("testFloatCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullComparesLessEqual2() {
+        test("testFloatCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testFloatSwappedCompareLessEqual(FieldObject f, float floatValue) {
+        if (floatValue <= f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatSwappedCompareLessEqualConstant1(FieldObject f) {
+        if (floatTestValue1 <= f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatSwappedCompareLessEqualConstant2(FieldObject f) {
+        if (floatTestValue2 <= f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatSwappedComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testFloatSwappedCompareLessEqual", f, floatTestValue1);
+        test("testFloatSwappedCompareLessEqualConstant1", f);
+        test("testFloatSwappedCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesLessEqual() {
+        test("testFloatSwappedCompareLessEqual", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesLessEqual1() {
+        test("testFloatSwappedCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesLessEqual2() {
+        test("testFloatSwappedCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testFloatCompareGreater(FieldObject f, float floatValue) {
+        if (f.floatValue > floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareGreaterConstant1(FieldObject f) {
+        if (f.floatValue > floatTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareGreaterConstant2(FieldObject f) {
+        if (f.floatValue > floatTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testFloatCompareGreater", f, floatTestValue1);
+        test("testFloatCompareGreaterConstant1", f);
+        test("testFloatCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullComparesGreater() {
+        test("testFloatCompareGreater", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullComparesGreater1() {
+        test("testFloatCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullComparesGreater2() {
+        test("testFloatCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testFloatSwappedCompareGreater(FieldObject f, float floatValue) {
+        if (floatValue > f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatSwappedCompareGreaterConstant1(FieldObject f) {
+        if (floatTestValue1 > f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatSwappedCompareGreaterConstant2(FieldObject f) {
+        if (floatTestValue2 > f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatSwappedComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testFloatSwappedCompareGreater", f, floatTestValue1);
+        test("testFloatSwappedCompareGreaterConstant1", f);
+        test("testFloatSwappedCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesGreater() {
+        test("testFloatSwappedCompareGreater", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesGreater1() {
+        test("testFloatSwappedCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesGreater2() {
+        test("testFloatSwappedCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testFloatCompareGreaterEqual(FieldObject f, float floatValue) {
+        if (f.floatValue >= floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareGreaterEqualConstant1(FieldObject f) {
+        if (f.floatValue >= floatTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatCompareGreaterEqualConstant2(FieldObject f) {
+        if (f.floatValue >= floatTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testFloatCompareGreaterEqual", f, floatTestValue1);
+        test("testFloatCompareGreaterEqualConstant1", f);
+        test("testFloatCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullComparesGreaterEqual() {
+        test("testFloatCompareGreaterEqual", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullComparesGreaterEqual1() {
+        test("testFloatCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullComparesGreaterEqual2() {
+        test("testFloatCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testFloatSwappedCompareGreaterEqual(FieldObject f, float floatValue) {
+        if (floatValue >= f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatSwappedCompareGreaterEqualConstant1(FieldObject f) {
+        if (floatTestValue1 >= f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testFloatSwappedCompareGreaterEqualConstant2(FieldObject f) {
+        if (floatTestValue2 >= f.floatValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testFloatSwappedComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testFloatSwappedCompareGreaterEqual", f, floatTestValue1);
+        test("testFloatSwappedCompareGreaterEqualConstant1", f);
+        test("testFloatSwappedCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesGreaterEqual() {
+        test("testFloatSwappedCompareGreaterEqual", null, floatTestValue1);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesGreaterEqual1() {
+        test("testFloatSwappedCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testFloatNullSwappedComparesGreaterEqual2() {
+        test("testFloatSwappedCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testLongCompare(FieldObject f, long longValue) {
+        if (f.longValue == longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareConstant1(FieldObject f) {
+        if (f.longValue == longTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareConstant2(FieldObject f) {
+        if (f.longValue == longTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongCompares() {
+        FieldObject f = new FieldObject();
+        test("testLongCompare", f, longTestValue1);
+        test("testLongCompareConstant1", f);
+        test("testLongCompareConstant2", f);
+    }
+
+    @Test
+    public void testLongNullCompares() {
+        test("testLongCompare", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullCompares1() {
+        test("testLongCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullCompares2() {
+        test("testLongCompareConstant2", (Object) null);
+    }
+
+    public static Object testLongCompareLess(FieldObject f, long longValue) {
+        if (f.longValue < longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareLessConstant1(FieldObject f) {
+        if (f.longValue < longTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareLessConstant2(FieldObject f) {
+        if (f.longValue < longTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testLongCompareLess", f, longTestValue1);
+        test("testLongCompareLessConstant1", f);
+        test("testLongCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testLongNullComparesLess() {
+        test("testLongCompareLess", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullComparesLess1() {
+        test("testLongCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullComparesLess2() {
+        test("testLongCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testLongSwappedCompareLess(FieldObject f, long longValue) {
+        if (longValue < f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongSwappedCompareLessConstant1(FieldObject f) {
+        if (longTestValue1 < f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongSwappedCompareLessConstant2(FieldObject f) {
+        if (longTestValue2 < f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongSwappedComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testLongSwappedCompareLess", f, longTestValue1);
+        test("testLongSwappedCompareLessConstant1", f);
+        test("testLongSwappedCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesLess() {
+        test("testLongSwappedCompareLess", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesLess1() {
+        test("testLongSwappedCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesLess2() {
+        test("testLongSwappedCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testLongCompareLessEqual(FieldObject f, long longValue) {
+        if (f.longValue <= longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareLessEqualConstant1(FieldObject f) {
+        if (f.longValue <= longTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareLessEqualConstant2(FieldObject f) {
+        if (f.longValue <= longTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testLongCompareLessEqual", f, longTestValue1);
+        test("testLongCompareLessEqualConstant1", f);
+        test("testLongCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testLongNullComparesLessEqual() {
+        test("testLongCompareLessEqual", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullComparesLessEqual1() {
+        test("testLongCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullComparesLessEqual2() {
+        test("testLongCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testLongSwappedCompareLessEqual(FieldObject f, long longValue) {
+        if (longValue <= f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongSwappedCompareLessEqualConstant1(FieldObject f) {
+        if (longTestValue1 <= f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongSwappedCompareLessEqualConstant2(FieldObject f) {
+        if (longTestValue2 <= f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongSwappedComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testLongSwappedCompareLessEqual", f, longTestValue1);
+        test("testLongSwappedCompareLessEqualConstant1", f);
+        test("testLongSwappedCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesLessEqual() {
+        test("testLongSwappedCompareLessEqual", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesLessEqual1() {
+        test("testLongSwappedCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesLessEqual2() {
+        test("testLongSwappedCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testLongCompareGreater(FieldObject f, long longValue) {
+        if (f.longValue > longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareGreaterConstant1(FieldObject f) {
+        if (f.longValue > longTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareGreaterConstant2(FieldObject f) {
+        if (f.longValue > longTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testLongCompareGreater", f, longTestValue1);
+        test("testLongCompareGreaterConstant1", f);
+        test("testLongCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testLongNullComparesGreater() {
+        test("testLongCompareGreater", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullComparesGreater1() {
+        test("testLongCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullComparesGreater2() {
+        test("testLongCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testLongSwappedCompareGreater(FieldObject f, long longValue) {
+        if (longValue > f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongSwappedCompareGreaterConstant1(FieldObject f) {
+        if (longTestValue1 > f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongSwappedCompareGreaterConstant2(FieldObject f) {
+        if (longTestValue2 > f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongSwappedComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testLongSwappedCompareGreater", f, longTestValue1);
+        test("testLongSwappedCompareGreaterConstant1", f);
+        test("testLongSwappedCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesGreater() {
+        test("testLongSwappedCompareGreater", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesGreater1() {
+        test("testLongSwappedCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesGreater2() {
+        test("testLongSwappedCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testLongCompareGreaterEqual(FieldObject f, long longValue) {
+        if (f.longValue >= longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareGreaterEqualConstant1(FieldObject f) {
+        if (f.longValue >= longTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongCompareGreaterEqualConstant2(FieldObject f) {
+        if (f.longValue >= longTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testLongCompareGreaterEqual", f, longTestValue1);
+        test("testLongCompareGreaterEqualConstant1", f);
+        test("testLongCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testLongNullComparesGreaterEqual() {
+        test("testLongCompareGreaterEqual", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullComparesGreaterEqual1() {
+        test("testLongCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullComparesGreaterEqual2() {
+        test("testLongCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testLongSwappedCompareGreaterEqual(FieldObject f, long longValue) {
+        if (longValue >= f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongSwappedCompareGreaterEqualConstant1(FieldObject f) {
+        if (longTestValue1 >= f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testLongSwappedCompareGreaterEqualConstant2(FieldObject f) {
+        if (longTestValue2 >= f.longValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testLongSwappedComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testLongSwappedCompareGreaterEqual", f, longTestValue1);
+        test("testLongSwappedCompareGreaterEqualConstant1", f);
+        test("testLongSwappedCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesGreaterEqual() {
+        test("testLongSwappedCompareGreaterEqual", null, longTestValue1);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesGreaterEqual1() {
+        test("testLongSwappedCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testLongNullSwappedComparesGreaterEqual2() {
+        test("testLongSwappedCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testDoubleCompare(FieldObject f, double doubleValue) {
+        if (f.doubleValue == doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareConstant1(FieldObject f) {
+        if (f.doubleValue == doubleTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareConstant2(FieldObject f) {
+        if (f.doubleValue == doubleTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleCompares() {
+        FieldObject f = new FieldObject();
+        test("testDoubleCompare", f, doubleTestValue1);
+        test("testDoubleCompareConstant1", f);
+        test("testDoubleCompareConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullCompares() {
+        test("testDoubleCompare", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullCompares1() {
+        test("testDoubleCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullCompares2() {
+        test("testDoubleCompareConstant2", (Object) null);
+    }
+
+    public static Object testDoubleCompareLess(FieldObject f, double doubleValue) {
+        if (f.doubleValue < doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareLessConstant1(FieldObject f) {
+        if (f.doubleValue < doubleTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareLessConstant2(FieldObject f) {
+        if (f.doubleValue < doubleTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testDoubleCompareLess", f, doubleTestValue1);
+        test("testDoubleCompareLessConstant1", f);
+        test("testDoubleCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullComparesLess() {
+        test("testDoubleCompareLess", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullComparesLess1() {
+        test("testDoubleCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullComparesLess2() {
+        test("testDoubleCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testDoubleSwappedCompareLess(FieldObject f, double doubleValue) {
+        if (doubleValue < f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleSwappedCompareLessConstant1(FieldObject f) {
+        if (doubleTestValue1 < f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleSwappedCompareLessConstant2(FieldObject f) {
+        if (doubleTestValue2 < f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleSwappedComparesLess() {
+        FieldObject f = new FieldObject();
+        test("testDoubleSwappedCompareLess", f, doubleTestValue1);
+        test("testDoubleSwappedCompareLessConstant1", f);
+        test("testDoubleSwappedCompareLessConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesLess() {
+        test("testDoubleSwappedCompareLess", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesLess1() {
+        test("testDoubleSwappedCompareLessConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesLess2() {
+        test("testDoubleSwappedCompareLessConstant2", (Object) null);
+    }
+
+    public static Object testDoubleCompareLessEqual(FieldObject f, double doubleValue) {
+        if (f.doubleValue <= doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareLessEqualConstant1(FieldObject f) {
+        if (f.doubleValue <= doubleTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareLessEqualConstant2(FieldObject f) {
+        if (f.doubleValue <= doubleTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testDoubleCompareLessEqual", f, doubleTestValue1);
+        test("testDoubleCompareLessEqualConstant1", f);
+        test("testDoubleCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullComparesLessEqual() {
+        test("testDoubleCompareLessEqual", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullComparesLessEqual1() {
+        test("testDoubleCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullComparesLessEqual2() {
+        test("testDoubleCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testDoubleSwappedCompareLessEqual(FieldObject f, double doubleValue) {
+        if (doubleValue <= f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleSwappedCompareLessEqualConstant1(FieldObject f) {
+        if (doubleTestValue1 <= f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleSwappedCompareLessEqualConstant2(FieldObject f) {
+        if (doubleTestValue2 <= f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleSwappedComparesLessEqual() {
+        FieldObject f = new FieldObject();
+        test("testDoubleSwappedCompareLessEqual", f, doubleTestValue1);
+        test("testDoubleSwappedCompareLessEqualConstant1", f);
+        test("testDoubleSwappedCompareLessEqualConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesLessEqual() {
+        test("testDoubleSwappedCompareLessEqual", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesLessEqual1() {
+        test("testDoubleSwappedCompareLessEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesLessEqual2() {
+        test("testDoubleSwappedCompareLessEqualConstant2", (Object) null);
+    }
+
+    public static Object testDoubleCompareGreater(FieldObject f, double doubleValue) {
+        if (f.doubleValue > doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareGreaterConstant1(FieldObject f) {
+        if (f.doubleValue > doubleTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareGreaterConstant2(FieldObject f) {
+        if (f.doubleValue > doubleTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testDoubleCompareGreater", f, doubleTestValue1);
+        test("testDoubleCompareGreaterConstant1", f);
+        test("testDoubleCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullComparesGreater() {
+        test("testDoubleCompareGreater", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullComparesGreater1() {
+        test("testDoubleCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullComparesGreater2() {
+        test("testDoubleCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testDoubleSwappedCompareGreater(FieldObject f, double doubleValue) {
+        if (doubleValue > f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleSwappedCompareGreaterConstant1(FieldObject f) {
+        if (doubleTestValue1 > f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleSwappedCompareGreaterConstant2(FieldObject f) {
+        if (doubleTestValue2 > f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleSwappedComparesGreater() {
+        FieldObject f = new FieldObject();
+        test("testDoubleSwappedCompareGreater", f, doubleTestValue1);
+        test("testDoubleSwappedCompareGreaterConstant1", f);
+        test("testDoubleSwappedCompareGreaterConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesGreater() {
+        test("testDoubleSwappedCompareGreater", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesGreater1() {
+        test("testDoubleSwappedCompareGreaterConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesGreater2() {
+        test("testDoubleSwappedCompareGreaterConstant2", (Object) null);
+    }
+
+    public static Object testDoubleCompareGreaterEqual(FieldObject f, double doubleValue) {
+        if (f.doubleValue >= doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareGreaterEqualConstant1(FieldObject f) {
+        if (f.doubleValue >= doubleTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleCompareGreaterEqualConstant2(FieldObject f) {
+        if (f.doubleValue >= doubleTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testDoubleCompareGreaterEqual", f, doubleTestValue1);
+        test("testDoubleCompareGreaterEqualConstant1", f);
+        test("testDoubleCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullComparesGreaterEqual() {
+        test("testDoubleCompareGreaterEqual", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullComparesGreaterEqual1() {
+        test("testDoubleCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullComparesGreaterEqual2() {
+        test("testDoubleCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testDoubleSwappedCompareGreaterEqual(FieldObject f, double doubleValue) {
+        if (doubleValue >= f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleSwappedCompareGreaterEqualConstant1(FieldObject f) {
+        if (doubleTestValue1 >= f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testDoubleSwappedCompareGreaterEqualConstant2(FieldObject f) {
+        if (doubleTestValue2 >= f.doubleValue) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testDoubleSwappedComparesGreaterEqual() {
+        FieldObject f = new FieldObject();
+        test("testDoubleSwappedCompareGreaterEqual", f, doubleTestValue1);
+        test("testDoubleSwappedCompareGreaterEqualConstant1", f);
+        test("testDoubleSwappedCompareGreaterEqualConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesGreaterEqual() {
+        test("testDoubleSwappedCompareGreaterEqual", null, doubleTestValue1);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesGreaterEqual1() {
+        test("testDoubleSwappedCompareGreaterEqualConstant1", (Object) null);
+    }
+
+    @Test
+    public void testDoubleNullSwappedComparesGreaterEqual2() {
+        test("testDoubleSwappedCompareGreaterEqualConstant2", (Object) null);
+    }
+
+    public static Object testObjectCompare(FieldObject f, Object objectValue) {
+        if (f.objectValue == objectValue) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testObjectCompareConstant1(FieldObject f) {
+        if (f.objectValue == objectTestValue1) {
+            return f;
+        }
+        return null;
+    }
+
+    public static Object testObjectCompareConstant2(FieldObject f) {
+        if (f.objectValue == objectTestValue2) {
+            return f;
+        }
+        return null;
+    }
+
+    @Test
+    public void testObjectCompares() {
+        FieldObject f = new FieldObject();
+        test("testObjectCompare", f, objectTestValue1);
+        test("testObjectCompareConstant1", f);
+        test("testObjectCompareConstant2", f);
+    }
+
+    @Test
+    public void testObjectNullCompares() {
+        test("testObjectCompare", null, objectTestValue1);
+    }
+
+    @Test
+    public void testObjectNullCompares1() {
+        test("testObjectCompareConstant1", (Object) null);
+    }
+
+    @Test
+    public void testObjectNullCompares2() {
+        test("testObjectCompareConstant2", (Object) null);
+    }
+
+    public static int testByteAdd(FieldObject f, byte byteValue) {
+        return f.byteValue + byteValue;
+    }
+
+    public static int testByteAddConstant1(FieldObject f) {
+        return f.byteValue + byteTestValue1;
+    }
+
+    public static int testByteAddConstant2(FieldObject f) {
+        return f.byteValue + byteTestValue2;
+    }
+
+    @Test
+    public void testByteAdds() {
+        FieldObject f = new FieldObject();
+        test("testByteAdd", f, byteTestValue1);
+        test("testByteAddConstant1", f);
+        test("testByteAddConstant2", f);
+    }
+
+    @Test
+    public void testByteNullAdd() {
+        test("testByteAdd", null, byteTestValue1);
+    }
+
+    public static int testShortAdd(FieldObject f, short shortValue) {
+        return f.shortValue + shortValue;
+    }
+
+    public static int testShortAddConstant1(FieldObject f) {
+        return f.shortValue + shortTestValue1;
+    }
+
+    public static int testShortAddConstant2(FieldObject f) {
+        return f.shortValue + shortTestValue2;
+    }
+
+    @Test
+    public void testShortAdds() {
+        FieldObject f = new FieldObject();
+        test("testShortAdd", f, shortTestValue1);
+        test("testShortAddConstant1", f);
+        test("testShortAddConstant2", f);
+    }
+
+    @Test
+    public void testShortNullAdd() {
+        test("testShortAdd", null, shortTestValue1);
+    }
+
+    public static int testCharAdd(FieldObject f, char charValue) {
+        return f.charValue + charValue;
+    }
+
+    public static int testCharAddConstant1(FieldObject f) {
+        return f.charValue + charTestValue1;
+    }
+
+    public static int testCharAddConstant2(FieldObject f) {
+        return f.charValue + charTestValue2;
+    }
+
+    @Test
+    public void testCharAdds() {
+        FieldObject f = new FieldObject();
+        test("testCharAdd", f, charTestValue1);
+        test("testCharAddConstant1", f);
+        test("testCharAddConstant2", f);
+    }
+
+    @Test
+    public void testCharNullAdd() {
+        test("testCharAdd", null, charTestValue1);
+    }
+
+    public static int testIntAdd(FieldObject f, int intValue) {
+        return f.intValue + intValue;
+    }
+
+    public static int testIntAddConstant1(FieldObject f) {
+        return f.intValue + intTestValue1;
+    }
+
+    public static int testIntAddConstant2(FieldObject f) {
+        return f.intValue + intTestValue2;
+    }
+
+    @Test
+    public void testIntAdds() {
+        FieldObject f = new FieldObject();
+        test("testIntAdd", f, intTestValue1);
+        test("testIntAddConstant1", f);
+        test("testIntAddConstant2", f);
+    }
+
+    @Test
+    public void testIntNullAdd() {
+        test("testIntAdd", null, intTestValue1);
+    }
+
+    public static long testLongAdd(FieldObject f, long longValue) {
+        return f.longValue + longValue;
+    }
+
+    public static long testLongAddConstant1(FieldObject f) {
+        return f.longValue + longTestValue1;
+    }
+
+    public static long testLongAddConstant2(FieldObject f) {
+        return f.longValue + longTestValue2;
+    }
+
+    @Test
+    public void testLongAdds() {
+        FieldObject f = new FieldObject();
+        test("testLongAdd", f, longTestValue1);
+        test("testLongAddConstant1", f);
+        test("testLongAddConstant2", f);
+    }
+
+    @Test
+    public void testLongNullAdd() {
+        test("testLongAdd", null, longTestValue1);
+    }
+
+    public static float testFloatAdd(FieldObject f, float floatValue) {
+        return f.floatValue + floatValue;
+    }
+
+    public static float testFloatAddConstant1(FieldObject f) {
+        return f.floatValue + floatTestValue1;
+    }
+
+    public static float testFloatAddConstant2(FieldObject f) {
+        return f.floatValue + floatTestValue2;
+    }
+
+    @Test
+    public void testFloatAdds() {
+        FieldObject f = new FieldObject();
+        test("testFloatAdd", f, floatTestValue1);
+        test("testFloatAddConstant1", f);
+        test("testFloatAddConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullAdd() {
+        test("testFloatAdd", null, floatTestValue1);
+    }
+
+    public static double testDoubleAdd(FieldObject f, double doubleValue) {
+        return f.doubleValue + doubleValue;
+    }
+
+    public static double testDoubleAddConstant1(FieldObject f) {
+        return f.doubleValue + doubleTestValue1;
+    }
+
+    public static double testDoubleAddConstant2(FieldObject f) {
+        return f.doubleValue + doubleTestValue2;
+    }
+
+    @Test
+    public void testDoubleAdds() {
+        FieldObject f = new FieldObject();
+        test("testDoubleAdd", f, doubleTestValue1);
+        test("testDoubleAddConstant1", f);
+        test("testDoubleAddConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullAdd() {
+        test("testDoubleAdd", null, doubleTestValue1);
+    }
+
+    public static int testByteSub(FieldObject f, byte byteValue) {
+        return f.byteValue - byteValue;
+    }
+
+    public static int testByteSubConstant1(FieldObject f) {
+        return f.byteValue - byteTestValue1;
+    }
+
+    public static int testByteSubConstant2(FieldObject f) {
+        return f.byteValue - byteTestValue2;
+    }
+
+    @Test
+    public void testByteSubs() {
+        FieldObject f = new FieldObject();
+        test("testByteSub", f, byteTestValue1);
+        test("testByteSubConstant1", f);
+        test("testByteSubConstant2", f);
+    }
+
+    @Test
+    public void testByteNullSub() {
+        test("testByteSub", null, byteTestValue1);
+    }
+
+    public static int testShortSub(FieldObject f, short shortValue) {
+        return f.shortValue - shortValue;
+    }
+
+    public static int testShortSubConstant1(FieldObject f) {
+        return f.shortValue - shortTestValue1;
+    }
+
+    public static int testShortSubConstant2(FieldObject f) {
+        return f.shortValue - shortTestValue2;
+    }
+
+    @Test
+    public void testShortSubs() {
+        FieldObject f = new FieldObject();
+        test("testShortSub", f, shortTestValue1);
+        test("testShortSubConstant1", f);
+        test("testShortSubConstant2", f);
+    }
+
+    @Test
+    public void testShortNullSub() {
+        test("testShortSub", null, shortTestValue1);
+    }
+
+    public static int testCharSub(FieldObject f, char charValue) {
+        return f.charValue - charValue;
+    }
+
+    public static int testCharSubConstant1(FieldObject f) {
+        return f.charValue - charTestValue1;
+    }
+
+    public static int testCharSubConstant2(FieldObject f) {
+        return f.charValue - charTestValue2;
+    }
+
+    @Test
+    public void testCharSubs() {
+        FieldObject f = new FieldObject();
+        test("testCharSub", f, charTestValue1);
+        test("testCharSubConstant1", f);
+        test("testCharSubConstant2", f);
+    }
+
+    @Test
+    public void testCharNullSub() {
+        test("testCharSub", null, charTestValue1);
+    }
+
+    public static int testIntSub(FieldObject f, int intValue) {
+        return f.intValue - intValue;
+    }
+
+    public static int testIntSubConstant1(FieldObject f) {
+        return f.intValue - intTestValue1;
+    }
+
+    public static int testIntSubConstant2(FieldObject f) {
+        return f.intValue - intTestValue2;
+    }
+
+    @Test
+    public void testIntSubs() {
+        FieldObject f = new FieldObject();
+        test("testIntSub", f, intTestValue1);
+        test("testIntSubConstant1", f);
+        test("testIntSubConstant2", f);
+    }
+
+    @Test
+    public void testIntNullSub() {
+        test("testIntSub", null, intTestValue1);
+    }
+
+    public static long testLongSub(FieldObject f, long longValue) {
+        return f.longValue - longValue;
+    }
+
+    public static long testLongSubConstant1(FieldObject f) {
+        return f.longValue - longTestValue1;
+    }
+
+    public static long testLongSubConstant2(FieldObject f) {
+        return f.longValue - longTestValue2;
+    }
+
+    @Test
+    public void testLongSubs() {
+        FieldObject f = new FieldObject();
+        test("testLongSub", f, longTestValue1);
+        test("testLongSubConstant1", f);
+        test("testLongSubConstant2", f);
+    }
+
+    @Test
+    public void testLongNullSub() {
+        test("testLongSub", null, longTestValue1);
+    }
+
+    public static float testFloatSub(FieldObject f, float floatValue) {
+        return f.floatValue - floatValue;
+    }
+
+    public static float testFloatSubConstant1(FieldObject f) {
+        return f.floatValue - floatTestValue1;
+    }
+
+    public static float testFloatSubConstant2(FieldObject f) {
+        return f.floatValue - floatTestValue2;
+    }
+
+    @Test
+    public void testFloatSubs() {
+        FieldObject f = new FieldObject();
+        test("testFloatSub", f, floatTestValue1);
+        test("testFloatSubConstant1", f);
+        test("testFloatSubConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullSub() {
+        test("testFloatSub", null, floatTestValue1);
+    }
+
+    public static double testDoubleSub(FieldObject f, double doubleValue) {
+        return f.doubleValue - doubleValue;
+    }
+
+    public static double testDoubleSubConstant1(FieldObject f) {
+        return f.doubleValue - doubleTestValue1;
+    }
+
+    public static double testDoubleSubConstant2(FieldObject f) {
+        return f.doubleValue - doubleTestValue2;
+    }
+
+    @Test
+    public void testDoubleSubs() {
+        FieldObject f = new FieldObject();
+        test("testDoubleSub", f, doubleTestValue1);
+        test("testDoubleSubConstant1", f);
+        test("testDoubleSubConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullSub() {
+        test("testDoubleSub", null, doubleTestValue1);
+    }
+
+    public static int testByteMul(FieldObject f, byte byteValue) {
+        return f.byteValue * byteValue;
+    }
+
+    public static int testByteMulConstant1(FieldObject f) {
+        return f.byteValue * byteTestValue1;
+    }
+
+    public static int testByteMulConstant2(FieldObject f) {
+        return f.byteValue * byteTestValue2;
+    }
+
+    @Test
+    public void testByteMuls() {
+        FieldObject f = new FieldObject();
+        test("testByteMul", f, byteTestValue1);
+        test("testByteMulConstant1", f);
+        test("testByteMulConstant2", f);
+    }
+
+    @Test
+    public void testByteNullMul() {
+        test("testByteMul", null, byteTestValue1);
+    }
+
+    public static int testShortMul(FieldObject f, short shortValue) {
+        return f.shortValue * shortValue;
+    }
+
+    public static int testShortMulConstant1(FieldObject f) {
+        return f.shortValue * shortTestValue1;
+    }
+
+    public static int testShortMulConstant2(FieldObject f) {
+        return f.shortValue * shortTestValue2;
+    }
+
+    @Test
+    public void testShortMuls() {
+        FieldObject f = new FieldObject();
+        test("testShortMul", f, shortTestValue1);
+        test("testShortMulConstant1", f);
+        test("testShortMulConstant2", f);
+    }
+
+    @Test
+    public void testShortNullMul() {
+        test("testShortMul", null, shortTestValue1);
+    }
+
+    public static int testCharMul(FieldObject f, char charValue) {
+        return f.charValue * charValue;
+    }
+
+    public static int testCharMulConstant1(FieldObject f) {
+        return f.charValue * charTestValue1;
+    }
+
+    public static int testCharMulConstant2(FieldObject f) {
+        return f.charValue * charTestValue2;
+    }
+
+    @Test
+    public void testCharMuls() {
+        FieldObject f = new FieldObject();
+        test("testCharMul", f, charTestValue1);
+        test("testCharMulConstant1", f);
+        test("testCharMulConstant2", f);
+    }
+
+    @Test
+    public void testCharNullMul() {
+        test("testCharMul", null, charTestValue1);
+    }
+
+    public static int testIntMul(FieldObject f, int intValue) {
+        return f.intValue * intValue;
+    }
+
+    public static int testIntMulConstant1(FieldObject f) {
+        return f.intValue * intTestValue1;
+    }
+
+    public static int testIntMulConstant2(FieldObject f) {
+        return f.intValue * intTestValue2;
+    }
+
+    @Test
+    public void testIntMuls() {
+        FieldObject f = new FieldObject();
+        test("testIntMul", f, intTestValue1);
+        test("testIntMulConstant1", f);
+        test("testIntMulConstant2", f);
+    }
+
+    @Test
+    public void testIntNullMul() {
+        test("testIntMul", null, intTestValue1);
+    }
+
+    public static long testLongMul(FieldObject f, long longValue) {
+        return f.longValue * longValue;
+    }
+
+    public static long testLongMulConstant1(FieldObject f) {
+        return f.longValue * longTestValue1;
+    }
+
+    public static long testLongMulConstant2(FieldObject f) {
+        return f.longValue * longTestValue2;
+    }
+
+    @Test
+    public void testLongMuls() {
+        FieldObject f = new FieldObject();
+        test("testLongMul", f, longTestValue1);
+        test("testLongMulConstant1", f);
+        test("testLongMulConstant2", f);
+    }
+
+    @Test
+    public void testLongNullMul() {
+        test("testLongMul", null, longTestValue1);
+    }
+
+    public static float testFloatMul(FieldObject f, float floatValue) {
+        return f.floatValue * floatValue;
+    }
+
+    public static float testFloatMulConstant1(FieldObject f) {
+        return f.floatValue * floatTestValue1;
+    }
+
+    public static float testFloatMulConstant2(FieldObject f) {
+        return f.floatValue * floatTestValue2;
+    }
+
+    @Test
+    public void testFloatMuls() {
+        FieldObject f = new FieldObject();
+        test("testFloatMul", f, floatTestValue1);
+        test("testFloatMulConstant1", f);
+        test("testFloatMulConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullMul() {
+        test("testFloatMul", null, floatTestValue1);
+    }
+
+    public static double testDoubleMul(FieldObject f, double doubleValue) {
+        return f.doubleValue * doubleValue;
+    }
+
+    public static double testDoubleMulConstant1(FieldObject f) {
+        return f.doubleValue * doubleTestValue1;
+    }
+
+    public static double testDoubleMulConstant2(FieldObject f) {
+        return f.doubleValue * doubleTestValue2;
+    }
+
+    @Test
+    public void testDoubleMuls() {
+        FieldObject f = new FieldObject();
+        test("testDoubleMul", f, doubleTestValue1);
+        test("testDoubleMulConstant1", f);
+        test("testDoubleMulConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullMul() {
+        test("testDoubleMul", null, doubleTestValue1);
+    }
+
+    public static int testByteDiv(FieldObject f, byte byteValue) {
+        return f.byteValue / byteValue;
+    }
+
+    public static int testByteDivConstant1(FieldObject f) {
+        return f.byteValue / byteTestValue1;
+    }
+
+    public static int testByteDivConstant2(FieldObject f) {
+        return f.byteValue / byteTestValue2;
+    }
+
+    @Test
+    public void testByteDivs() {
+        FieldObject f = new FieldObject();
+        test("testByteDiv", f, byteTestValue1);
+        test("testByteDivConstant1", f);
+        test("testByteDivConstant2", f);
+    }
+
+    @Test
+    public void testByteNullDiv() {
+        test("testByteDiv", null, byteTestValue1);
+    }
+
+    public static int testShortDiv(FieldObject f, short shortValue) {
+        return f.shortValue / shortValue;
+    }
+
+    public static int testShortDivConstant1(FieldObject f) {
+        return f.shortValue / shortTestValue1;
+    }
+
+    public static int testShortDivConstant2(FieldObject f) {
+        return f.shortValue / shortTestValue2;
+    }
+
+    @Test
+    public void testShortDivs() {
+        FieldObject f = new FieldObject();
+        test("testShortDiv", f, shortTestValue1);
+        test("testShortDivConstant1", f);
+        test("testShortDivConstant2", f);
+    }
+
+    @Test
+    public void testShortNullDiv() {
+        test("testShortDiv", null, shortTestValue1);
+    }
+
+    public static int testCharDiv(FieldObject f, char charValue) {
+        return f.charValue / charValue;
+    }
+
+    public static int testCharDivConstant1(FieldObject f) {
+        return f.charValue / charTestValue1;
+    }
+
+    public static int testCharDivConstant2(FieldObject f) {
+        return f.charValue / charTestValue2;
+    }
+
+    @Test
+    public void testCharDivs() {
+        FieldObject f = new FieldObject();
+        test("testCharDiv", f, charTestValue1);
+        test("testCharDivConstant1", f);
+        test("testCharDivConstant2", f);
+    }
+
+    @Test
+    public void testCharNullDiv() {
+        test("testCharDiv", null, charTestValue1);
+    }
+
+    public static int testIntDiv(FieldObject f, int intValue) {
+        return f.intValue / intValue;
+    }
+
+    public static int testIntDivConstant1(FieldObject f) {
+        return f.intValue / intTestValue1;
+    }
+
+    public static int testIntDivConstant2(FieldObject f) {
+        return f.intValue / intTestValue2;
+    }
+
+    @Test
+    public void testIntDivs() {
+        FieldObject f = new FieldObject();
+        test("testIntDiv", f, intTestValue1);
+        test("testIntDivConstant1", f);
+        test("testIntDivConstant2", f);
+    }
+
+    @Test
+    public void testIntNullDiv() {
+        test("testIntDiv", null, intTestValue1);
+    }
+
+    public static long testLongDiv(FieldObject f, long longValue) {
+        return f.longValue / longValue;
+    }
+
+    public static long testLongDivConstant1(FieldObject f) {
+        return f.longValue / longTestValue1;
+    }
+
+    public static long testLongDivConstant2(FieldObject f) {
+        return f.longValue / longTestValue2;
+    }
+
+    @Test
+    public void testLongDivs() {
+        FieldObject f = new FieldObject();
+        test("testLongDiv", f, longTestValue1);
+        test("testLongDivConstant1", f);
+        test("testLongDivConstant2", f);
+    }
+
+    @Test
+    public void testLongNullDiv() {
+        test("testLongDiv", null, longTestValue1);
+    }
+
+    public static float testFloatDiv(FieldObject f, float floatValue) {
+        return f.floatValue / floatValue;
+    }
+
+    public static float testFloatDivConstant1(FieldObject f) {
+        return f.floatValue / floatTestValue1;
+    }
+
+    public static float testFloatDivConstant2(FieldObject f) {
+        return f.floatValue / floatTestValue2;
+    }
+
+    @Test
+    public void testFloatDivs() {
+        FieldObject f = new FieldObject();
+        test("testFloatDiv", f, floatTestValue1);
+        test("testFloatDivConstant1", f);
+        test("testFloatDivConstant2", f);
+    }
+
+    @Test
+    public void testFloatNullDiv() {
+        test("testFloatDiv", null, floatTestValue1);
+    }
+
+    public static double testDoubleDiv(FieldObject f, double doubleValue) {
+        return f.doubleValue / doubleValue;
+    }
+
+    public static double testDoubleDivConstant1(FieldObject f) {
+        return f.doubleValue / doubleTestValue1;
+    }
+
+    public static double testDoubleDivConstant2(FieldObject f) {
+        return f.doubleValue / doubleTestValue2;
+    }
+
+    @Test
+    public void testDoubleDivs() {
+        FieldObject f = new FieldObject();
+        test("testDoubleDiv", f, doubleTestValue1);
+        test("testDoubleDivConstant1", f);
+        test("testDoubleDivConstant2", f);
+    }
+
+    @Test
+    public void testDoubleNullDiv() {
+        test("testDoubleDiv", null, doubleTestValue1);
+    }
+
+    public static int testByteOr(FieldObject f, byte byteValue) {
+        return f.byteValue | byteValue;
+    }
+
+    public static int testByteOrConstant1(FieldObject f) {
+        return f.byteValue | byteTestValue1;
+    }
+
+    public static int testByteOrConstant2(FieldObject f) {
+        return f.byteValue | byteTestValue2;
+    }
+
+    @Test
+    public void testByteOrs() {
+        FieldObject f = new FieldObject();
+        test("testByteOr", f, byteTestValue1);
+        test("testByteOrConstant1", f);
+        test("testByteOrConstant2", f);
+    }
+
+    @Test
+    public void testByteNullOr() {
+        test("testByteOr", null, byteTestValue1);
+    }
+
+    public static int testShortOr(FieldObject f, short shortValue) {
+        return f.shortValue | shortValue;
+    }
+
+    public static int testShortOrConstant1(FieldObject f) {
+        return f.shortValue | shortTestValue1;
+    }
+
+    public static int testShortOrConstant2(FieldObject f) {
+        return f.shortValue | shortTestValue2;
+    }
+
+    @Test
+    public void testShortOrs() {
+        FieldObject f = new FieldObject();
+        test("testShortOr", f, shortTestValue1);
+        test("testShortOrConstant1", f);
+        test("testShortOrConstant2", f);
+    }
+
+    @Test
+    public void testShortNullOr() {
+        test("testShortOr", null, shortTestValue1);
+    }
+
+    public static int testCharOr(FieldObject f, char charValue) {
+        return f.charValue | charValue;
+    }
+
+    public static int testCharOrConstant1(FieldObject f) {
+        return f.charValue | charTestValue1;
+    }
+
+    public static int testCharOrConstant2(FieldObject f) {
+        return f.charValue | charTestValue2;
+    }
+
+    @Test
+    public void testCharOrs() {
+        FieldObject f = new FieldObject();
+        test("testCharOr", f, charTestValue1);
+        test("testCharOrConstant1", f);
+        test("testCharOrConstant2", f);
+    }
+
+    @Test
+    public void testCharNullOr() {
+        test("testCharOr", null, charTestValue1);
+    }
+
+    public static int testIntOr(FieldObject f, int intValue) {
+        return f.intValue | intValue;
+    }
+
+    public static int testIntOrConstant1(FieldObject f) {
+        return f.intValue | intTestValue1;
+    }
+
+    public static int testIntOrConstant2(FieldObject f) {
+        return f.intValue | intTestValue2;
+    }
+
+    @Test
+    public void testIntOrs() {
+        FieldObject f = new FieldObject();
+        test("testIntOr", f, intTestValue1);
+        test("testIntOrConstant1", f);
+        test("testIntOrConstant2", f);
+    }
+
+    @Test
+    public void testIntNullOr() {
+        test("testIntOr", null, intTestValue1);
+    }
+
+    public static long testLongOr(FieldObject f, long longValue) {
+        return f.longValue | longValue;
+    }
+
+    public static long testLongOrConstant1(FieldObject f) {
+        return f.longValue | longTestValue1;
+    }
+
+    public static long testLongOrConstant2(FieldObject f) {
+        return f.longValue | longTestValue2;
+    }
+
+    @Test
+    public void testLongOrs() {
+        FieldObject f = new FieldObject();
+        test("testLongOr", f, longTestValue1);
+        test("testLongOrConstant1", f);
+        test("testLongOrConstant2", f);
+    }
+
+    @Test
+    public void testLongNullOr() {
+        test("testLongOr", null, longTestValue1);
+    }
+
+    public static int testByteXor(FieldObject f, byte byteValue) {
+        return f.byteValue ^ byteValue;
+    }
+
+    public static int testByteXorConstant1(FieldObject f) {
+        return f.byteValue ^ byteTestValue1;
+    }
+
+    public static int testByteXorConstant2(FieldObject f) {
+        return f.byteValue ^ byteTestValue2;
+    }
+
+    @Test
+    public void testByteXors() {
+        FieldObject f = new FieldObject();
+        test("testByteXor", f, byteTestValue1);
+        test("testByteXorConstant1", f);
+        test("testByteXorConstant2", f);
+    }
+
+    @Test
+    public void testByteNullXor() {
+        test("testByteXor", null, byteTestValue1);
+    }
+
+    public static int testShortXor(FieldObject f, short shortValue) {
+        return f.shortValue ^ shortValue;
+    }
+
+    public static int testShortXorConstant1(FieldObject f) {
+        return f.shortValue ^ shortTestValue1;
+    }
+
+    public static int testShortXorConstant2(FieldObject f) {
+        return f.shortValue ^ shortTestValue2;
+    }
+
+    @Test
+    public void testShortXors() {
+        FieldObject f = new FieldObject();
+        test("testShortXor", f, shortTestValue1);
+        test("testShortXorConstant1", f);
+        test("testShortXorConstant2", f);
+    }
+
+    @Test
+    public void testShortNullXor() {
+        test("testShortXor", null, shortTestValue1);
+    }
+
+    public static int testCharXor(FieldObject f, char charValue) {
+        return f.charValue ^ charValue;
+    }
+
+    public static int testCharXorConstant1(FieldObject f) {
+        return f.charValue ^ charTestValue1;
+    }
+
+    public static int testCharXorConstant2(FieldObject f) {
+        return f.charValue ^ charTestValue2;
+    }
+
+    @Test
+    public void testCharXors() {
+        FieldObject f = new FieldObject();
+        test("testCharXor", f, charTestValue1);
+        test("testCharXorConstant1", f);
+        test("testCharXorConstant2", f);
+    }
+
+    @Test
+    public void testCharNullXor() {
+        test("testCharXor", null, charTestValue1);
+    }
+
+    public static int testIntXor(FieldObject f, int intValue) {
+        return f.intValue ^ intValue;
+    }
+
+    public static int testIntXorConstant1(FieldObject f) {
+        return f.intValue ^ intTestValue1;
+    }
+
+    public static int testIntXorConstant2(FieldObject f) {
+        return f.intValue ^ intTestValue2;
+    }
+
+    @Test
+    public void testIntXors() {
+        FieldObject f = new FieldObject();
+        test("testIntXor", f, intTestValue1);
+        test("testIntXorConstant1", f);
+        test("testIntXorConstant2", f);
+    }
+
+    @Test
+    public void testIntNullXor() {
+        test("testIntXor", null, intTestValue1);
+    }
+
+    public static long testLongXor(FieldObject f, long longValue) {
+        return f.longValue ^ longValue;
+    }
+
+    public static long testLongXorConstant1(FieldObject f) {
+        return f.longValue ^ longTestValue1;
+    }
+
+    public static long testLongXorConstant2(FieldObject f) {
+        return f.longValue ^ longTestValue2;
+    }
+
+    @Test
+    public void testLongXors() {
+        FieldObject f = new FieldObject();
+        test("testLongXor", f, longTestValue1);
+        test("testLongXorConstant1", f);
+        test("testLongXorConstant2", f);
+    }
+
+    @Test
+    public void testLongNullXor() {
+        test("testLongXor", null, longTestValue1);
+    }
+
+    public static int testByteAnd(FieldObject f, byte byteValue) {
+        return f.byteValue & byteValue;
+    }
+
+    public static int testByteAndConstant1(FieldObject f) {
+        return f.byteValue & byteTestValue1;
+    }
+
+    public static int testByteAndConstant2(FieldObject f) {
+        return f.byteValue & byteTestValue2;
+    }
+
+    @Test
+    public void testByteAnds() {
+        FieldObject f = new FieldObject();
+        test("testByteAnd", f, byteTestValue1);
+        test("testByteAndConstant1", f);
+        test("testByteAndConstant2", f);
+    }
+
+    @Test
+    public void testByteNullAnd() {
+        test("testByteAnd", null, byteTestValue1);
+    }
+
+    public static int testShortAnd(FieldObject f, short shortValue) {
+        return f.shortValue & shortValue;
+    }
+
+    public static int testShortAndConstant1(FieldObject f) {
+        return f.shortValue & shortTestValue1;
+    }
+
+    public static int testShortAndConstant2(FieldObject f) {
+        return f.shortValue & shortTestValue2;
+    }
+
+    @Test
+    public void testShortAnds() {
+        FieldObject f = new FieldObject();
+        test("testShortAnd", f, shortTestValue1);
+        test("testShortAndConstant1", f);
+        test("testShortAndConstant2", f);
+    }
+
+    @Test
+    public void testShortNullAnd() {
+        test("testShortAnd", null, shortTestValue1);
+    }
+
+    public static int testCharAnd(FieldObject f, char charValue) {
+        return f.charValue & charValue;
+    }
+
+    public static int testCharAndConstant1(FieldObject f) {
+        return f.charValue & charTestValue1;
+    }
+
+    public static int testCharAndConstant2(FieldObject f) {
+        return f.charValue & charTestValue2;
+    }
+
+    @Test
+    public void testCharAnds() {
+        FieldObject f = new FieldObject();
+        test("testCharAnd", f, charTestValue1);
+        test("testCharAndConstant1", f);
+        test("testCharAndConstant2", f);
+    }
+
+    @Test
+    public void testCharNullAnd() {
+        test("testCharAnd", null, charTestValue1);
+    }
+
+    public static int testIntAnd(FieldObject f, int intValue) {
+        return f.intValue & intValue;
+    }
+
+    public static int testIntAndConstant1(FieldObject f) {
+        return f.intValue & intTestValue1;
+    }
+
+    public static int testIntAndConstant2(FieldObject f) {
+        return f.intValue & intTestValue2;
+    }
+
+    @Test
+    public void testIntAnds() {
+        FieldObject f = new FieldObject();
+        test("testIntAnd", f, intTestValue1);
+        test("testIntAndConstant1", f);
+        test("testIntAndConstant2", f);
+    }
+
+    @Test
+    public void testIntNullAnd() {
+        test("testIntAnd", null, intTestValue1);
+    }
+
+    public static long testLongAnd(FieldObject f, long longValue) {
+        return f.longValue & longValue;
+    }
+
+    public static long testLongAndConstant1(FieldObject f) {
+        return f.longValue & longTestValue1;
+    }
+
+    public static long testLongAndConstant2(FieldObject f) {
+        return f.longValue & longTestValue2;
+    }
+
+    @Test
+    public void testLongAnds() {
+        FieldObject f = new FieldObject();
+        test("testLongAnd", f, longTestValue1);
+        test("testLongAndConstant1", f);
+        test("testLongAndConstant2", f);
+    }
+
+    @Test
+    public void testLongNullAnd() {
+        test("testLongAnd", null, longTestValue1);
+    }
+
+    public static boolean testIntMask(FieldObject f, int intValue) {
+        if ((f.intValue & intValue) != 0) {
+            count++;
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean testIntMaskConstant1(FieldObject f) {
+        return (f.intValue & intTestValue1) != 0;
+    }
+
+    public static boolean testIntMaskConstant2(FieldObject f) {
+        return (f.intValue & intTestValue2) != 0;
+    }
+
+    @Test
+    public void testIntMasks() {
+        FieldObject f = new FieldObject();
+        test("testIntMask", f, intTestValue1);
+        test("testIntMaskConstant1", f);
+        test("testIntMaskConstant2", f);
+    }
+
+    @Test
+    public void testIntNullMask() {
+        test("testIntMask", null, intTestValue1);
+    }
+
+    public static boolean testLongMask(FieldObject f, long longValue) {
+        if ((f.longValue & longValue) != 0) {
+            count++;
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean testLongMaskConstant1(FieldObject f) {
+        return (f.longValue & longTestValue1) != 0;
+    }
+
+    public static boolean testLongMaskConstant2(FieldObject f) {
+        return (f.longValue & longTestValue2) != 0;
+    }
+
+    @Test
+    public void testLongMasks() {
+        FieldObject f = new FieldObject();
+        test("testLongMask", f, longTestValue1);
+        test("testLongMaskConstant1", f);
+        test("testLongMaskConstant2", f);
+    }
+
+    @Test
+    public void testLongNullMask() {
+        test("testLongMask", null, longTestValue1);
+    }
+
+    public static int doConvertByteInt(FieldObject f) {
+        return f.byteValue;
+    }
+
+    @Test
+    public void testConvertByteInt() {
+        test("doConvertByteInt", maxObject);
+        test("doConvertByteInt", (FieldObject) null);
+    }
+
+    public static int doConvertShortInt(FieldObject f) {
+        return f.shortValue;
+    }
+
+    @Test
+    public void testConvertShortInt() {
+        test("doConvertShortInt", maxObject);
+        test("doConvertShortInt", (FieldObject) null);
+    }
+
+    public static int doConvertCharInt(FieldObject f) {
+        return f.charValue;
+    }
+
+    @Test
+    public void testConvertCharInt() {
+        test("doConvertCharInt", maxObject);
+        test("doConvertCharInt", (FieldObject) null);
+    }
+
+    public static int doConvertLongInt(FieldObject f) {
+        return (int) f.longValue;
+    }
+
+    @Test
+    public void testConvertLongInt() {
+        test("doConvertLongInt", maxObject);
+        test("doConvertLongInt", (FieldObject) null);
+    }
+
+    public static int doConvertFloatInt(FieldObject f) {
+        return (int) f.floatValue;
+    }
+
+    @Test
+    public void testConvertFloatInt() {
+        test("doConvertFloatInt", maxObject);
+        test("doConvertFloatInt", (FieldObject) null);
+    }
+
+    public static int doConvertDoubleInt(FieldObject f) {
+        return (int) f.doubleValue;
+    }
+
+    @Test
+    public void testConvertDoubleInt() {
+        test("doConvertDoubleInt", maxObject);
+        test("doConvertDoubleInt", (FieldObject) null);
+    }
+
+    public static long doConvertByteLong(FieldObject f) {
+        return f.byteValue;
+    }
+
+    @Test
+    public void testConvertByteLong() {
+        test("doConvertByteLong", maxObject);
+        test("doConvertByteLong", (FieldObject) null);
+    }
+
+    public static long doConvertShortLong(FieldObject f) {
+        return f.shortValue;
+    }
+
+    @Test
+    public void testConvertShortLong() {
+        test("doConvertShortLong", maxObject);
+        test("doConvertShortLong", (FieldObject) null);
+    }
+
+    public static long doConvertCharLong(FieldObject f) {
+        return f.charValue;
+    }
+
+    @Test
+    public void testConvertCharLong() {
+        test("doConvertCharLong", maxObject);
+        test("doConvertCharLong", (FieldObject) null);
+    }
+
+    public static long doConvertIntLong(FieldObject f) {
+        return f.intValue;
+    }
+
+    @Test
+    public void testConvertIntLong() {
+        test("doConvertIntLong", maxObject);
+        test("doConvertIntLong", (FieldObject) null);
+    }
+
+    public static long doConvertFloatLong(FieldObject f) {
+        return (long) f.floatValue;
+    }
+
+    @Test
+    public void testConvertFloatLong() {
+        test("doConvertFloatLong", maxObject);
+        test("doConvertFloatLong", (FieldObject) null);
+    }
+
+    public static long doConvertDoubleLong(FieldObject f) {
+        return (long) f.doubleValue;
+    }
+
+    @Test
+    public void testConvertDoubleLong() {
+        test("doConvertDoubleLong", maxObject);
+        test("doConvertDoubleLong", (FieldObject) null);
+    }
+
+    public static float doConvertByteFloat(FieldObject f) {
+        return f.byteValue;
+    }
+
+    @Test
+    public void testConvertByteFloat() {
+        test("doConvertByteFloat", maxObject);
+        test("doConvertByteFloat", (FieldObject) null);
+    }
+
+    public static float doConvertShortFloat(FieldObject f) {
+        return f.shortValue;
+    }
+
+    @Test
+    public void testConvertShortFloat() {
+        test("doConvertShortFloat", maxObject);
+        test("doConvertShortFloat", (FieldObject) null);
+    }
+
+    public static float doConvertCharFloat(FieldObject f) {
+        return f.charValue;
+    }
+
+    @Test
+    public void testConvertCharFloat() {
+        test("doConvertCharFloat", maxObject);
+        test("doConvertCharFloat", (FieldObject) null);
+    }
+
+    public static float doConvertIntFloat(FieldObject f) {
+        return f.intValue;
+    }
+
+    @Test
+    public void testConvertIntFloat() {
+        test("doConvertIntFloat", maxObject);
+        test("doConvertIntFloat", (FieldObject) null);
+    }
+
+    public static float doConvertLongFloat(FieldObject f) {
+        return f.longValue;
+    }
+
+    @Test
+    public void testConvertLongFloat() {
+        test("doConvertLongFloat", maxObject);
+        test("doConvertLongFloat", (FieldObject) null);
+    }
+
+    public static float doConvertDoubleFloat(FieldObject f) {
+        return (float) f.doubleValue;
+    }
+
+    @Test
+    public void testConvertDoubleFloat() {
+        test("doConvertDoubleFloat", maxObject);
+        test("doConvertDoubleFloat", (FieldObject) null);
+    }
+
+    public static double doConvertByteDouble(FieldObject f) {
+        return f.byteValue;
+    }
+
+    @Test
+    public void testConvertByteDouble() {
+        test("doConvertByteDouble", maxObject);
+        test("doConvertByteDouble", (FieldObject) null);
+    }
+
+    public static double doConvertShortDouble(FieldObject f) {
+        return f.shortValue;
+    }
+
+    @Test
+    public void testConvertShortDouble() {
+        test("doConvertShortDouble", maxObject);
+        test("doConvertShortDouble", (FieldObject) null);
+    }
+
+    public static double doConvertCharDouble(FieldObject f) {
+        return f.charValue;
+    }
+
+    @Test
+    public void testConvertCharDouble() {
+        test("doConvertCharDouble", maxObject);
+        test("doConvertCharDouble", (FieldObject) null);
+    }
+
+    public static double doConvertIntDouble(FieldObject f) {
+        return f.intValue;
+    }
+
+    @Test
+    public void testConvertIntDouble() {
+        test("doConvertIntDouble", maxObject);
+        test("doConvertIntDouble", (FieldObject) null);
+    }
+
+    public static double doConvertLongDouble(FieldObject f) {
+        return f.longValue;
+    }
+
+    @Test
+    public void testConvertLongDouble() {
+        test("doConvertLongDouble", maxObject);
+        test("doConvertLongDouble", (FieldObject) null);
+    }
+
+    public static double doConvertFloatDouble(FieldObject f) {
+        return f.floatValue;
+    }
+
+    @Test
+    public void testConvertFloatDouble() {
+        test("doConvertFloatDouble", maxObject);
+        test("doConvertFloatDouble", (FieldObject) null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThread.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 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.compiler;
+
+import com.oracle.graal.compiler.CompilerThreadFactory.*;
+import com.oracle.graal.debug.*;
+
+/**
+ * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY} and executes in the
+ * context of a thread-local {@linkplain GraalDebugConfig debug configuration}.
+ */
+public class CompilerThread extends Thread {
+
+    private final DebugConfigAccess debugConfigAccess;
+
+    public CompilerThread(Runnable r, String namePrefix, DebugConfigAccess debugConfigAccess) {
+        super(r);
+        this.setName(namePrefix + "-" + this.getId());
+        this.setPriority(Thread.MAX_PRIORITY);
+        this.setDaemon(true);
+        this.debugConfigAccess = debugConfigAccess;
+    }
+
+    @Override
+    public void run() {
+        GraalDebugConfig debugConfig = debugConfigAccess.getDebugConfig();
+        try {
+            super.run();
+        } finally {
+            if (debugConfig != null) {
+                for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) {
+                    try {
+                        dumpHandler.close();
+                    } catch (Throwable t) {
+                    }
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThreadFactory.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThreadFactory.java	Wed Mar 26 20:44:11 2014 +0100
@@ -53,38 +53,4 @@
     public Thread newThread(Runnable r) {
         return new CompilerThread(r, threadNamePrefix, debugConfigAccess);
     }
-
-    /**
-     * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY} and executes in
-     * the context of a thread-local {@linkplain GraalDebugConfig debug configuration}.
-     */
-    public static class CompilerThread extends Thread {
-
-        private final DebugConfigAccess debugConfigAccess;
-
-        public CompilerThread(Runnable r, String namePrefix, DebugConfigAccess debugConfigAccess) {
-            super(r);
-            this.setName(namePrefix + "-" + this.getId());
-            this.setPriority(Thread.MAX_PRIORITY);
-            this.setDaemon(true);
-            this.debugConfigAccess = debugConfigAccess;
-        }
-
-        @Override
-        public void run() {
-            GraalDebugConfig debugConfig = debugConfigAccess.getDebugConfig();
-            try {
-                super.run();
-            } finally {
-                if (debugConfig != null) {
-                    for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) {
-                        try {
-                            dumpHandler.close();
-                        } catch (Throwable t) {
-                        }
-                    }
-                }
-            }
-        }
-    }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Wed Mar 26 20:44:11 2014 +0100
@@ -1179,7 +1179,9 @@
         String to = "?";
         if (first != null && first != Range.EndMarker) {
             from = String.valueOf(from());
-            to = String.valueOf(to());
+            // to() may cache a computed value, modifying the current object, which is a bad idea
+            // for a printing function. Compute it directly instead.
+            to = String.valueOf(calcTo());
         }
         String locationString = this.location == null ? "" : "@" + this.location;
         return operandNumber + ":" + operand + (isRegister(operand) ? "" : locationString) + "[" + from + "," + to + "]";
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed Mar 26 20:44:11 2014 +0100
@@ -53,6 +53,14 @@
 
     private MoveResolver moveResolver; // for ordering spill moves
 
+    /**
+     * Only 10% of the lists in {@link #spillIntervals} are actually used. But when they are used,
+     * they can grow quite long. The maximum length observed was 45 (all numbers taken from a
+     * bootstrap run of Graal). Therefore, we initialize {@link #spillIntervals} with this marker
+     * value, and allocate a "real" list only on demand in {@link #setUsePos}.
+     */
+    private static final List<Interval> EMPTY_LIST = new ArrayList<>(0);
+
     // accessors mapped to same functions in class LinearScan
     int blockCount() {
         return allocator.blockCount();
@@ -76,7 +84,7 @@
         moveResolver = new MoveResolver(allocator);
         spillIntervals = Util.uncheckedCast(new List[allocator.registers.length]);
         for (int i = 0; i < allocator.registers.length; i++) {
-            spillIntervals[i] = new ArrayList<>(2);
+            spillIntervals[i] = EMPTY_LIST;
         }
         usePos = new int[allocator.registers.length];
         blockPos = new int[allocator.registers.length];
@@ -111,7 +119,12 @@
                     this.usePos[i] = usePos;
                 }
                 if (!onlyProcessUsePos) {
-                    spillIntervals[i].add(interval);
+                    List<Interval> list = spillIntervals[i];
+                    if (list == EMPTY_LIST) {
+                        list = new ArrayList<>(2);
+                        spillIntervals[i] = list;
+                    }
+                    list.add(interval);
                 }
             }
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -145,7 +145,7 @@
 
     /**
      * set this before using the LIRGenerator
-     * 
+     *
      * TODO this should be removed
      */
     void setDebugInfoBuilder(DebugInfoBuilder builder) {
@@ -155,7 +155,7 @@
     /**
      * Checks whether the supplied constant can be used without loading it into a register for store
      * operations, i.e., on the right hand side of a memory access.
-     * 
+     *
      * @param c The constant to check.
      * @return True if the constant can be used directly, false if the constant needs to be in a
      *         register.
@@ -204,7 +204,7 @@
 
     /**
      * Creates a new {@linkplain Variable variable}.
-     * 
+     *
      * @param platformKind The kind of the new variable.
      * @return a new variable
      */
@@ -260,18 +260,29 @@
         return false;
     }
 
+    private static FrameState getFrameState(DeoptimizingNode deopt) {
+        if (deopt instanceof DeoptimizingNode.DeoptBefore) {
+            return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore();
+        } else if (deopt instanceof DeoptimizingNode.DeoptDuring) {
+            return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring();
+        } else {
+            assert deopt instanceof DeoptimizingNode.DeoptAfter;
+            return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter();
+        }
+    }
+
     public LIRFrameState state(DeoptimizingNode deopt) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateFor(deopt.getDeoptimizationState());
+        return stateFor(getFrameState(deopt));
     }
 
     public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), exceptionEdge);
+        return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge);
     }
 
     public LIRFrameState stateFor(FrameState state) {
@@ -288,7 +299,7 @@
 
     /**
      * Gets the ABI specific operand used to return a value of a given kind from a method.
-     * 
+     *
      * @param kind the kind of value being returned
      * @return the operand representing the ABI defined location used return a value of kind
      *         {@code kind}
@@ -300,7 +311,7 @@
         return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind);
     }
 
-    protected void append(LIRInstruction op) {
+    public void append(LIRInstruction op) {
         if (printIRWithLIR && !TTY.isSuppressed()) {
             // if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
             // lastInstructionPrinted = currentInstruction;
@@ -387,7 +398,7 @@
         LIRFrameState state = null;
         if (linkage.canDeoptimize()) {
             if (info != null) {
-                state = stateFor(info.getDeoptimizationState());
+                state = stateFor(getFrameState(info));
             } else {
                 assert needOnlyOopMaps();
                 state = new LIRFrameState(null, null, null);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -37,6 +37,7 @@
 import com.oracle.graal.compiler.gen.LIRGenerator.LoadConstant;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
@@ -50,6 +51,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
 
 /**
  * This class traverses the HIR instructions and generates LIR instructions from them.
@@ -95,18 +97,30 @@
 
     /**
      * Returns the operand that has been previously initialized by
-     * {@link #setResult(ValueNode, Value)} with the result of an instruction.
-     * 
+     * {@link #setResult(ValueNode, Value)} with the result of an instruction. It's a code
+     * generation error to ask for the operand of ValueNode that doesn't have one yet.
+     *
      * @param node A node that produces a result value.
      */
     @Override
     public Value operand(ValueNode node) {
+        Value operand = getOperand(node);
+        assert operand != null : String.format("missing operand for %1s", node);
+        return operand;
+    }
+
+    @Override
+    public boolean hasOperand(ValueNode node) {
+        return getOperand(node) != null;
+    }
+
+    private Value getOperand(ValueNode node) {
         if (nodeOperands == null) {
             return null;
         }
         Value operand = nodeOperands.get(node);
         if (operand == null) {
-            return getConstantOperand(node);
+            operand = getConstantOperand(node);
         }
         return operand;
     }
@@ -178,24 +192,40 @@
         return LabelRef.forSuccessor(res.getLIR(), (Block) gen.getCurrentBlock(), suxIndex);
     }
 
+    @Deprecated
+    private static FrameState getFrameState(DeoptimizingNode deopt) {
+        if (deopt instanceof DeoptimizingNode.DeoptBefore) {
+            return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore();
+        } else if (deopt instanceof DeoptimizingNode.DeoptDuring) {
+            return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring();
+        } else {
+            assert deopt instanceof DeoptimizingNode.DeoptAfter;
+            return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter();
+        }
+    }
+
+    @Deprecated
     public LIRFrameState state(DeoptimizingNode deopt) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateFor(deopt.getDeoptimizationState());
+        return stateFor(getFrameState(deopt));
     }
 
+    @Deprecated
     public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), exceptionEdge);
+        return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge);
     }
 
+    @Deprecated
     public LIRFrameState stateFor(FrameState state) {
         return stateForWithExceptionEdge(state, null);
     }
 
+    @Deprecated
     public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) {
         if (gen.needOnlyOopMaps()) {
             return new LIRFrameState(null, null, null);
@@ -204,7 +234,7 @@
         return getDebugInfoBuilder().build(state, exceptionEdge);
     }
 
-    final protected void append(LIRInstruction op) {
+    public final void append(LIRInstruction op) {
         if (printIRWithLIR && !TTY.isSuppressed()) {
             if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
                 lastInstructionPrinted = currentInstruction;
@@ -275,23 +305,32 @@
         }
 
         List<ScheduledNode> nodes = blockMap.get(block);
+        int instructionsFolded = 0;
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
             if (traceLevel >= 3) {
                 TTY.println("LIRGen for " + instr);
             }
+            if (instructionsFolded > 0) {
+                instructionsFolded--;
+                continue;
+            }
             if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) {
                 // Loading of constants is done lazily by operand()
+
             } else if (instr instanceof ValueNode) {
                 ValueNode valueNode = (ValueNode) instr;
-                if (operand(valueNode) == null) {
+                if (!hasOperand(valueNode)) {
                     if (!peephole(valueNode)) {
-                        try {
-                            doRoot((ValueNode) instr);
-                        } catch (GraalInternalError e) {
-                            throw e.addContext(instr);
-                        } catch (Throwable e) {
-                            throw new GraalInternalError(e).addContext(instr);
+                        instructionsFolded = maybeFoldMemory(nodes, i, valueNode);
+                        if (instructionsFolded == 0) {
+                            try {
+                                doRoot((ValueNode) instr);
+                            } catch (GraalInternalError e) {
+                                throw e.addContext(instr);
+                            } catch (Throwable e) {
+                                throw new GraalInternalError(e).addContext(instr);
+                            }
                         }
                     }
                 } else {
@@ -318,6 +357,138 @@
         doBlockEnd(block);
     }
 
+    private static final DebugMetric MemoryFoldSuccess = Debug.metric("MemoryFoldSuccess");
+    private static final DebugMetric MemoryFoldFailed = Debug.metric("MemoryFoldFailed");
+    private static final DebugMetric MemoryFoldFailedNonAdjacent = Debug.metric("MemoryFoldedFailedNonAdjacent");
+    private static final DebugMetric MemoryFoldFailedDifferentBlock = Debug.metric("MemoryFoldedFailedDifferentBlock");
+
+    /**
+     * Subclass can provide helper to fold memory operations into other operations.
+     */
+    public MemoryArithmeticLIRLowerer getMemoryLowerer() {
+        return null;
+    }
+
+    /**
+     * Try to find a sequence of Nodes which can be passed to the backend to look for optimized
+     * instruction sequences using memory. Currently this basically is a read with a single
+     * arithmetic user followed by an possible if use. This should generalized to more generic
+     * pattern matching so that it can be more flexibly used.
+     */
+    private int maybeFoldMemory(List<ScheduledNode> nodes, int i, ValueNode access) {
+        MemoryArithmeticLIRLowerer lowerer = getMemoryLowerer();
+        if (lowerer != null && GraalOptions.OptFoldMemory.getValue() && (access instanceof ReadNode || access instanceof FloatingReadNode) && access.usages().count() == 1 && i + 1 < nodes.size()) {
+            try (Scope s = Debug.scope("MaybeFoldMemory", access)) {
+                // This is all bit hacky since it's happening on the linearized schedule. This needs
+                // to be revisited at some point.
+
+                // Find a memory lowerable usage of this operation
+                if (access.usages().first() instanceof MemoryArithmeticLIRLowerable) {
+                    ValueNode operation = (ValueNode) access.usages().first();
+                    if (!nodes.contains(operation)) {
+                        Debug.log("node %1s in different block from %1s", access, operation);
+                        MemoryFoldFailedDifferentBlock.increment();
+                        return 0;
+                    }
+                    ValueNode firstOperation = operation;
+                    if (operation instanceof LogicNode) {
+                        if (operation.usages().count() == 1 && operation.usages().first() instanceof IfNode) {
+                            ValueNode ifNode = (ValueNode) operation.usages().first();
+                            if (!nodes.contains(ifNode)) {
+                                MemoryFoldFailedDifferentBlock.increment();
+                                Debug.log("if node %1s in different block from %1s", ifNode, operation);
+                                try (Indent indent = Debug.logAndIndent("checking operations")) {
+                                    int start = nodes.indexOf(access);
+                                    int end = nodes.indexOf(operation);
+                                    for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) {
+                                        indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1));
+                                    }
+                                }
+                                return 0;
+                            } else {
+                                operation = ifNode;
+                            }
+                        }
+                    }
+                    if (Debug.isLogEnabled()) {
+                        synchronized ("lock") {  // Hack to ensure the output is grouped.
+                            try (Indent indent = Debug.logAndIndent("checking operations")) {
+                                int start = nodes.indexOf(access);
+                                int end = nodes.indexOf(operation);
+                                for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) {
+                                    indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1));
+                                }
+                            }
+                        }
+                    }
+                    // Possible lowerable operation in the same block. Check out the dependencies.
+                    int opIndex = nodes.indexOf(operation);
+                    int current = i + 1;
+                    ArrayList<ValueNode> deferred = null;
+                    while (current < opIndex) {
+                        ScheduledNode node = nodes.get(current);
+                        if (node != firstOperation) {
+                            if (node instanceof LocationNode || node instanceof VirtualObjectNode) {
+                                // nothing to do
+                            } else if (node instanceof ConstantNode) {
+                                if (deferred == null) {
+                                    deferred = new ArrayList<>(2);
+                                }
+                                // These nodes are collected and the backend is expended to
+                                // evaluate them before generating the lowered form. This
+                                // basically works around unfriendly scheduling of values which
+                                // are defined in a block but not used there.
+                                deferred.add((ValueNode) node);
+                            } else {
+                                Debug.log("unexpected node %1s", node);
+                                // Unexpected inline node
+                                break;
+                            }
+                        }
+                        current++;
+                    }
+
+                    if (current == opIndex) {
+                        if (lowerer.memoryPeephole((Access) access, (MemoryArithmeticLIRLowerable) operation, deferred)) {
+                            MemoryFoldSuccess.increment();
+                            // if this operation had multiple access inputs, then previous attempts
+                            // would be marked as failures which is wrong. Try to adjust the
+                            // counters to account for this.
+                            for (Node input : operation.inputs()) {
+                                if (input == access) {
+                                    continue;
+                                }
+                                if (input instanceof Access && nodes.contains(input)) {
+                                    MemoryFoldFailedNonAdjacent.add(-1);
+                                }
+                            }
+                            if (deferred != null) {
+                                // Ensure deferred nodes were evaluated
+                                for (ValueNode node : deferred) {
+                                    assert hasOperand(node);
+                                }
+                            }
+                            return opIndex - i;
+                        } else {
+                            // This isn't true failure, it just means there wasn't match for the
+                            // pattern. Usually that means it's just not supported by the backend.
+                            MemoryFoldFailed.increment();
+                            return 0;
+                        }
+                    } else {
+                        MemoryFoldFailedNonAdjacent.increment();
+                    }
+                } else {
+                    // memory usage which isn't considered lowerable. Mostly these are
+                    // uninteresting but it might be worth looking at to ensure that interesting
+                    // nodes are being properly handled.
+                    // Debug.log("usage isn't lowerable %1s", access.usages().first());
+                }
+            }
+        }
+        return 0;
+    }
+
     protected abstract boolean peephole(ValueNode valueNode);
 
     private boolean hasBlockEnd(Block block) {
@@ -336,7 +507,7 @@
 
         Debug.log("Visiting %s", instr);
         emitNode(instr);
-        Debug.log("Operand for %s = %s", instr, operand(instr));
+        Debug.log("Operand for %s = %s", instr, getOperand(instr));
     }
 
     protected void emitNode(ValueNode node) {
@@ -459,7 +630,7 @@
 
     private Value operandForPhi(PhiNode phi) {
         assert phi.type() == PhiType.Value : "wrong phi type: " + phi;
-        Value result = operand(phi);
+        Value result = getOperand(phi);
         if (result == null) {
             // allocate a variable for this phi
             Variable newOperand = gen.newVariable(getPhiKind(phi));
@@ -622,7 +793,7 @@
      * This method tries to create a switch implementation that is optimal for the given switch. It
      * will either generate a sequential if/then/else cascade, a set of range tests or a table
      * switch.
-     * 
+     *
      * If the given switch does not contain int keys, it will always create a sequential
      * implementation.
      */
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Wed Mar 26 20:44:11 2014 +0100
@@ -25,15 +25,29 @@
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
 public class LowTier extends PhaseSuite<LowTierContext> {
 
+    static class Options {
+
+        // @formatter:off
+        @Option(help = "")
+        public static final OptionValue<Boolean> ProfileCompiledMethods = new OptionValue<>(false);
+        // @formatter:on
+
+    }
+
     public LowTier() {
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue());
 
+        if (Options.ProfileCompiledMethods.getValue()) {
+            appendPhase(new ProfileCompiledMethodsPhase());
+        }
+
         appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER));
 
         appendPhase(new RemoveValueProxyPhase());
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Wed Mar 26 20:44:11 2014 +0100
@@ -356,7 +356,9 @@
 
     /**
      * Prints a message to the current debug scope's logging stream. This method must only be called
-     * if debugging is {@linkplain Debug#isEnabled() enabled}.
+     * if debugging is {@linkplain Debug#isEnabled() enabled} as it incurs allocation at the call
+     * site. If possible, call one of the other {@code log()} methods in this class that take a
+     * fixed number of parameters.
      * 
      * @param format a format string
      * @param args the arguments referenced by the format specifiers in {@code format}
@@ -369,6 +371,17 @@
     }
 
     /**
+     * This override exists the catch cases when log is called with one argument from a method which
+     * is vararg. It will bind to this method instead of the single arg variant and produce a
+     * deprecation warning instead of silently wrapping the Object[] inside of another Object[].
+     */
+    @Deprecated
+    public static void log(String format, Object[] args) {
+        assert false : "shouldn't use this";
+        logv(format, args);
+    }
+
+    /**
      * The same as {@link #log}, but without line termination and without indentation.
      */
     public static void printf(String msg, Object... args) {
@@ -443,6 +456,73 @@
         return noLoggerInstance;
     }
 
+    /**
+     * A convenience function which combines enabling/disabling of logging and
+     * {@link #logAndIndent(String, Object...)}. Note: Use this method with care because it
+     * overrules the -G:Log option.
+     * 
+     * @param enabled Flag for enabling or disabling logging
+     * @param msg The format string of the log message
+     * @param args The arguments referenced by the log message string
+     * @return The new indentation level
+     * @see Indent#logAndIndent
+     */
+    public static Indent logAndIndent(boolean enabled, String msg, Object... args) {
+        if (ENABLED) {
+            Collection<DebugDumpHandler> dumpHandlers;
+            PrintStream output;
+            DebugConfig currentConfig = DebugScope.getConfig();
+            if (currentConfig != null) {
+                dumpHandlers = currentConfig.dumpHandlers();
+                output = currentConfig.output();
+            } else {
+                dumpHandlers = Collections.<DebugDumpHandler> emptyList();
+                output = System.out;
+            }
+            DebugConfigScope configScope = new DebugConfigScope(Debug.fixedConfig(enabled, Debug.isDumpEnabled(), false, false, dumpHandlers, output));
+            return new IndentWithEnable(Debug.logAndIndent(msg, args), configScope);
+        }
+        return noLoggerInstance;
+    }
+
+    private static class IndentWithEnable implements Indent {
+
+        Indent delegate;
+        DebugConfigScope configScope;
+
+        IndentWithEnable(Indent delegate, DebugConfigScope configScope) {
+            this.delegate = delegate;
+            this.configScope = configScope;
+        }
+
+        @Override
+        public void log(String msg, Object... args) {
+            delegate.log(msg, args);
+        }
+
+        @Override
+        public Indent indent() {
+            return delegate.indent();
+        }
+
+        @Override
+        public Indent logAndIndent(String msg, Object... args) {
+            return delegate.logAndIndent(msg, args);
+        }
+
+        @Override
+        public Indent outdent() {
+            configScope.close();
+            return delegate.outdent();
+        }
+
+        @Override
+        public void close() {
+            configScope.close();
+            delegate.close();
+        }
+    }
+
     public static Iterable<Object> context() {
         if (ENABLED) {
             return DebugScope.getInstance().getCurrentContext();
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -44,6 +44,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
@@ -152,6 +153,10 @@
         return ((AMD64HotSpotLIRGenerationResult) res).getStub() != null;
     }
 
+    public void emitData(AllocatableValue dst, byte[] data) {
+        append(new LeaDataOp(dst, data));
+    }
+
     private LIRFrameState currentRuntimeCallInfo;
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.compiler.amd64.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.data.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * Specialized code gen for comparison with compressed memory.
+ */
+
+public class AMD64HotSpotMemoryPeephole extends AMD64MemoryPeephole {
+    public static class CompareMemoryCompressedOp extends AMD64LIRInstruction {
+        @Alive({COMPOSITE}) protected AMD64AddressValue x;
+        @Use({CONST}) protected Value y;
+        @State protected LIRFrameState state;
+
+        public CompareMemoryCompressedOp(AMD64AddressValue x, Constant y, LIRFrameState state) {
+            this.x = x;
+            this.y = y;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            Constant constant = (Constant) y;
+            if (constant.isNull()) {
+                masm.cmpl(x.toAddress(), 0);
+            } else {
+                if (y.getKind() == Kind.Object) {
+                    crb.recordInlineDataInCode(new OopData(0, constant.asObject(), true));
+                } else if (y.getKind() == Kind.Long) {
+                    crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), constant.getPrimitiveAnnotation(), true));
+                } else {
+                    throw GraalInternalError.shouldNotReachHere();
+                }
+                if (state != null) {
+                    crb.recordImplicitException(masm.position(), state);
+                }
+                masm.cmpl(x.toAddress(), 0xdeaddead);
+            }
+        }
+    }
+
+    AMD64HotSpotMemoryPeephole(AMD64NodeLIRGenerator gen) {
+        super(gen);
+    }
+
+    @Override
+    protected boolean emitCompareBranchMemory(ValueNode left, ValueNode right, Access access, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel,
+                    double trueLabelProbability) {
+        assert left == access || right == access;
+        ValueNode other = left == access ? right : left;
+        Kind kind = access.nullCheckLocation().getValueKind();
+
+        if (other.isConstant() && kind == Kind.Object && access.isCompressible()) {
+            ensureEvaluated(other);
+            gen.append(new CompareMemoryCompressedOp(makeAddress(access), other.asConstant(), getState(access)));
+            Condition finalCondition = right == access ? cond.mirror() : cond;
+            gen.append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
+            return true;
+        }
+
+        return super.emitCompareBranchMemory(left, right, access, cond, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -59,6 +59,7 @@
 
     public AMD64HotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult res, LIRGenerator gen) {
         super(graph, res, gen);
+        memoryPeephole = new AMD64HotSpotMemoryPeephole(this);
     }
 
     private AMD64HotSpotLIRGenerator getGen() {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Wed Mar 26 20:44:11 2014 +0100
@@ -82,7 +82,7 @@
         NodeIterable<MethodCallTargetNode> calls = graph.getNodes(MethodCallTargetNode.class);
         assert calls.count() == 1;
         ResolvedJavaMethod lambdaMethod = calls.first().targetMethod();
-        Debug.log("target ... " + lambdaMethod);
+        Debug.log("target ... %s", lambdaMethod);
 
         if (lambdaMethod == null) {
             Debug.log("Did not find call in accept()");
@@ -115,7 +115,7 @@
                 getHSAILBackend().executeKernel(code, jobSize, args);
                 return true;
             } catch (InvalidInstalledCodeException iice) {
-                Debug.log("WARNING: Invalid installed code at exec time." + iice);
+                Debug.log("WARNING: Invalid installed code at exec time: %s", iice);
                 iice.printStackTrace();
                 return false;
             }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -31,6 +31,8 @@
 import com.oracle.graal.compiler.hsail.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall1ArgOp;
@@ -57,6 +59,11 @@
         this.config = config;
     }
 
+    @Override
+    public HotSpotProviders getProviders() {
+        return (HotSpotProviders) super.getProviders();
+    }
+
     int getLogMinObjectAlignment() {
         return config.logMinObjAlignment();
     }
@@ -131,6 +138,9 @@
                 if (isCompressed) {
                     if ((c.getKind() == Kind.Object) && c.isNull()) {
                         append(new StoreConstantOp(Kind.Int, storeAddress, Constant.forInt(0), state));
+                    } else if (c.getKind() == Kind.Long) {
+                        Constant value = compress(c, config.getKlassEncoding());
+                        append(new StoreConstantOp(Kind.Int, storeAddress, value, state));
                     } else {
                         throw GraalInternalError.shouldNotReachHere("can't handle: " + access);
                     }
@@ -194,4 +204,14 @@
         // this version of emitForeignCall not used for now
     }
 
+    /**
+     * @return a compressed version of the incoming constant lifted from AMD64HotSpotLIRGenerator
+     */
+    protected static Constant compress(Constant c, CompressEncoding encoding) {
+        if (c.getKind() == Kind.Long) {
+            return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -28,6 +28,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.hsail.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
@@ -85,4 +87,14 @@
         setResult(node, nodeResult);
     }
 
+    /**
+     * @return a compressed version of the incoming constant lifted from AMD64HotSpotLIRGenerator
+     */
+    protected static Constant compress(Constant c, CompressEncoding encoding) {
+        if (c.getKind() == Kind.Long) {
+            return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Wed Mar 26 20:44:11 2014 +0100
@@ -250,7 +250,7 @@
 
         ValueNode[] launchArgsArray = args.values().toArray(new ValueNode[args.size()]);
         ForeignCallNode result = append(new ForeignCallNode(providers.getForeignCalls(), CALL_KERNEL, launchArgsArray));
-        result.setDeoptimizationState(fs);
+        result.setStateAfter(fs);
 
         InvokeNode getObjectResult = null;
         ValueNode returnValue;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Mar 26 20:44:11 2014 +0100
@@ -31,6 +31,7 @@
 import static com.oracle.graal.phases.common.InliningUtil.*;
 
 import java.io.*;
+import java.lang.management.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -40,7 +41,7 @@
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.baseline.*;
-import com.oracle.graal.compiler.CompilerThreadFactory.CompilerThread;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
@@ -108,6 +109,12 @@
 
     private boolean blocking;
 
+    /**
+     * A {@link com.sun.management.ThreadMXBean} to be able to query some information about the
+     * current compiler thread, e.g. total allocated bytes.
+     */
+    private final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
+
     public CompilationTask(HotSpotBackend backend, HotSpotResolvedJavaMethod method, int entryBCI, boolean blocking) {
         this.backend = backend;
         this.method = method;
@@ -210,9 +217,11 @@
          */
 
         HotSpotVMConfig config = backend.getRuntime().getConfig();
+        final long threadId = Thread.currentThread().getId();
         long previousInlinedBytecodes = InlinedBytecodes.getCurrentValue();
         long previousCompilationTime = CompilationTime.getCurrentValue();
         HotSpotInstalledCode installedCode = null;
+
         try (TimerCloseable a = CompilationTime.start()) {
             if (!tryToChangeStatus(CompilationStatus.Queued, CompilationStatus.Running)) {
                 return;
@@ -237,7 +246,9 @@
 
             CompilationResult result = null;
             TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
-            long start = System.currentTimeMillis();
+            final long start = System.currentTimeMillis();
+            final long allocatedBytesBefore = threadMXBean.getThreadAllocatedBytes(threadId);
+
             try (Scope s = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) {
 
                 if (UseBaselineCompiler.getValue() == true) {
@@ -281,10 +292,18 @@
             } finally {
                 filter.remove();
                 final boolean printAfterCompilation = PrintAfterCompilation.getValue() && !TTY.isSuppressed();
-                if (printAfterCompilation) {
-                    TTY.println(getMethodDescription() + String.format(" | %4dms %5dB", System.currentTimeMillis() - start, (result != null ? result.getTargetCodeSize() : -1)));
-                } else if (printCompilation) {
-                    TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, (result != null ? result.getTargetCodeSize() : -1)));
+
+                if (printAfterCompilation || printCompilation) {
+                    final long stop = System.currentTimeMillis();
+                    final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
+                    final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId);
+                    final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
+
+                    if (printAfterCompilation) {
+                        TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes));
+                    } else if (printCompilation) {
+                        TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dms %5dB %5dkB", id, "", "", "", stop - start, targetCodeSize, allocatedBytes));
+                    }
                 }
             }
 
@@ -296,7 +315,6 @@
                 }
             }
             stats.finish(method, installedCode);
-
         } catch (BailoutException bailout) {
             BAILOUTS.increment();
             if (ExitVMOnBailout.getValue()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Mar 26 20:44:11 2014 +0100
@@ -1022,8 +1022,15 @@
     @HotSpotVMField(name = "Method::_access_flags", type = "AccessFlags", get = HotSpotVMField.Type.OFFSET) @Stable public int methodAccessFlagsOffset;
     @HotSpotVMField(name = "Method::_constMethod", type = "ConstMethod*", get = HotSpotVMField.Type.OFFSET) @Stable public int methodConstMethodOffset;
     @HotSpotVMField(name = "Method::_intrinsic_id", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int methodIntrinsicIdOffset;
+    @HotSpotVMField(name = "Method::_flags", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int methodFlagsOffset;
     @HotSpotVMField(name = "Method::_vtable_index", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodVtableIndexOffset;
 
+    @HotSpotVMConstant(name = "Method::_jfr_towrite") @Stable public int methodFlagsJfrTowrite;
+    @HotSpotVMConstant(name = "Method::_caller_sensitive") @Stable public int methodFlagsCallerSensitive;
+    @HotSpotVMConstant(name = "Method::_force_inline") @Stable public int methodFlagsForceInline;
+    @HotSpotVMConstant(name = "Method::_dont_inline") @Stable public int methodFlagsDontInline;
+    @HotSpotVMConstant(name = "Method::_hidden") @Stable public int methodFlagsHidden;
+
     @HotSpotVMConstant(name = "JVM_ACC_MONITOR_MATCH") @Stable public int jvmAccMonitorMatch;
     @HotSpotVMConstant(name = "JVM_ACC_HAS_MONITOR_BYTECODES") @Stable public int jvmAccHasMonitorBytecodes;
 
@@ -1276,6 +1283,7 @@
     @HotSpotVMConstant(name = "DataLayout::call_type_data_tag") @Stable public int dataLayoutCallTypeDataTag;
     @HotSpotVMConstant(name = "DataLayout::virtual_call_type_data_tag") @Stable public int dataLayoutVirtualCallTypeDataTag;
     @HotSpotVMConstant(name = "DataLayout::parameters_type_data_tag") @Stable public int dataLayoutParametersTypeDataTag;
+    @HotSpotVMConstant(name = "DataLayout::speculative_trap_data_tag") @Stable public int dataLayoutSpeculativeTrapDataTag;
 
     @HotSpotVMFlag(name = "BciProfileWidth") @Stable public int bciProfileWidth;
     @HotSpotVMFlag(name = "TypeProfileWidth") @Stable public int typeProfileWidth;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Mar 26 20:44:11 2014 +0100
@@ -99,12 +99,12 @@
     long getKlassImplementor(long metaspaceKlass);
 
     /**
-     * Initializes a {@link HotSpotResolvedJavaMethod} object from a metaspace Method object.
+     * Determines if a given metaspace method is ignored by security stack walks.
      * 
      * @param metaspaceMethod the metaspace Method object
-     * @param method address of a metaspace Method object
+     * @return true if the method is ignored
      */
-    void initializeMethod(long metaspaceMethod, HotSpotResolvedJavaMethod method);
+    boolean methodIsIgnoredBySecurityStackWalk(long metaspaceMethod);
 
     /**
      * Converts a name to a metaspace klass.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Mar 26 20:44:11 2014 +0100
@@ -104,8 +104,7 @@
     @Override
     public native boolean hasFinalizableSubclass(long metaspaceKlass);
 
-    @Override
-    public native void initializeMethod(long metaspaceMethod, HotSpotResolvedJavaMethod method);
+    public native boolean methodIsIgnoredBySecurityStackWalk(long metaspaceMethod);
 
     @Override
     public native long getClassInitializer(long metaspaceKlass);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Mar 26 20:44:11 2014 +0100
@@ -33,7 +33,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.CompilerThreadFactory.CompilerThread;
 import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Mar 26 20:44:11 2014 +0100
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.debug;
 
 import java.io.*;
-import java.text.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
@@ -36,8 +35,8 @@
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.extended.*;
@@ -83,6 +82,8 @@
         //@formatter:off
         @Option(help = "Turn on the benchmark counters, and displays the results on VM shutdown")
         private static final OptionValue<Boolean> GenericDynamicCounters = new OptionValue<>(false);
+        @Option(help = "Turn on the benchmark counters, and displays the results every n milliseconds")
+        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" +
@@ -109,7 +110,8 @@
         }
         String name = counter.getName();
         String group = counter.getGroup();
-        name = counter.isWithContext() ? name + " @ " + counter.graph().graphId() + ":" + MetaUtil.format("%h.%n", counter.graph().method()) + "#" + group : name + "#" + group;
+        name = counter.isWithContext() && counter.graph().method() != null ? name + " @ " + counter.graph().graphId() + ":" + MetaUtil.format("%h.%n", counter.graph().method()) + "#" + group : name +
+                        "#" + group;
         Integer index = indexes.get(name);
         if (index == null) {
             synchronized (BenchmarkCounters.class) {
@@ -129,15 +131,15 @@
         return index;
     }
 
-    public static synchronized void dump(PrintStream out, double seconds, long[] counters) {
+    public static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) {
         if (!groups.isEmpty()) {
             out.println("====== dynamic counters (" + staticCounters.size() + " in total) ======");
             for (String group : new TreeSet<>(groups)) {
                 if (group != null) {
                     if (DUMP_STATIC) {
-                        dumpCounters(out, seconds, counters, true, group);
+                        dumpCounters(out, seconds, counters, true, group, maxRows);
                     }
-                    dumpCounters(out, seconds, counters, false, group);
+                    dumpCounters(out, seconds, counters, false, group, maxRows);
                 }
             }
             out.println("============================");
@@ -150,9 +152,10 @@
         delta = counters;
     }
 
-    private static synchronized void dumpCounters(PrintStream out, double seconds, long[] counters, boolean staticCounter, String group) {
+    private static synchronized void dumpCounters(PrintStream out, double seconds, long[] counters, boolean staticCounter, String group, int maxRows) {
         TreeMap<Long, String> sorted = new TreeMap<>();
 
+        // collect the numbers
         long[] array;
         if (staticCounter) {
             array = new long[indexes.size()];
@@ -165,6 +168,7 @@
                 array[i] -= delta[i];
             }
         }
+        // sort the counters by putting them into a sorted map
         long sum = 0;
         for (Map.Entry<String, Integer> entry : indexes.entrySet()) {
             int index = entry.getValue();
@@ -175,41 +179,51 @@
         }
 
         if (sum > 0) {
-            NumberFormat format = NumberFormat.getInstance(Locale.US);
             long cutoff = sorted.size() < 10 ? 1 : Math.max(1, sum / 100);
+            int cnt = sorted.size();
+
+            // remove everything below cutoff and keep at most maxRows
+            Iterator<Map.Entry<Long, String>> iter = sorted.entrySet().iterator();
+            while (iter.hasNext()) {
+                Map.Entry<Long, String> entry = iter.next();
+                long counter = entry.getKey() / array.length;
+                if (counter < cutoff || cnt > maxRows) {
+                    iter.remove();
+                }
+                cnt--;
+            }
+
             if (staticCounter) {
                 out.println("=========== " + group + " (static counters):");
                 for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                     long counter = entry.getKey() / array.length;
-                    if (counter >= cutoff) {
-                        out.println(format.format(counter) + " \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
-                    }
+                    out.format(Locale.US, "%,19d %3d%%  %s\n", counter, percentage(counter, sum), entry.getValue());
                 }
-                out.println(sum + ": total");
+                out.format(Locale.US, "%,19d total\n", sum);
             } else {
                 if (group.startsWith("~")) {
                     out.println("=========== " + group + " (dynamic counters), time = " + seconds + " s:");
                     for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                         long counter = entry.getKey() / array.length;
-                        if (counter >= cutoff) {
-                            out.println(format.format((long) (counter / seconds)) + "/s \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
-                        }
+                        out.format(Locale.US, "%,19d/s %3d%%  %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue());
                     }
-                    out.println(format.format((long) (sum / seconds)) + "/s: total");
+                    out.format(Locale.US, "%,19d/s total\n", (long) (sum / seconds));
                 } else {
                     out.println("=========== " + group + " (dynamic counters):");
                     for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                         long counter = entry.getKey() / array.length;
-                        if (counter >= cutoff) {
-                            out.println(format.format(counter) + " \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
-                        }
+                        out.format(Locale.US, "%,19d %3d%%  %s\n", counter, percentage(counter, sum), entry.getValue());
                     }
-                    out.println(format.format(sum) + ": total");
+                    out.format(Locale.US, "%,19d total\n", sum);
                 }
             }
         }
     }
 
+    private static long percentage(long counter, long sum) {
+        return (counter * 200 + 1) / sum / 2;
+    }
+
     public abstract static class CallbackOutputStream extends OutputStream {
 
         protected final PrintStream delegate;
@@ -282,7 +296,7 @@
                     case 2:
                         if (waitingForEnd) {
                             waitingForEnd = false;
-                            BenchmarkCounters.dump(delegate, (System.nanoTime() - startTime) / 1000000000d, compilerToVM.collectCounters());
+                            BenchmarkCounters.dump(delegate, (System.nanoTime() - startTime) / 1000000000d, compilerToVM.collectCounters(), 100);
                         }
                         break;
                 }
@@ -309,20 +323,43 @@
         if (Options.GenericDynamicCounters.getValue()) {
             enabled = true;
         }
-        if (Options.GenericDynamicCounters.getValue() || Options.BenchmarkDynamicCounters.getValue() != null) {
+        if (Options.TimedDynamicCounters.getValue() > 0) {
+            Thread thread = new Thread() {
+                long lastTime = System.nanoTime();
+                PrintStream out = System.out;
+
+                @Override
+                public void run() {
+                    while (true) {
+                        try {
+                            Thread.sleep(Options.TimedDynamicCounters.getValue());
+                        } catch (InterruptedException e) {
+                        }
+                        long time = System.nanoTime();
+                        dump(out, (time - lastTime) / 1000000000d, compilerToVM.collectCounters(), 10);
+                        lastTime = time;
+                    }
+                }
+            };
+            thread.setDaemon(true);
+            thread.setPriority(Thread.MAX_PRIORITY);
+            thread.start();
+            enabled = true;
+        }
+        if (enabled) {
             clear(compilerToVM.collectCounters());
         }
     }
 
     public static void shutdown(CompilerToVM compilerToVM, long compilerStartTime) {
         if (Options.GenericDynamicCounters.getValue()) {
-            dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d, compilerToVM.collectCounters());
+            dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d, compilerToVM.collectCounters(), 100);
         }
     }
 
     public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) {
         StructuredGraph graph = counter.graph();
-        if (excludedClassPrefix == null || !counter.graph().method().getDeclaringClass().getName().startsWith(excludedClassPrefix)) {
+        if (excludedClassPrefix == null || (counter.graph().method() != null && !counter.graph().method().getDeclaringClass().getName().startsWith(excludedClassPrefix))) {
 
             ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false));
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Wed Mar 26 20:44:11 2014 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.HotSpotMethodDataAccessor.Tag;
 
 /**
  * Access to a HotSpot MethodData structure (defined in methodData.hpp).
@@ -57,7 +58,11 @@
         new RetData(),
         new BranchData(),
         new MultiBranchData(),
-        new ArgInfoData()
+        new ArgInfoData(),
+        null, // call_type_data_tag
+        null, // virtual_call_type_data_tag
+        null, // parameters_type_data_tag
+        null  // speculative_trap_data_tag
     };
     // @formatter:on
 
@@ -146,9 +151,10 @@
 
     private HotSpotMethodDataAccessor getData(int position) {
         assert position >= 0 : "out of bounds";
-        int tag = AbstractMethodData.readTag(this, position);
-        assert tag >= 0 && tag < PROFILE_DATA_ACCESSORS.length : "illegal tag " + tag;
-        return PROFILE_DATA_ACCESSORS[tag];
+        final Tag tag = AbstractMethodData.readTag(this, position);
+        HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag.getValue()];
+        assert accessor == null || accessor.getTag() == tag : "wrong data accessor " + accessor + " for tag " + tag;
+        return accessor;
     }
 
     private int readUnsignedByte(int position, int offsetInBytes) {
@@ -258,20 +264,21 @@
          */
         private static final int EXCEPTIONS_MASK = 0x2;
 
-        private final int tag;
+        private final Tag tag;
         private final int staticSize;
 
-        protected AbstractMethodData(int tag, int staticSize) {
+        protected AbstractMethodData(Tag tag, int staticSize) {
             this.tag = tag;
             this.staticSize = staticSize;
         }
 
-        public int getTag() {
+        public Tag getTag() {
             return tag;
         }
 
-        public static int readTag(HotSpotMethodData data, int position) {
-            return data.readUnsignedByte(position, config.dataLayoutTagOffset);
+        public static Tag readTag(HotSpotMethodData data, int position) {
+            final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
+            return Tag.getEnum(tag);
         }
 
         @Override
@@ -337,7 +344,7 @@
         private final TriState exceptionSeen;
 
         protected NoMethodData(TriState exceptionSeen) {
-            super(runtime().getConfig().dataLayoutNoTag, NO_DATA_SIZE);
+            super(Tag.No, NO_DATA_SIZE);
             this.exceptionSeen = exceptionSeen;
         }
 
@@ -363,10 +370,10 @@
         private static final int BIT_DATA_NULL_SEEN_FLAG = 0x01;
 
         private BitData() {
-            super(runtime().getConfig().dataLayoutBitDataTag, BIT_DATA_SIZE);
+            super(Tag.BitData, BIT_DATA_SIZE);
         }
 
-        protected BitData(int tag, int staticSize) {
+        protected BitData(Tag tag, int staticSize) {
             super(tag, staticSize);
         }
 
@@ -387,10 +394,10 @@
         private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(0);
 
         public CounterData() {
-            super(runtime().getConfig().dataLayoutCounterDataTag, COUNTER_DATA_SIZE);
+            super(Tag.CounterData, COUNTER_DATA_SIZE);
         }
 
-        protected CounterData(int tag, int staticSize) {
+        protected CounterData(Tag tag, int staticSize) {
             super(tag, staticSize);
         }
 
@@ -416,10 +423,10 @@
         protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(1);
 
         public JumpData() {
-            super(runtime().getConfig().dataLayoutJumpDataTag, JUMP_DATA_SIZE);
+            super(Tag.JumpData, JUMP_DATA_SIZE);
         }
 
-        protected JumpData(int tag, int staticSize) {
+        protected JumpData(Tag tag, int staticSize) {
             super(tag, staticSize);
         }
 
@@ -465,7 +472,7 @@
         protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(2);
         protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(3);
 
-        protected AbstractTypeData(int tag, int staticSize) {
+        protected AbstractTypeData(Tag tag, int staticSize) {
             super(tag, staticSize);
         }
 
@@ -548,7 +555,7 @@
         private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
         public TypeCheckData() {
-            super(runtime().getConfig().dataLayoutReceiverTypeDataTag, TYPE_CHECK_DATA_SIZE);
+            super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE);
         }
 
         @Override
@@ -569,12 +576,12 @@
         private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
         public VirtualCallData() {
-            super(runtime().getConfig().dataLayoutVirtualCallDataTag, VIRTUAL_CALL_DATA_SIZE);
+            super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE);
         }
 
         @Override
         public int getExecutionCount(HotSpotMethodData data, int position) {
-            int typeProfileWidth = config.typeProfileWidth;
+            final int typeProfileWidth = config.typeProfileWidth;
 
             long total = 0;
             for (int i = 0; i < typeProfileWidth; i++) {
@@ -670,7 +677,7 @@
         private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
 
         public RetData() {
-            super(runtime().getConfig().dataLayoutRetDataTag, RET_DATA_SIZE);
+            super(Tag.RetData, RET_DATA_SIZE);
         }
     }
 
@@ -680,7 +687,7 @@
         private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(2);
 
         public BranchData() {
-            super(runtime().getConfig().dataLayoutBranchDataTag, BRANCH_DATA_SIZE);
+            super(Tag.BranchData, BRANCH_DATA_SIZE);
         }
 
         @Override
@@ -712,7 +719,7 @@
         private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(0);
         protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(1);
 
-        public ArrayData(int tag, int staticSize) {
+        public ArrayData(Tag tag, int staticSize) {
             super(tag, staticSize);
         }
 
@@ -740,7 +747,7 @@
         private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
 
         public MultiBranchData() {
-            super(runtime().getConfig().dataLayoutMultiBranchDataTag, MULTI_BRANCH_DATA_SIZE);
+            super(Tag.MultiBranchData, MULTI_BRANCH_DATA_SIZE);
         }
 
         @Override
@@ -822,7 +829,7 @@
         private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
 
         public ArgInfoData() {
-            super(runtime().getConfig().dataLayoutArgInfoDataTag, ARG_INFO_DATA_SIZE);
+            super(Tag.ArgInfoData, ARG_INFO_DATA_SIZE);
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Wed Mar 26 20:44:11 2014 +0100
@@ -22,8 +22,12 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
 
 /**
  * Interface for accessor objects that encapsulate the logic for accessing the different kinds of
@@ -33,11 +37,54 @@
 public interface HotSpotMethodDataAccessor {
 
     /**
-     * Returns the tag stored in the LayoutData header.
+     * {@code DataLayout} tag values.
+     */
+    enum Tag {
+        No(config().dataLayoutNoTag),
+        BitData(config().dataLayoutBitDataTag),
+        CounterData(config().dataLayoutCounterDataTag),
+        JumpData(config().dataLayoutJumpDataTag),
+        ReceiverTypeData(config().dataLayoutReceiverTypeDataTag),
+        VirtualCallData(config().dataLayoutVirtualCallDataTag),
+        RetData(config().dataLayoutRetDataTag),
+        BranchData(config().dataLayoutBranchDataTag),
+        MultiBranchData(config().dataLayoutMultiBranchDataTag),
+        ArgInfoData(config().dataLayoutArgInfoDataTag),
+        CallTypeData(config().dataLayoutCallTypeDataTag),
+        VirtualCallTypeData(config().dataLayoutVirtualCallTypeDataTag),
+        ParametersTypeData(config().dataLayoutParametersTypeDataTag),
+        SpeculativeTrapData(config().dataLayoutSpeculativeTrapDataTag);
+
+        private final int value;
+
+        private Tag(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        private static HotSpotVMConfig config() {
+            return runtime().getConfig();
+        }
+
+        public static Tag getEnum(int value) {
+            for (Tag e : values()) {
+                if (e.value == value) {
+                    return e;
+                }
+            }
+            throw GraalInternalError.shouldNotReachHere("unknown enum value " + value);
+        }
+    }
+
+    /**
+     * Returns the {@link Tag} stored in the LayoutData header.
      * 
-     * @return An integer >= 0 or -1 if not supported.
+     * @return tag stored in the LayoutData header
      */
-    int getTag();
+    Tag getTag();
 
     /**
      * Returns the BCI stored in the LayoutData header.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Mar 26 20:44:11 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -53,10 +53,6 @@
     private final HotSpotResolvedObjectType holder;
     private final HotSpotConstantPool constantPool;
     private final HotSpotSignature signature;
-    private boolean callerSensitive;
-    private boolean forceInline;
-    private boolean dontInline;
-    private boolean ignoredBySecurityStackWalk;
     private HotSpotMethodData methodData;
     private byte[] code;
     private SpeculationLog speculationLog;
@@ -109,8 +105,6 @@
 
         final int signatureIndex = unsafe.getChar(constMethod + config.constMethodSignatureIndexOffset);
         this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex);
-
-        runtime().getCompilerToVM().initializeMethod(metaspaceMethod, this);
     }
 
     /**
@@ -139,11 +133,20 @@
     }
 
     /**
+     * Returns this method's flags ({@code Method::_flags}).
+     * 
+     * @return flags of this method
+     */
+    private int getFlags() {
+        return unsafe.getByte(metaspaceMethod + runtime().getConfig().methodFlagsOffset);
+    }
+
+    /**
      * Returns this method's constant method flags ({@code ConstMethod::_flags}).
      * 
      * @return flags of this method's ConstMethod
      */
-    private long getConstMethodFlags() {
+    private int getConstMethodFlags() {
         return unsafe.getChar(getConstMethod() + runtime().getConfig().constMethodFlagsOffset);
     }
 
@@ -169,8 +172,7 @@
      * modifiers as well as the HotSpot internal modifiers.
      */
     public int getAllModifiers() {
-        HotSpotVMConfig config = runtime().getConfig();
-        return unsafe.getInt(metaspaceMethod + config.methodAccessFlagsOffset);
+        return unsafe.getInt(metaspaceMethod + runtime().getConfig().methodAccessFlagsOffset);
     }
 
     @Override
@@ -245,19 +247,36 @@
     }
 
     /**
-     * Returns true if this method has a CallerSensitive annotation.
+     * Returns true if this method has a {@code CallerSensitive} annotation.
      * 
      * @return true if CallerSensitive annotation present, false otherwise
      */
     public boolean isCallerSensitive() {
-        return callerSensitive;
+        return (getFlags() & runtime().getConfig().methodFlagsCallerSensitive) != 0;
+    }
+
+    /**
+     * Returns true if this method has a {@code ForceInline} annotation.
+     * 
+     * @return true if ForceInline annotation present, false otherwise
+     */
+    public boolean isForceInline() {
+        return (getFlags() & runtime().getConfig().methodFlagsForceInline) != 0;
+    }
+
+    /**
+     * Returns true if this method has a {@code DontInline} annotation.
+     * 
+     * @return true if DontInline annotation present, false otherwise
+     */
+    public boolean isDontInline() {
+        return (getFlags() & runtime().getConfig().methodFlagsDontInline) != 0;
     }
 
     /**
      * Manually adds a DontInline annotation to this method.
      */
     public void setNotInlineable() {
-        dontInline = true;
         runtime().getCompilerToVM().doNotInlineOrCompile(metaspaceMethod);
     }
 
@@ -268,7 +287,7 @@
      * @return true if special method ignored by security stack walks, false otherwise
      */
     public boolean ignoredBySecurityStackWalk() {
-        return ignoredBySecurityStackWalk;
+        return runtime().getCompilerToVM().methodIsIgnoredBySecurityStackWalk(metaspaceMethod);
     }
 
     public boolean hasBalancedMonitors() {
@@ -502,7 +521,7 @@
 
     @Override
     public boolean canBeInlined() {
-        if (dontInline) {
+        if (isDontInline()) {
             return false;
         }
         return runtime().getCompilerToVM().canInlineMethod(metaspaceMethod);
@@ -510,7 +529,7 @@
 
     @Override
     public boolean shouldBeInlined() {
-        if (forceInline) {
+        if (isForceInline()) {
             return true;
         }
         return runtime().getCompilerToVM().shouldInlineMethod(metaspaceMethod);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -22,18 +22,17 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
-
-import com.oracle.graal.nodes.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
- * Converts a compile-time constant Java string into a malloc'ed C string. The malloc'ed string is
- * never reclaimed so this should only be used for strings in permanent code such as compiled stubs.
+ * Converts a compile-time constant Java string into a C string installed with the generated code.
  */
-public final class CStringNode extends FloatingNode implements Lowerable {
+public final class CStringNode extends FloatingNode implements LIRGenLowerable {
 
     private final String string;
 
@@ -42,16 +41,29 @@
         this.string = string;
     }
 
-    @Override
-    public void lower(LoweringTool tool) {
-        byte[] formatBytes = string.getBytes();
-        long cstring = unsafe.allocateMemory(formatBytes.length + 1);
-        for (int i = 0; i < formatBytes.length; i++) {
-            unsafe.putByte(cstring + i, formatBytes[i]);
+    public void generate(NodeLIRGenerator gen) {
+        gen.setResult(this, emitCString(gen, string));
+    }
+
+    public static AllocatableValue emitCString(NodeLIRGeneratorTool gen, String value) {
+        AllocatableValue dst = gen.getLIRGeneratorTool().newVariable(gen.getLIRGeneratorTool().target().wordKind);
+        gen.getLIRGeneratorTool().emitData(dst, toCString(value));
+        return dst;
+    }
+
+    /**
+     * Converts a string to a null terminated byte array of ASCII characters.
+     * 
+     * @param s a String that must only contain ASCII characters
+     */
+    public static byte[] toCString(String s) {
+        byte[] bytes = new byte[s.length() + 1];
+        for (int i = 0; i < s.length(); i++) {
+            assert s.charAt(i) < 128 : "non-ascii string: " + s;
+            bytes[i] = (byte) s.charAt(i);
         }
-        unsafe.putByte(cstring + formatBytes.length, (byte) 0);
-        ConstantNode replacement = ConstantNode.forLong(cstring, graph());
-        graph().replaceFloating(this, replacement);
+        bytes[s.length()] = 0;
+        return bytes;
     }
 
     @NodeIntrinsic(setStampFromReturnType = true)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Wed Mar 26 20:44:11 2014 +0100
@@ -25,7 +25,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
-public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode {
+public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore {
 
     @Input private FrameState deoptimizationState;
     private final boolean nullCheck;
@@ -55,17 +55,13 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
+    public FrameState stateBefore() {
         return deoptimizationState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState state) {
+    public void setStateBefore(FrameState state) {
         updateUsages(deoptimizationState, state);
         deoptimizationState = state;
     }
-
-    public FrameState getState() {
-        return deoptimizationState;
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -22,6 +22,9 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.hotspot.nodes.CStringNode.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
@@ -47,14 +50,22 @@
 
     @Override
     public void generate(NodeLIRGeneratorTool gen) {
-        String whereString = "in compiled code for " + graph();
-
-        // As these strings will end up embedded as oops in the code, they
-        // must be interned or else they will cause the nmethod to be unloaded
-        // (nmethods are a) weak GC roots and b) unloaded if any of their
-        // embedded oops become unreachable).
-        Constant whereArg = Constant.forObject(whereString.intern());
-        Constant formatArg = Constant.forObject(format.intern());
+        String whereString;
+        if (stateBefore() != null) {
+            String nl = CodeUtil.NEW_LINE;
+            StringBuilder sb = new StringBuilder("in compiled code associated with frame state:");
+            FrameState fs = stateBefore();
+            while (fs != null) {
+                MetaUtil.appendLocation(sb.append(nl).append("\t"), fs.method(), fs.bci);
+                fs = fs.outerFrameState();
+            }
+            whereString = sb.toString();
+        } else {
+            ResolvedJavaMethod method = graph().method();
+            whereString = "in compiled code for " + (method == null ? graph().toString() : format("%H.%n(%p)", method));
+        }
+        Value whereArg = emitCString(gen, whereString);
+        Value formatArg = emitCString(gen, format);
 
         ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(VMErrorNode.VM_ERROR);
         gen.getLIRGeneratorTool().emitForeignCall(linkage, null, whereArg, formatArg, gen.operand(value));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -68,9 +68,9 @@
 
     protected static void addG1PreWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean doLoad, boolean nullCheck, StructuredGraph graph) {
         G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(object, value, location, doLoad, nullCheck));
-        preBarrier.setDeoptimizationState(node.getDeoptimizationState());
+        preBarrier.setStateBefore(node.stateBefore());
         node.setNullCheck(false);
-        node.setDeoptimizationState(null);
+        node.setStateBefore(null);
         graph.addBeforeFixed(node, preBarrier);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Wed Mar 26 20:44:11 2014 +0100
@@ -27,7 +27,6 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.Options.*;
 import static com.oracle.graal.nodes.PiArrayNode.*;
-import static com.oracle.graal.nodes.PiNode.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
@@ -251,7 +250,7 @@
      * Computes the size of the memory chunk allocated for an array. This size accounts for the
      * array header size, boy size and any padding after the last element to satisfy object
      * alignment requirements.
-     * 
+     *
      * @param length the number of elements in the array
      * @param alignment the object alignment requirement
      * @param headerSize the size of the array header
@@ -285,7 +284,7 @@
     /**
      * Zero uninitialized memory in a newly allocated object, unrolling as necessary and ensuring
      * that stores are aligned.
-     * 
+     *
      * @param size number of bytes to zero
      * @param memory beginning of object which is being zeroed
      * @param constantSize is @ size} known to be constant in the snippet
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Mar 26 20:44:11 2014 +0100
@@ -652,7 +652,7 @@
                 }
                 sb.append(n);
             }
-            Debug.log(sb.toString());
+            Debug.log("%s", sb);
         }
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -140,7 +140,7 @@
          * the jump. When the block is seen the second time, a {@link MergeNode} is created to
          * correctly merge the now two different predecessor states.
          */
-        private static class BlockPlaceholderNode extends FixedWithNextNode {
+        protected static class BlockPlaceholderNode extends FixedWithNextNode {
 
             /*
              * Cannot be explicitly declared as a Node type since it is not an input; would cause
@@ -240,6 +240,7 @@
             }
             frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true);
             ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
+            finishPrepare(lastInstr);
 
             if (graphBuilderConfig.eagerInfopointMode()) {
                 InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START, frameState.create(0)));
@@ -287,6 +288,15 @@
             indent.outdent();
         }
 
+        /**
+         * A hook for derived classes to modify the graph start instruction or append new
+         * instructions to it.
+         * 
+         * @param startInstr The start instruction of the graph.
+         */
+        protected void finishPrepare(FixedWithNextNode startInstr) {
+        }
+
         private BciBlock unwindBlock(int bci) {
             if (unwindBlock == null) {
                 unwindBlock = new ExceptionDispatchBlock();
@@ -306,6 +316,10 @@
             return stream.currentBCI();
         }
 
+        private void loadLocal(int index, Kind kind) {
+            frameState.push(kind, frameState.loadLocal(index));
+        }
+
         private void storeLocal(Kind kind, int index) {
             ValueNode value;
             if (kind == Kind.Object) {
@@ -452,7 +466,7 @@
                 dispatchState.setRethrowException(true);
             }
             FixedNode target = createTarget(dispatchBlock, dispatchState);
-            dispatchBegin.setNext(target);
+            finishInstruction(dispatchBegin, dispatchState).setNext(target);
             return dispatchBegin;
         }
 
@@ -1110,7 +1124,7 @@
         private void genInvokeInterface(JavaMethod target) {
             if (target instanceof ResolvedJavaMethod) {
                 ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
-                genInvokeIndirect(InvokeKind.Interface, (ResolvedJavaMethod) target, args);
+                appendInvoke(InvokeKind.Interface, (ResolvedJavaMethod) target, args);
             } else {
                 handleUnresolvedInvoke(target, InvokeKind.Interface);
             }
@@ -1145,7 +1159,7 @@
                 }
                 ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver));
                 if (hasReceiver) {
-                    genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
+                    appendInvoke(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
                 } else {
                     appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args);
                 }
@@ -1160,47 +1174,12 @@
                 assert target != null;
                 assert target.getSignature() != null;
                 ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
-                invokeDirect((ResolvedJavaMethod) target, args);
+                appendInvoke(InvokeKind.Special, (ResolvedJavaMethod) target, args);
             } else {
                 handleUnresolvedInvoke(target, InvokeKind.Special);
             }
         }
 
-        private void genInvokeIndirect(InvokeKind invokeKind, ResolvedJavaMethod target, ValueNode[] args) {
-            ValueNode receiver = args[0];
-            // attempt to devirtualize the call
-            ResolvedJavaType klass = target.getDeclaringClass();
-
-            // 0. check for trivial cases
-            if (target.canBeStaticallyBound()) {
-                // check for trivial cases (e.g. final methods, nonvirtual methods)
-                invokeDirect(target, args);
-                return;
-            }
-            // 1. check if the exact type of the receiver can be determined
-            ResolvedJavaType exact = klass.asExactType();
-            if (exact == null && receiver.stamp() instanceof ObjectStamp) {
-                ObjectStamp receiverStamp = (ObjectStamp) receiver.stamp();
-                if (receiverStamp.isExactType()) {
-                    exact = receiverStamp.type();
-                }
-            }
-            if (exact != null) {
-                // either the holder class is exact, or the receiver object has an exact type
-                ResolvedJavaMethod exactMethod = exact.resolveMethod(target);
-                if (exactMethod != null) {
-                    invokeDirect(exactMethod, args);
-                    return;
-                }
-            }
-            // devirtualization failed, produce an actual invokevirtual
-            appendInvoke(invokeKind, target, args);
-        }
-
-        private void invokeDirect(ResolvedJavaMethod target, ValueNode[] args) {
-            appendInvoke(InvokeKind.Special, target, args);
-        }
-
         private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) {
             Kind resultType = targetMethod.getSignature().getReturnKind();
             if (DeoptALot.getValue()) {
@@ -1787,6 +1766,8 @@
             assert lastInstr.next() == null : "instructions already appended at block " + block;
             Debug.log("  frameState: %s", frameState);
 
+            lastInstr = finishInstruction(lastInstr, frameState);
+
             int endBCI = stream.endBCI();
 
             stream.setBCI(block.startBci);
@@ -1836,6 +1817,7 @@
                         }
                     }
                 }
+                lastInstr = finishInstruction(lastInstr, frameState);
                 if (bci < endBCI) {
                     if (bci > block.endBci) {
                         assert !block.getSuccessor(0).isExceptionEntry;
@@ -1848,6 +1830,17 @@
             }
         }
 
+        /**
+         * A hook for derived classes to modify the last instruction or add other instructions.
+         * 
+         * @param instr The last instruction (= fixed node) which was added.
+         * @param state The current frame state.
+         * @Returns Returns the (new) last instruction.
+         */
+        protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, HIRFrameStateBuilder state) {
+            return instr;
+        }
+
         private final int traceLevel = Options.TraceBytecodeParserLevel.getValue();
 
         private void traceState() {
@@ -2096,7 +2089,7 @@
                 if (!currentBlock.jsrScope.isEmpty()) {
                     sb.append(' ').append(currentBlock.jsrScope);
                 }
-                Debug.log(sb.toString());
+                Debug.log("%s", sb);
             }
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_getfield1.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007, 2012, 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.jtt.except;
+
+import com.oracle.graal.jtt.*;
+
+import org.junit.*;
+
+public class BC_getfield1 extends JTTTest {
+
+    private int field = 13;
+
+    public static void test(BC_getfield1 arg) {
+        @SuppressWarnings("unused")
+        int i = arg.field;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", (Object) null);
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        // tests that the null check isn't removed along with the read
+        runTest(EMPTY, true, true, "test", (Object) null);
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        runTest("test", new BC_getfield1());
+    }
+
+}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Wed Mar 26 20:44:11 2014 +0100
@@ -49,6 +49,7 @@
     I2F, I2D,
     L2F, L2D,
     MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L,
+    MOV_B2UI, MOV_B2UL, // Zero extending byte loads
 
     /*
      * Converts a float/double to an int/long. The result of the conversion does not comply with Java semantics
@@ -102,6 +103,32 @@
     }
 
     /**
+     * Unary operation with separate memory source and destination operand.
+     */
+    public static class Unary2MemoryOp extends AMD64LIRInstruction {
+
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE}) protected AMD64AddressValue x;
+        @State protected LIRFrameState state;
+
+        public Unary2MemoryOp(AMD64Arithmetic opcode, AllocatableValue result, AMD64AddressValue x, LIRFrameState state) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            if (state != null) {
+                crb.recordImplicitException(masm.position(), state);
+            }
+            emit(crb, masm, opcode, result, x, null);
+        }
+    }
+
+    /**
      * Binary operation with two operands. The first source operand is combined with the
      * destination. The second source operand may be a stack slot.
      */
@@ -135,6 +162,45 @@
 
     /**
      * Binary operation with two operands. The first source operand is combined with the
+     * destination. The second source operand may be a stack slot.
+     */
+    public static class BinaryMemory extends AMD64LIRInstruction {
+
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG}) protected AllocatableValue x;
+        protected final Kind kind;
+        @Alive({COMPOSITE}) protected AMD64AddressValue location;
+        @State protected LIRFrameState state;
+
+        public BinaryMemory(AMD64Arithmetic opcode, Kind kind, AllocatableValue result, AllocatableValue x, AMD64AddressValue location, LIRFrameState state) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.location = location;
+            this.kind = kind;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            AMD64Move.move(crb, masm, result, x);
+            if (state != null) {
+                crb.recordImplicitException(masm.position(), state);
+            }
+            emit(crb, masm, opcode, result, location, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            assert differentRegisters(result, location) || sameRegister(x, location);
+            // verifyKind(opcode, result, x, location);
+        }
+    }
+
+    /**
+     * Binary operation with two operands. The first source operand is combined with the
      * destination. The second source operand must be a register.
      */
     public static class BinaryRegReg extends AMD64LIRInstruction {
@@ -688,7 +754,8 @@
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
-        } else {
+        } else if (isStackSlot(src)) {
+
             switch (opcode) {
                 case IADD:
                     masm.addl(asIntReg(dst), (AMD64Address) crb.asIntAddr(src));
@@ -819,6 +886,143 @@
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
+        } else {
+            switch (opcode) {
+                case IADD:
+                    masm.addl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case ISUB:
+                    masm.subl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case IAND:
+                    masm.andl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case IMUL:
+                    masm.imull(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case IOR:
+                    masm.orl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case IXOR:
+                    masm.xorl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+
+                case LADD:
+                    masm.addq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case LSUB:
+                    masm.subq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case LMUL:
+                    masm.imulq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case LAND:
+                    masm.andq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case LOR:
+                    masm.orq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case LXOR:
+                    masm.xorq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+
+                case FADD:
+                    masm.addss(asFloatReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case FSUB:
+                    masm.subss(asFloatReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case FMUL:
+                    masm.mulss(asFloatReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case FDIV:
+                    masm.divss(asFloatReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+
+                case DADD:
+                    masm.addsd(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case DSUB:
+                    masm.subsd(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case DMUL:
+                    masm.mulsd(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case DDIV:
+                    masm.divsd(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+
+                case SQRT:
+                    masm.sqrtsd(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+
+                case B2I:
+                    masm.movsbl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case S2I:
+                    masm.movswl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case B2L:
+                    masm.movsbq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case S2L:
+                    masm.movswq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case I2L:
+                    masm.movslq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case F2D:
+                    masm.cvtss2sd(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case D2F:
+                    masm.cvtsd2ss(asFloatReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case I2F:
+                    masm.cvtsi2ssl(asFloatReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case I2D:
+                    masm.cvtsi2sdl(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case L2F:
+                    masm.cvtsi2ssq(asFloatReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case L2D:
+                    masm.cvtsi2sdq(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case F2I:
+                    masm.cvttss2sil(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case D2I:
+                    masm.cvttsd2sil(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case F2L:
+                    masm.cvttss2siq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case D2L:
+                    masm.cvttsd2siq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case MOV_I2F:
+                    masm.movss(asFloatReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case MOV_L2D:
+                    masm.movsd(asDoubleReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case MOV_F2I:
+                    masm.movl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case MOV_D2L:
+                    masm.movq(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case MOV_B2UI:
+                    masm.movzbl(asIntReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+                case MOV_B2UL:
+                    masm.movzbl(asLongReg(dst), ((AMD64AddressValue) src).toAddress());
+                    break;
+
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
         }
 
         if (info != null) {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Wed Mar 26 20:44:11 2014 +0100
@@ -31,7 +31,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
-// @formatter:off
 public enum AMD64Compare {
     ICMP, LCMP, ACMP, FCMP, DCMP;
 
@@ -54,57 +53,152 @@
         @Override
         protected void verify() {
             super.verify();
-            assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
-                || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
-                || (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object)
-                || (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
-                || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+            assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) ||
+                            (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) ||
+                            (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+        }
+    }
+
+    public static class CompareMemoryOp extends AMD64LIRInstruction {
+        @Opcode private final AMD64Compare opcode;
+        @Use({REG, COMPOSITE}) protected Value x;
+        @Use({CONST, COMPOSITE}) protected Value y;
+        @State protected LIRFrameState state;
+
+        /**
+         * Compare memory, constant or register, memory.
+         */
+        public CompareMemoryOp(AMD64Compare opcode, Value x, Value y, LIRFrameState state) {
+            assert (x instanceof AMD64AddressValue && y instanceof Constant) || (x instanceof Variable && y instanceof AMD64AddressValue);
+            this.opcode = opcode;
+            this.x = x;
+            this.y = y;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            if (state != null) {
+                crb.recordImplicitException(masm.position(), state);
+            }
+            emit(crb, masm, opcode, x, y);
+        }
+
+        @Override
+        protected void verify() {
+            super.verify();
+            assert (x instanceof AMD64AddressValue && y instanceof Constant) || (x instanceof Variable && y instanceof AMD64AddressValue);
         }
     }
 
     public static void emit(CompilationResultBuilder crb, AMD64MacroAssembler masm, AMD64Compare opcode, Value x, Value y) {
-        if (isRegister(y)) {
+        if (isRegister(x) && isRegister(y)) {
             switch (opcode) {
-                case ICMP: masm.cmpl(asIntReg(x), asIntReg(y)); break;
-                case LCMP: masm.cmpq(asLongReg(x), asLongReg(y)); break;
-                case ACMP: masm.cmpptr(asObjectReg(x), asObjectReg(y)); break;
-                case FCMP: masm.ucomiss(asFloatReg(x), asFloatReg(y)); break;
-                case DCMP: masm.ucomisd(asDoubleReg(x), asDoubleReg(y)); break;
-                default:   throw GraalInternalError.shouldNotReachHere();
+                case ICMP:
+                    masm.cmpl(asIntReg(x), asIntReg(y));
+                    break;
+                case LCMP:
+                    masm.cmpq(asLongReg(x), asLongReg(y));
+                    break;
+                case ACMP:
+                    masm.cmpptr(asObjectReg(x), asObjectReg(y));
+                    break;
+                case FCMP:
+                    masm.ucomiss(asFloatReg(x), asFloatReg(y));
+                    break;
+                case DCMP:
+                    masm.ucomisd(asDoubleReg(x), asDoubleReg(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
-        } else if (isConstant(y)) {
+        } else if (isRegister(x) && isConstant(y)) {
             boolean isZero = ((Constant) y).isDefaultForKind();
             switch (opcode) {
-                case ICMP: if (isZero) {
-                    masm.testl(asIntReg(x), asIntReg(x));
-                } else {
-                    masm.cmpl(asIntReg(x), crb.asIntConst(y));
-                }
-                break;
-                case LCMP: if (isZero) {
-                    masm.testq(asLongReg(x), asLongReg(x));
-                } else {
-                    masm.cmpq(asLongReg(x), crb.asIntConst(y));
-                }
-                break;
+                case ICMP:
+                    if (isZero) {
+                        masm.testl(asIntReg(x), asIntReg(x));
+                    } else {
+                        masm.cmpl(asIntReg(x), crb.asIntConst(y));
+                    }
+                    break;
+                case LCMP:
+                    if (isZero) {
+                        masm.testq(asLongReg(x), asLongReg(x));
+                    } else {
+                        masm.cmpq(asLongReg(x), crb.asIntConst(y));
+                    }
+                    break;
                 case ACMP:
                     if (isZero) {
-                        masm.testq(asObjectReg(x), asObjectReg(x)); break;
+                        masm.testq(asObjectReg(x), asObjectReg(x));
+                        break;
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons");
                     }
-                case FCMP: masm.ucomiss(asFloatReg(x), (AMD64Address) crb.asFloatConstRef(y)); break;
-                case DCMP: masm.ucomisd(asDoubleReg(x), (AMD64Address) crb.asDoubleConstRef(y)); break;
-                default:   throw GraalInternalError.shouldNotReachHere();
+                case FCMP:
+                    masm.ucomiss(asFloatReg(x), (AMD64Address) crb.asFloatConstRef(y));
+                    break;
+                case DCMP:
+                    masm.ucomisd(asDoubleReg(x), (AMD64Address) crb.asDoubleConstRef(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
-        } else {
+        } else if (isRegister(x) && isStackSlot(y)) {
+            switch (opcode) {
+                case ICMP:
+                    masm.cmpl(asIntReg(x), (AMD64Address) crb.asIntAddr(y));
+                    break;
+                case LCMP:
+                    masm.cmpq(asLongReg(x), (AMD64Address) crb.asLongAddr(y));
+                    break;
+                case ACMP:
+                    masm.cmpptr(asObjectReg(x), (AMD64Address) crb.asObjectAddr(y));
+                    break;
+                case FCMP:
+                    masm.ucomiss(asFloatReg(x), (AMD64Address) crb.asFloatAddr(y));
+                    break;
+                case DCMP:
+                    masm.ucomisd(asDoubleReg(x), (AMD64Address) crb.asDoubleAddr(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isRegister(x) && y instanceof AMD64AddressValue) {
             switch (opcode) {
-                case ICMP: masm.cmpl(asIntReg(x), (AMD64Address) crb.asIntAddr(y)); break;
-                case LCMP: masm.cmpq(asLongReg(x), (AMD64Address) crb.asLongAddr(y)); break;
-                case ACMP: masm.cmpptr(asObjectReg(x), (AMD64Address) crb.asObjectAddr(y)); break;
-                case FCMP: masm.ucomiss(asFloatReg(x), (AMD64Address) crb.asFloatAddr(y)); break;
-                case DCMP: masm.ucomisd(asDoubleReg(x), (AMD64Address) crb.asDoubleAddr(y)); break;
-                default:  throw GraalInternalError.shouldNotReachHere();
+                case ICMP:
+                    masm.cmpl(asIntReg(x), ((AMD64AddressValue) y).toAddress());
+                    break;
+                case LCMP:
+                    masm.cmpq(asLongReg(x), ((AMD64AddressValue) y).toAddress());
+                    break;
+                case ACMP:
+                    masm.cmpptr(asObjectReg(x), ((AMD64AddressValue) y).toAddress());
+                    break;
+                case FCMP:
+                    masm.ucomiss(asFloatReg(x), ((AMD64AddressValue) y).toAddress());
+                    break;
+                case DCMP:
+                    masm.ucomisd(asDoubleReg(x), ((AMD64AddressValue) y).toAddress());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (x instanceof AMD64AddressValue && isConstant(y)) {
+            switch (opcode) {
+                case ICMP:
+                    masm.cmpl(((AMD64AddressValue) x).toAddress(), crb.asIntConst(y));
+                    break;
+                case LCMP:
+                    if (crb.asLongConst(y) == (int) crb.asLongConst(y)) {
+                        masm.cmpq(((AMD64AddressValue) x).toAddress(), (int) crb.asLongConst(y));
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere();
+                    }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         }
     }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Wed Mar 26 20:44:11 2014 +0100
@@ -29,6 +29,7 @@
 
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.RawData;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
@@ -171,6 +172,38 @@
         }
     }
 
+    public static class ZeroExtendLoadOp extends MemOp {
+
+        @Def({REG}) protected AllocatableValue result;
+
+        public ZeroExtendLoadOp(Kind kind, AllocatableValue result, AMD64AddressValue address, LIRFrameState state) {
+            super(kind, address, state);
+            this.result = result;
+        }
+
+        @Override
+        public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            switch (kind) {
+                case Boolean:
+                case Byte:
+                    masm.movzbl(asRegister(result), address.toAddress());
+                    break;
+                case Char:
+                case Short:
+                    masm.movzwl(asRegister(result), address.toAddress());
+                    break;
+                case Int:
+                    masm.movl(asRegister(result), address.toAddress());
+                    break;
+                case Long:
+                    masm.movq(asRegister(result), address.toAddress());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
     public static class StoreOp extends MemOp {
 
         @Use({REG}) protected AllocatableValue input;
@@ -277,6 +310,23 @@
         }
     }
 
+    public static class LeaDataOp extends AMD64LIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        private final byte[] data;
+
+        public LeaDataOp(AllocatableValue result, byte[] data) {
+            this.result = result;
+            this.data = data;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            RawData rawData = new RawData(data, 16);
+            masm.leaq(asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(rawData));
+        }
+    }
+
     public static class StackLeaOp extends AMD64LIRInstruction {
 
         @Def({REG}) protected AllocatableValue result;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011, 2012, 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.lir.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+public class AMD64TestMemoryOp extends AMD64LIRInstruction {
+
+    @Use({COMPOSITE}) protected AMD64AddressValue x;
+    @Use({REG, CONST}) protected Value y;
+    @State protected LIRFrameState state;
+
+    public AMD64TestMemoryOp(AMD64AddressValue x, Value y, LIRFrameState state) {
+        this.x = x;
+        this.y = y;
+        this.state = state;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        if (state != null) {
+            crb.recordImplicitException(masm.position(), state);
+        }
+        emit(crb, masm, x, y);
+    }
+
+    @Override
+    protected void verify() {
+        super.verify();
+        // Can't check the kind of an address so just check the other input
+        assert (x.getKind() == Kind.Int || x.getKind() == Kind.Long) : x + " " + y;
+    }
+
+    public static void emit(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value x, Value y) {
+        if (isRegister(y)) {
+            switch (y.getKind()) {
+                case Int:
+                    masm.testl(asIntReg(y), ((AMD64AddressValue) x).toAddress());
+                    break;
+                case Long:
+                    masm.testq(asLongReg(y), ((AMD64AddressValue) x).toAddress());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(y)) {
+            switch (y.getKind()) {
+                case Int:
+                    masm.testl(((AMD64AddressValue) x).toAddress(), crb.asIntConst(y));
+                    break;
+                case Long:
+                    masm.testq(((AMD64AddressValue) x).toAddress(), crb.asIntConst(y));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Mar 26 20:44:11 2014 +0100
@@ -23,13 +23,32 @@
 package com.oracle.graal.lir.sparc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Add;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsh;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Lduh;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Membar;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Rdpc;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stb;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Sth;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stw;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cas;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Casx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Clr;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setuw;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Wed Mar 26 20:44:11 2014 +0100
@@ -63,7 +63,7 @@
     }
 
     private void findDerived(Collection<BasicInductionVariable> bivs) {
-        Queue<InductionVariable> scanQueue = new LinkedList<InductionVariable>(bivs);
+        Queue<InductionVariable> scanQueue = new LinkedList<>(bivs);
         while (!scanQueue.isEmpty()) {
             InductionVariable baseIv = scanQueue.remove();
             ValueNode baseIvNode = baseIv.valueNode();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Mar 26 20:44:11 2014 +0100
@@ -141,7 +141,7 @@
             BinaryNode result = BinaryNode.reassociate(binary, invariant);
             if (result != binary) {
                 if (Debug.isLogEnabled()) {
-                    Debug.log(MetaUtil.format("%H::%n", Debug.contextLookup(ResolvedJavaMethod.class)) + " : Reassociated %s into %s", binary, result);
+                    Debug.log("%s : Reassociated %s into %s", MetaUtil.format("%H::%n", graph.method()), binary, result);
                 }
                 graph.replaceFloating(binary, result);
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -84,6 +84,6 @@
             }
         }
         sb.append("]");
-        Debug.log(sb.toString());
+        Debug.log("%s", sb);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -30,11 +30,9 @@
  * This node represents an unconditional explicit request for immediate deoptimization.
  * 
  * After this node, execution will continue using a fallback execution engine (such as an
- * interpreter) at the position described by the {@link #getDeoptimizationState() deoptimization
- * state}.
- * 
+ * interpreter) at the position described by the {@link #stateBefore() deoptimization state}.
  */
-public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode {
+public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode.DeoptBefore {
 
     @Input private FrameState deoptState;
 
@@ -48,20 +46,16 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
+    public FrameState stateBefore() {
         return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
+    public void setStateBefore(FrameState f) {
         updateUsages(deoptState, f);
         deoptState = f;
     }
 
-    public FrameState getState() {
-        return deoptState;
-    }
-
     public abstract ValueNode getActionAndReason(MetaAccessProvider metaAccess);
 
     public abstract ValueNode getSpeculation(MetaAccessProvider metaAccess);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -86,7 +86,7 @@
         FixedNode next = next();
         setNext(null);
         DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
-        deopt.setDeoptimizationState(getDeoptimizationState());
+        deopt.setStateBefore(stateBefore());
         IfNode ifNode;
         AbstractBeginNode noDeoptSuccessor;
         if (negated) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Wed Mar 26 20:44:11 2014 +0100
@@ -41,10 +41,6 @@
         stateAfter = x;
     }
 
-    public FrameState getState() {
-        return stateAfter();
-    }
-
     public boolean hasSideEffect() {
         return true;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.nodes.type.*;
 
-public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode {
+public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode.DeoptBefore {
 
     @Input(notDataflow = true) private FrameState deoptState;
 
@@ -33,17 +33,13 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
+    public FrameState stateBefore() {
         return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
+    public void setStateBefore(FrameState f) {
         updateUsages(deoptState, f);
         deoptState = f;
     }
-
-    public FrameState getState() {
-        return deoptState;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -35,14 +35,46 @@
     boolean canDeoptimize();
 
     /**
-     * Gets the deoptimization information associated with this node if any.
+     * Interface for nodes that need a {@link FrameState} for deoptimizing to a point before their
+     * execution.
      */
-    FrameState getDeoptimizationState();
+    public interface DeoptBefore extends DeoptimizingNode {
+
+        /**
+         * Sets the {@link FrameState} describing the program state before the execution of this
+         * node.
+         */
+        void setStateBefore(FrameState state);
+
+        FrameState stateBefore();
+    }
+
+    /**
+     * Interface for nodes that need a {@link FrameState} for deoptimizing to a point after their
+     * execution.
+     */
+    public interface DeoptAfter extends DeoptimizingNode, StateSplit {
+    }
 
     /**
-     * Sets the deoptimization information associated with this node.
-     * 
-     * @param state the {@link FrameState} which represents the deoptimization information
+     * Interface for nodes that need a special {@link FrameState} for deoptimizing during their
+     * execution (e.g. {@link Invoke}).
      */
-    void setDeoptimizationState(FrameState state);
+    public interface DeoptDuring extends DeoptimizingNode, StateSplit {
+
+        FrameState stateDuring();
+
+        /**
+         * Sets the {@link FrameState} describing the program state during the execution of this
+         * node.
+         */
+        void setStateDuring(FrameState state);
+
+        /**
+         * Compute the {@link FrameState} describing the program state during the execution of this
+         * node from an input {@link FrameState} describing the program state after finishing the
+         * execution of this node.
+         */
+        void computeStateDuring(FrameState stateAfter);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -66,7 +66,7 @@
             DeoptimizeNode newDeopt = graph().add(
                             new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), tool.getMetaAccess().decodeDebugId(constant),
                                             speculationConstant));
-            newDeopt.setDeoptimizationState(getDeoptimizationState());
+            newDeopt.setStateBefore(stateBefore());
             return newDeopt;
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -52,7 +52,7 @@
                 }
 
                 DeoptimizeNode deopt = graph().add(new DeoptimizeNode(getAction(), getReason()));
-                deopt.setDeoptimizationState(getDeoptimizationState());
+                deopt.setStateBefore(stateBefore());
                 setNext(deopt);
             }
             this.replaceAtUsages(null);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -42,7 +43,7 @@
  * The {@code IfNode} represents a branch that can go one of two directions depending on the outcome
  * of a comparison.
  */
-public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable {
+public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, MemoryArithmeticLIRLowerable {
 
     @Successor private AbstractBeginNode trueSuccessor;
     @Successor private AbstractBeginNode falseSuccessor;
@@ -131,6 +132,11 @@
     }
 
     @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        return gen.emitIfMemory(this, access);
+    }
+
+    @Override
     public boolean verify() {
         assertTrue(condition() != null, "missing condition");
         assertTrue(trueSuccessor() != null, "missing trueSuccessor");
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -51,7 +51,7 @@
 
     @Override
     public boolean verify() {
-        return getState() != null && super.verify();
+        return state != null && super.verify();
     }
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-public interface Invoke extends StateSplit, Lowerable, DeoptimizingNode, GuardedNode {
+public interface Invoke extends StateSplit, Lowerable, DeoptimizingNode.DeoptDuring, GuardedNode {
 
     FixedNode next();
 
@@ -38,10 +38,6 @@
 
     FixedNode asNode();
 
-    FrameState stateDuring();
-
-    FrameState stateAfter();
-
     Node predecessor();
 
     void intrinsify(Node node);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -133,17 +133,6 @@
     }
 
     @Override
-    public FrameState stateDuring() {
-        FrameState stateAfter = stateAfter();
-        if (stateAfter == null) {
-            return null;
-        }
-        FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), getKind());
-        stateDuring.setDuringCall(true);
-        return stateDuring;
-    }
-
-    @Override
     public void intrinsify(Node node) {
         assert !(node instanceof ValueNode) || (((ValueNode) node).getKind() == Kind.Void) == (getKind() == Kind.Void);
         CallTargetNode call = callTarget;
@@ -174,18 +163,21 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
-        if (deoptState == null) {
-            FrameState stateDuring = stateDuring();
-            updateUsages(deoptState, stateDuring);
-            deoptState = stateDuring;
-        }
+    public FrameState stateDuring() {
         return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
-        throw new IllegalStateException("Cannot set deoptimization state " + f + " for invoke " + this);
+    public void setStateDuring(FrameState stateDuring) {
+        updateUsages(deoptState, stateDuring);
+        deoptState = stateDuring;
+    }
+
+    @Override
+    public void computeStateDuring(FrameState stateAfter) {
+        FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), getKind());
+        stateDuring.setDuringCall(true);
+        setStateDuring(stateDuring);
     }
 
     @Override
@@ -198,14 +190,4 @@
         updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode());
         this.guard = guard;
     }
-
-    @Override
-    public FrameState getState() {
-        if (deoptState != null) {
-            assert stateAfter() == null;
-            return deoptState;
-        } else {
-            return super.getState();
-        }
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -155,13 +155,6 @@
         return LocationIdentity.ANY_LOCATION;
     }
 
-    public FrameState stateDuring() {
-        FrameState tempStateAfter = stateAfter();
-        FrameState stateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), getKind());
-        stateDuring.setDuringCall(true);
-        return stateDuring;
-    }
-
     @Override
     public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
         Map<Object, Object> debugProperties = super.getDebugProperties(map);
@@ -219,18 +212,21 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
-        if (deoptState == null) {
-            FrameState stateDuring = stateDuring();
-            updateUsages(deoptState, stateDuring);
-            deoptState = stateDuring;
-        }
+    public FrameState stateDuring() {
         return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
-        throw new IllegalStateException();
+    public void setStateDuring(FrameState stateDuring) {
+        updateUsages(deoptState, stateDuring);
+        deoptState = stateDuring;
+    }
+
+    @Override
+    public void computeStateDuring(FrameState tempStateAfter) {
+        FrameState stateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), getKind());
+        stateDuring.setDuringCall(true);
+        setStateDuring(stateDuring);
     }
 
     @Override
@@ -244,16 +240,6 @@
         this.guard = guard;
     }
 
-    @Override
-    public FrameState getState() {
-        if (deoptState != null) {
-            assert stateAfter() == null;
-            return deoptState;
-        } else {
-            return stateAfter();
-        }
-    }
-
     public MemoryCheckpoint asMemoryCheckpoint() {
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -83,4 +84,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitAnd(gen.operand(x()), gen.operand(y())));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitAndMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -29,7 +29,7 @@
 /**
  * The {@code LogicNode} class definition.
  */
-public abstract class BitLogicNode extends BinaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
+public abstract class BitLogicNode extends BinaryNode implements ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     /**
      * Constructs a new logic operation node.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
 /* TODO (thomaswue/gdub) For high-level optimization purpose the compare node should be a boolean *value* (it is currently only a helper node)
@@ -34,7 +35,7 @@
  * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed
  * into variants that do not materialize the value (CompareIf, CompareGuard...)
  */
-public abstract class CompareNode extends LogicNode implements Canonicalizable, LIRLowerable {
+public abstract class CompareNode extends LogicNode implements Canonicalizable, LIRLowerable, MemoryArithmeticLIRLowerable {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
@@ -192,4 +193,14 @@
 
         return graph.unique(comparison);
     }
+
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        return false;
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
+        return super.verify();
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -77,10 +78,19 @@
 
     public static boolean livesLonger(ValueNode after, ValueNode value, NodeLIRGeneratorTool gen) {
         for (Node usage : value.usages()) {
-            if (usage != after && usage instanceof ValueNode && gen.operand(((ValueNode) usage)) != null) {
+            if (usage != after && usage instanceof ValueNode && gen.hasOperand(((ValueNode) usage))) {
                 return true;
             }
         }
         return false;
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitAddMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class FloatArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable {
+public abstract class FloatArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
 
     private final boolean isStrictFP;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -33,7 +34,7 @@
  * A {@code FloatConvert} converts between integers and floating point numbers according to Java
  * semantics.
  */
-public class FloatConvertNode extends ConvertNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable {
+public class FloatConvertNode extends ConvertNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
 
     public enum FloatConvert {
         F2I, D2I, F2L, D2L, I2F, L2F, D2F, I2D, L2D, F2D;
@@ -194,4 +195,18 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(getInput())));
     }
+
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Kind kind = access.nullCheckLocation().getValueKind();
+        if (kind != kind.getStackKind()) {
+            // Doesn't work for subword operations
+            return false;
+        }
+
+        Value result = gen.emitFloatConvertMemory(getOp(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -59,4 +60,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), null));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitDivMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -69,4 +70,13 @@
         }
         gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitMulMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -59,4 +60,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), null));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitRemMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -78,4 +79,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitSubMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -78,9 +79,6 @@
             if (reassociated != this) {
                 return reassociated;
             }
-            if (c < 0) {
-                return IntegerArithmeticNode.sub(graph(), x(), ConstantNode.forIntegerStamp(stamp(), -c, graph()));
-            }
         }
         if (x() instanceof NegateNode) {
             return IntegerArithmeticNode.sub(graph(), y(), ((NegateNode) x()).x());
@@ -102,4 +100,13 @@
         }
         gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitAddMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class IntegerArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable {
+public abstract class IntegerArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
 
     public IntegerArithmeticNode(Stamp stamp, ValueNode x, ValueNode y) {
         super(stamp, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -31,7 +31,7 @@
 /**
  * An {@code IntegerConvert} converts an integer to an integer of different width.
  */
-public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable, Canonicalizable {
+public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable, Canonicalizable, MemoryArithmeticLIRLowerable {
 
     private final int resultBits;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,8 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
 public final class IntegerEqualsNode extends CompareNode {
@@ -69,17 +71,67 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
+        if (GraphUtil.unproxify(x()) == GraphUtil.unproxify(y())) {
             return LogicConstantNode.tautology(graph());
         } else if (x().stamp().alwaysDistinct(y().stamp())) {
             return LogicConstantNode.contradiction(graph());
         }
 
-        if (x() instanceof AndNode && y().isConstant() && y().asConstant().asLong() == 0) {
-            return graph().unique(new IntegerTestNode(((AndNode) x()).x(), ((AndNode) x()).y()));
-        } else if (y() instanceof AndNode && x().isConstant() && x().asConstant().asLong() == 0) {
-            return graph().unique(new IntegerTestNode(((AndNode) y()).x(), ((AndNode) y()).y()));
+        ValueNode result = canonicalizeSymmetric(x(), y());
+        if (result != null) {
+            return result;
         }
+
+        result = canonicalizeSymmetric(y(), x());
+        if (result != null) {
+            return result;
+        }
+
         return super.canonical(tool);
     }
+
+    private ValueNode canonicalizeSymmetric(ValueNode x, ValueNode y) {
+        if (y.isConstant() && y.asConstant().asLong() == 0) {
+            if (x instanceof AndNode) {
+                return graph().unique(new IntegerTestNode(((AndNode) x).x(), ((AndNode) x).y()));
+            } else if (x instanceof LeftShiftNode) {
+                LeftShiftNode shift = (LeftShiftNode) x;
+                if (shift.y().isConstant()) {
+                    int mask = shift.getShiftAmountMask();
+                    int amount = shift.y().asConstant().asInt() & mask;
+                    if (shift.x().getKind() == Kind.Int) {
+                        return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 >>> amount, graph())));
+                    } else {
+                        assert shift.x().getKind() == Kind.Long;
+                        return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L >>> amount, graph())));
+                    }
+                }
+            } else if (x instanceof RightShiftNode) {
+                RightShiftNode shift = (RightShiftNode) x;
+                if (shift.y().isConstant() && ((IntegerStamp) shift.x().stamp()).isPositive()) {
+                    int mask = shift.getShiftAmountMask();
+                    int amount = shift.y().asConstant().asInt() & mask;
+                    if (shift.x().getKind() == Kind.Int) {
+                        return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph())));
+                    } else {
+                        assert shift.x().getKind() == Kind.Long;
+                        return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph())));
+                    }
+                }
+            } else if (x instanceof UnsignedRightShiftNode) {
+                UnsignedRightShiftNode shift = (UnsignedRightShiftNode) x;
+                if (shift.y().isConstant()) {
+                    int mask = shift.getShiftAmountMask();
+                    int amount = shift.y().asConstant().asInt() & mask;
+                    if (shift.x().getKind() == Kind.Int) {
+                        return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph())));
+                    } else {
+                        assert shift.x().getKind() == Kind.Long;
+                        return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph())));
+                    }
+                }
+            }
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -84,4 +85,13 @@
         }
         gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitMulMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -97,7 +98,9 @@
             if (reassociated != this) {
                 return reassociated;
             }
-            if (c < 0) {
+            if (c < 0 || ((IntegerStamp) StampFactory.forKind(y().getKind())).contains(-c)) {
+                // Adding a negative is more friendly to the backend since adds are
+                // commutative, so prefer add when it fits.
                 return IntegerArithmeticNode.add(graph(), x(), ConstantNode.forIntegerStamp(stamp(), -c, graph()));
             }
         } else if (x().isConstant()) {
@@ -117,4 +120,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitSubMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -25,6 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -33,7 +34,7 @@
  * expression "(x &amp; y) == 0", meaning that it will return true if (and only if) no bit is set in
  * both x and y.
  */
-public class IntegerTestNode extends LogicNode implements Canonicalizable, LIRLowerable {
+public class IntegerTestNode extends LogicNode implements Canonicalizable, LIRLowerable, MemoryArithmeticLIRLowerable {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
@@ -76,4 +77,9 @@
         }
         return this;
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        return false;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -59,13 +59,7 @@
         } else if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
-            int mask;
-            if (getKind() == Kind.Int) {
-                mask = 0x1f;
-            } else {
-                assert getKind() == Kind.Long;
-                mask = 0x3f;
-            }
+            int mask = getShiftAmountMask();
             amount &= mask;
             if (amount == 0) {
                 return x();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -112,4 +113,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitNarrow(gen.operand(getInput()), getResultBits()));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitNarrowMemory(getResultBits(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -75,4 +76,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitOr(gen.operand(x()), gen.operand(y())));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitOrMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -34,7 +35,7 @@
  * of a primitive value to some other incompatible stamp. The new stamp must have the same width as
  * the old stamp.
  */
-public class ReinterpretNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable {
+public class ReinterpretNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
 
     @Input private ValueNode value;
 
@@ -106,6 +107,15 @@
         gen.setResult(this, gen.getLIRGeneratorTool().emitReinterpret(kind, gen.operand(value())));
     }
 
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitReinterpretMemory(stamp(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
+
     public static ValueNode reinterpret(Kind toKind, ValueNode value) {
         return value.graph().unique(new ReinterpretNode(toKind, value));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -57,13 +57,7 @@
         } else if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
-            int mask;
-            if (getKind() == Kind.Int) {
-                mask = 0x1f;
-            } else {
-                assert getKind() == Kind.Long;
-                mask = 0x3f;
-            }
+            int mask = getShiftAmountMask();
             amount &= mask;
             if (amount == 0) {
                 return x();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -40,4 +41,15 @@
     public ShiftNode(Stamp stamp, ValueNode x, ValueNode s) {
         super(stamp, x, s);
     }
+
+    public int getShiftAmountMask() {
+        int mask;
+        if (getKind() == Kind.Int) {
+            mask = 0x1f;
+        } else {
+            assert getKind() == Kind.Long;
+            mask = 0x3f;
+        }
+        return mask;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -107,4 +108,14 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        assert !access.nullCheckLocation().getValueKind().isUnsigned() : "can't sign extend unsigned value";
+        Value result = gen.emitSignExtendMemory(access, access.nullCheckLocation().getValueKind().getBitCount(), getResultBits());
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -59,13 +59,7 @@
         } else if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
-            int mask;
-            if (getKind() == Kind.Int) {
-                mask = 0x1f;
-            } else {
-                assert getKind() == Kind.Long;
-                mask = 0x3f;
-            }
+            int mask = getShiftAmountMask();
             amount &= mask;
             if (amount == 0) {
                 return x();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -74,4 +75,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitXor(gen.operand(x()), gen.operand(y())));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitXorMemory(x(), y(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -87,4 +88,13 @@
     public void generate(NodeLIRGeneratorTool gen) {
         gen.setResult(this, gen.getLIRGeneratorTool().emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
     }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        Value result = gen.emitZeroExtendMemory(getInputBits(), getResultBits(), access);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+        return result != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -43,6 +43,11 @@
         return object;
     }
 
+    protected void setObject(ValueNode x) {
+        updateUsages(object, x);
+        object = x;
+    }
+
     public LocationNode location() {
         return (LocationNode) location;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -67,6 +67,9 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
+        if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
+            return graph().unique(new FloatingReadNode(((PiNode) object()).getOriginalValue(), location(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType(), isCompressible()));
+        }
         return ReadNode.canonicalizeRead(this, location(), object(), tool, isCompressible());
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -35,7 +35,7 @@
  * Node for a {@linkplain ForeignCallDescriptor foreign} call.
  */
 @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}")
-public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint.Multi {
+public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode.DeoptDuring, MemoryCheckpoint.Multi {
 
     @Input private final NodeInputList<ValueNode> arguments;
     private final ForeignCallsProvider foreignCalls;
@@ -101,32 +101,25 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
-        if (deoptState != null) {
-            return deoptState;
-        } else if (stateAfter() != null && canDeoptimize()) {
-            FrameState stateDuring = stateAfter();
-            if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
-                stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.getKind());
-            }
-            setDeoptimizationState(stateDuring);
-            return stateDuring;
-        }
-        return null;
+    public FrameState stateDuring() {
+        return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
-        updateUsages(deoptState, f);
-        assert deoptState == null && canDeoptimize() : "shouldn't assign deoptState to " + this;
-        deoptState = f;
+    public void setStateDuring(FrameState stateDuring) {
+        updateUsages(deoptState, stateDuring);
+        deoptState = stateDuring;
     }
 
     @Override
-    public void setStateAfter(FrameState x) {
-        if (hasSideEffect()) {
-            super.setStateAfter(x);
+    public void computeStateDuring(FrameState stateAfter) {
+        FrameState stateDuring;
+        if ((stateAfter.stackSize() > 0 && stateAfter.stackAt(stateAfter.stackSize() - 1) == this) || (stateAfter.stackSize() > 1 && stateAfter.stackAt(stateAfter.stackSize() - 2) == this)) {
+            stateDuring = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), this.getKind());
+        } else {
+            stateDuring = stateAfter;
         }
+        setStateDuring(stateDuring);
     }
 
     @Override
@@ -141,14 +134,4 @@
     public boolean canDeoptimize() {
         return foreignCalls.canDeoptimize(descriptor);
     }
-
-    @Override
-    public FrameState getState() {
-        if (deoptState != null) {
-            assert stateAfter() == null;
-            return deoptState;
-        } else {
-            return super.getState();
-        }
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -60,6 +60,9 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
+        if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
+            return graph().add(new ReadNode(((PiNode) object()).getOriginalValue(), location(), stamp(), getGuard(), getBarrierType(), isCompressible()));
+        }
         return canonicalizeRead(this, location(), object(), tool, isCompressible());
     }
 
@@ -71,8 +74,14 @@
     public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool, boolean compressible) {
         MetaAccessProvider metaAccess = tool.getMetaAccess();
         if (read.usages().isEmpty()) {
-            // Read without usages can be safely removed.
-            return null;
+            GuardingNode guard = ((Access) read).getGuard();
+            if (guard != null && !(guard instanceof FixedNode)) {
+                // The guard is necessary even if the read goes away.
+                return read.graph().add(new ValueAnchorNode((ValueNode) guard));
+            } else {
+                // Read without usages or guard can be safely removed.
+                return null;
+            }
         }
         if (tool.canonicalizeReads()) {
             if (metaAccess != null && object != null && object.isConstant()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -22,16 +22,17 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 /**
  * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph.
  */
-public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Virtualizable, GuardingNode {
+public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, GuardingNode {
 
     @Input private ValueNode anchored;
 
@@ -50,19 +51,40 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (anchored != null && !anchored.isConstant() && !(anchored instanceof FixedNode)) {
-            // Found entry that needs this anchor.
-            return this;
+    public void simplify(SimplifierTool tool) {
+        while (next() instanceof ValueAnchorNode) {
+            ValueAnchorNode nextAnchor = (ValueAnchorNode) next();
+            if (nextAnchor.anchored == anchored || nextAnchor.anchored == null) {
+                // two anchors for the same anchored -> coalesce
+                // nothing anchored on the next anchor -> coalesce
+                nextAnchor.replaceAtUsages(this);
+                GraphUtil.removeFixedWithUnusedInputs(nextAnchor);
+            } else {
+                break;
+            }
+        }
+        if (usages().isEmpty() && next() instanceof FixedAccessNode) {
+            FixedAccessNode next = (FixedAccessNode) next();
+            if (next.getGuard() == anchored) {
+                GraphUtil.removeFixedWithUnusedInputs(this);
+                return;
+            } else if (next.getGuard() == null && anchored instanceof GuardNode && ((GuardNode) anchored).condition() instanceof IsNullNode) {
+                // coalesce null check guards into subsequent read/write
+                next.setGuard((GuardingNode) anchored);
+                tool.addToWorkList(next());
+                return;
+            }
         }
 
-        if (usages().isNotEmpty()) {
-            // A not uses this anchor => anchor is necessary.
-            return this;
+        if (anchored != null && (anchored.isConstant() || anchored instanceof FixedNode)) {
+            // anchoring fixed nodes and constants is useless
+            removeAnchoredNode();
         }
 
-        // Anchor is not necessary any more => remove.
-        return null;
+        if (anchored == null && usages().isEmpty()) {
+            // anchor is not necessary any more => remove.
+            GraphUtil.removeFixedWithUnusedInputs(this);
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.LocationNode.Location;
 import com.oracle.graal.nodes.spi.*;
@@ -33,7 +34,7 @@
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}.
  */
-public final class WriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, MemoryAccess, Virtualizable {
+public final class WriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, MemoryAccess, Simplifiable, Virtualizable {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
@@ -45,16 +46,6 @@
         return stateAfter;
     }
 
-    @Override
-    public FrameState getState() {
-        if (stateAfter != null) {
-            assert super.getState() == null;
-            return stateAfter;
-        } else {
-            return super.getState();
-        }
-    }
-
     public void setStateAfter(FrameState x) {
         assert x == null || x.isAlive() : "frame state must be in a graph";
         updateUsages(stateAfter, x);
@@ -102,6 +93,13 @@
         gen.getLIRGeneratorTool().emitStore(location().getValueKind(), address, v, this);
     }
 
+    @Override
+    public void simplify(SimplifierTool tool) {
+        if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
+            setObject(((PiNode) object()).getOriginalValue());
+        }
+    }
+
     @NodeIntrinsic
     public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter BarrierType barrierType, @ConstantNodeParameter boolean compressible);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -33,9 +33,9 @@
  * The Java bytecode specification allows non-balanced locking. Graal does not handle such cases and
  * throws a {@link BailoutException} instead during graph building.
  */
-public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint, DeoptimizingNode {
+public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint, DeoptimizingNode.DeoptBefore, DeoptimizingNode.DeoptAfter {
 
-    @Input private FrameState deoptState;
+    @Input private FrameState stateBefore;
     @Input private ValueNode object;
     @Input private MonitorIdNode monitorId;
 
@@ -44,21 +44,14 @@
         return true;
     }
 
-    @Override
-    public FrameState getDeoptimizationState() {
-        return deoptState;
+    public FrameState stateBefore() {
+        return stateBefore;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
-        updateUsages(deoptState, f);
-        deoptState = f;
-    }
-
-    @Override
-    public FrameState getState() {
-        assert deoptState == null || stateAfter() == null;
-        return deoptState == null ? stateAfter() : deoptState;
+    public void setStateBefore(FrameState f) {
+        updateUsages(stateBefore, f);
+        stateBefore = f;
     }
 
     public ValueNode object() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -126,15 +126,28 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (!isStatic()) {
+        if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
+            // attempt to devirtualize the call
+
+            // check for trivial cases (e.g. final methods, nonvirtual methods)
+            if (targetMethod.canBeStaticallyBound()) {
+                invokeKind = InvokeKind.Special;
+                return this;
+            }
+
+            // check if the exact type of the receiver can be determined
             ValueNode receiver = receiver();
-            if (receiver != null && ObjectStamp.isExactType(receiver) && ObjectStamp.typeOrNull(receiver) != null) {
-                if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
-                    ResolvedJavaMethod method = ObjectStamp.typeOrNull(receiver).resolveMethod(targetMethod);
-                    if (method != null) {
-                        invokeKind = InvokeKind.Special;
-                        targetMethod = method;
-                    }
+            ResolvedJavaType exact = targetMethod.getDeclaringClass().asExactType();
+            if (exact == null && ObjectStamp.isExactType(receiver)) {
+                exact = ObjectStamp.typeOrNull(receiver);
+            }
+            if (exact != null) {
+                // either the holder class is exact, or the receiver object has an exact type
+                ResolvedJavaMethod exactMethod = exact.resolveMethod(targetMethod);
+                if (exactMethod != null) {
+                    invokeKind = InvokeKind.Special;
+                    targetMethod = exactMethod;
+                    return this;
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -34,7 +34,7 @@
  * This node is used to perform the finalizer registration at the end of the java.lang.Object
  * constructor.
  */
-public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode {
+public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter {
 
     public static final ForeignCallDescriptor REGISTER_FINALIZER = new ForeignCallDescriptor("registerFinalizer", void.class, Object.class);
 
@@ -96,17 +96,6 @@
         return true;
     }
 
-    @Override
-    public FrameState getDeoptimizationState() {
-        return deoptState;
-    }
-
-    @Override
-    public void setDeoptimizationState(FrameState f) {
-        updateUsages(deoptState, f);
-        deoptState = f;
-    }
-
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void register(Object thisObj) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -31,7 +31,6 @@
  * This interface can be used to generate LIR for arithmetic operations.
  */
 public interface ArithmeticLIRGenerator {
-
     /**
      * TODO remove reference to {@link Stamp}.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Mar 26 20:44:11 2014 +0100
@@ -65,6 +65,14 @@
 
     void emitMove(AllocatableValue dst, Value src);
 
+    /**
+     * Emits an op that loads the address of some raw data.
+     * 
+     * @param dst the variable into which the address is loaded
+     * @param data the data to be installed with the generated code
+     */
+    void emitData(AllocatableValue dst, byte[] data);
+
     Value emitAddress(Value base, long displacement, Value index, int scale);
 
     Value emitAddress(StackSlot slot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerable.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,42 @@
+/*
+ * 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.spi;
+
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * Marks nodes which may be lowered in combination with a memory operation.
+ */
+public interface MemoryArithmeticLIRLowerable {
+
+    /**
+     * Attempt to generate a memory form of a node operation. On platforms that support it this will
+     * be called when the merging is safe.
+     * 
+     * @param gen
+     * @param access the memory input which can potentially merge into this operation.
+     * @return null if it's not possible to emit a memory form of this operation. A non-null value
+     *         will be set as the operand of this node.
+     */
+    boolean generate(MemoryArithmeticLIRLowerer gen, Access access);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,71 @@
+/*
+ * 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.spi;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * This interface can be used to generate LIR for arithmetic operations where one of the operations
+ * is load (@see ArithmeticLIRLowerable).
+ */
+public interface MemoryArithmeticLIRLowerer {
+
+    Value setResult(ValueNode x, Value operand);
+
+    Value emitAddMemory(ValueNode x, ValueNode y, Access access);
+
+    Value emitMulMemory(ValueNode x, ValueNode y, Access access);
+
+    Value emitSubMemory(ValueNode x, ValueNode y, Access access);
+
+    Value emitDivMemory(ValueNode x, ValueNode y, Access access);
+
+    Value emitRemMemory(ValueNode x, ValueNode y, Access access);
+
+    Value emitXorMemory(ValueNode x, ValueNode y, Access access);
+
+    Value emitOrMemory(ValueNode x, ValueNode y, Access access);
+
+    Value emitAndMemory(ValueNode x, ValueNode y, Access access);
+
+    Value emitReinterpretMemory(Stamp stamp, Access access);
+
+    Value emitSignExtendMemory(Access access, int fromBits, int toBits);
+
+    Value emitNarrowMemory(int resultBits, Access access);
+
+    Value emitZeroExtendMemory(int inputBits, int resultBits, Access access);
+
+    Value emitFloatConvertMemory(FloatConvert op, Access access);
+
+    boolean memoryPeephole(Access valueNode, MemoryArithmeticLIRLowerable operation, List<ValueNode> deferred);
+
+    boolean emitIfMemory(IfNode ifNode, Access access);
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRGeneratorTool.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRGeneratorTool.java	Wed Mar 26 20:44:11 2014 +0100
@@ -67,4 +67,6 @@
     void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability);
 
     Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments);
+
+    MemoryArithmeticLIRLowerer getMemoryLowerer();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeMappableLIRGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeMappableLIRGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -7,6 +7,8 @@
 
     Value operand(ValueNode object);
 
+    boolean hasOperand(ValueNode object);
+
     Value setResult(ValueNode x, Value operand);
 
 }
\ No newline at end of file
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Wed Mar 26 20:44:11 2014 +0100
@@ -24,25 +24,11 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import static com.oracle.graal.nodes.StructuredGraph.GuardsStage.*;
 
 /**
  * Interface for nodes which have {@link FrameState} nodes as input.
- * <p>
- * Some node can implement more than one interface which requires a {@link FrameState} input (e.g.
- * {@link DeoptimizingNode} and {@link StateSplit}). Since this interface can only report one
- * FrameState, such nodes must ensure they only maintain a link to at most one FrameState at all
- * times. Usually this is not a problem because FrameStates are associated only with StateSplit
- * nodes before the {@link #AFTER_FSA} stage and only with DeoptimizingNodes after.
- * 
  */
 public interface NodeWithState {
-    /**
-     * Gets the {@link FrameState} associated with this node.
-     * 
-     * @return the {@link FrameState} associated with this node
-     */
-    FrameState getState();
 
     Node asNode();
 }
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Wed Mar 26 20:44:11 2014 +0100
@@ -45,10 +45,14 @@
  * }
  * </pre>
  */
-@SupportedSourceVersion(SourceVersion.RELEASE_7)
 @SupportedAnnotationTypes({"com.oracle.graal.options.Option"})
 public class OptionProcessor extends AbstractProcessor {
 
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
     private final Set<Element> processed = new HashSet<>();
 
     private void processElement(Element element, OptionsInfo info) {
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Wed Mar 26 20:44:11 2014 +0100
@@ -38,7 +38,7 @@
      * <p>
      * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
      * used:
-     * 
+     *
      * <pre>
      * try (OverrideScope s = OptionValue.override(myOption, myValue) {
      *     // code that depends on myOption == myValue
@@ -65,7 +65,7 @@
      * <p>
      * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
      * used:
-     * 
+     *
      * <pre>
      * Map<OptionValue, Object> overrides = new HashMap<>();
      * overrides.put(myOption1, myValue1);
@@ -96,13 +96,13 @@
      * <p>
      * Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
      * used:
-     * 
+     *
      * <pre>
      * try (OverrideScope s = OptionValue.override(myOption1, myValue1, myOption2, myValue2) {
      *     // code that depends on myOption == myValue
      * }
      * </pre>
-     * 
+     *
      * @param overrides overrides in the form {@code [option1, override1, option2, override2, ...]}
      */
     public static OverrideScope override(Object... overrides) {
@@ -221,14 +221,14 @@
 
     /**
      * Gets the values of this option including overridden values.
-     * 
+     *
      * @param c the collection to which the values are added. If null, one is allocated.
      * @return the collection to which the values were added in order from most overridden to
      *         current value
      */
     @SuppressWarnings("unchecked")
     public Collection<T> getValues(Collection<T> c) {
-        Collection<T> values = c == null ? new ArrayList<T>() : c;
+        Collection<T> values = c == null ? new ArrayList<>() : c;
         if (!(this instanceof StableOptionValue)) {
             OverrideScope overrideScope = overrideScopes.get();
             if (overrideScope != null) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -273,10 +273,10 @@
 // @formatter:on
         private boolean performReplacement(final Node node, Node canonical) {
             if (canonical == node) {
-                Debug.log("Canonicalizer: work on %s", node);
+                Debug.log("Canonicalizer: work on %1s", node);
                 return false;
             } else {
-                Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
+                Debug.log("Canonicalizer: replacing %1s with %1s", node, canonical);
                 METRIC_CANONICALIZED_NODES.increment();
                 StructuredGraph graph = (StructuredGraph) node.graph();
                 if (node instanceof FloatingNode) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -88,6 +88,9 @@
                     }
                     for (int i = 0; i < mergePredecessors.size(); ++i) {
                         AbstractEndNode mergePredecessor = mergePredecessors.get(i);
+                        if (!mergePredecessor.isAlive()) {
+                            break;
+                        }
                         if (xs[i] == null) {
                             continue;
                         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -82,7 +82,7 @@
                 }
             }
             if (obsoletes != null) {
-                ((DynamicDeoptimizeNode) ((MergeNode) target).next()).setDeoptimizationState(fs);
+                ((DynamicDeoptimizeNode) ((MergeNode) target).next()).setStateBefore(fs);
                 for (AbstractDeoptimizeNode obsolete : obsoletes) {
                     obsolete.safeDelete();
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -49,24 +49,41 @@
 
         @Override
         protected FrameState processNode(FixedNode node, FrameState currentState) {
-            if (node instanceof DeoptimizingNode) {
-                DeoptimizingNode deopt = (DeoptimizingNode) node;
-                if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) {
+            if (node instanceof DeoptimizingNode.DeoptBefore) {
+                DeoptimizingNode.DeoptBefore deopt = (DeoptimizingNode.DeoptBefore) node;
+                if (deopt.canDeoptimize() && deopt.stateBefore() == null) {
                     GraalInternalError.guarantee(currentState != null, "no FrameState at DeoptimizingNode %s", deopt);
-                    deopt.setDeoptimizationState(currentState);
+                    deopt.setStateBefore(currentState);
                 }
             }
 
+            FrameState newState = currentState;
             if (node instanceof StateSplit) {
                 StateSplit stateSplit = (StateSplit) node;
                 FrameState stateAfter = stateSplit.stateAfter();
                 if (stateAfter != null) {
-                    FrameState newState = stateAfter;
+                    newState = stateAfter;
                     stateSplit.setStateAfter(null);
-                    return newState;
                 }
             }
-            return currentState;
+
+            if (node instanceof DeoptimizingNode.DeoptDuring) {
+                DeoptimizingNode.DeoptDuring deopt = (DeoptimizingNode.DeoptDuring) node;
+                if (deopt.canDeoptimize()) {
+                    GraalInternalError.guarantee(newState != null, "no FrameState at DeoptimizingNode %s", deopt);
+                    deopt.computeStateDuring(newState);
+                }
+            }
+
+            if (node instanceof DeoptimizingNode.DeoptAfter) {
+                DeoptimizingNode.DeoptAfter deopt = (DeoptimizingNode.DeoptAfter) node;
+                if (deopt.canDeoptimize() && deopt.stateAfter() == null) {
+                    GraalInternalError.guarantee(newState != null, "no FrameState at DeoptimizingNode %s", deopt);
+                    deopt.setStateAfter(newState);
+                }
+            }
+
+            return newState;
         }
 
         @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -55,6 +55,9 @@
  * does the actual control-flow expansion of the remaining {@link GuardNode GuardNodes}.
  */
 public class GuardLoweringPhase extends BasePhase<MidTierContext> {
+
+    private static final DebugMetric metricImplicitNullCheck = Debug.metric("ImplicitNullCheck");
+
     private static class UseImplicitNullChecks extends ScheduledNodeIterator {
 
         private final IdentityHashMap<ValueNode, GuardNode> nullGuarded = new IdentityHashMap<>();
@@ -88,6 +91,7 @@
         private void processAccess(Access access) {
             GuardNode guard = nullGuarded.get(access.object());
             if (guard != null && isImplicitNullCheck(access.nullCheckLocation())) {
+                metricImplicitNullCheck.increment();
                 access.setGuard(guard.getGuard());
                 FixedAccessNode fixedAccess;
                 if (access instanceof FloatingAccessNode) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Mar 26 20:44:11 2014 +0100
@@ -173,7 +173,10 @@
 
     public static void logInliningDecision(final String msg, final Object... args) {
         try (Scope s = Debug.scope(inliningDecisionsScopeString)) {
-            Debug.log(msg, args);
+            // Can't use log here since we are varargs
+            if (Debug.isLogEnabled()) {
+                Debug.logv(msg, args);
+            }
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012, 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 java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.cfg.*;
+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.util.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.schedule.*;
+
+/**
+ * This phase add counters for the dynamically executed number of nodes. Incrementing the counter
+ * for each node would be too costly, so this phase takes the compromise that it trusts split
+ * probabilities, but not loop frequencies. This means that it will insert counters at the start of
+ * a method and at each loop header.
+ * 
+ * A schedule is created so that floating nodes can also be taken into account. The weight of a node
+ * is determined heuristically in the
+ * {@link ProfileCompiledMethodsPhase#getNodeWeight(ScheduledNode)} method.
+ * 
+ * Additionally, there's a second counter that's only increased for code sections without invokes.
+ */
+public class ProfileCompiledMethodsPhase extends Phase {
+
+    private static final String GROUP_NAME = "~profiled weight";
+    private static final String GROUP_NAME_WITHOUT = "~profiled weight (invoke-free sections)";
+
+    private static final boolean WITH_SECTION_HEADER = false;
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        ComputeProbabilityClosure closure = new ComputeProbabilityClosure(graph);
+        NodesToDoubles probabilities = closure.apply();
+        SchedulePhase schedule = new SchedulePhase();
+        schedule.apply(graph, false);
+
+        ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
+        for (Loop loop : cfg.getLoops()) {
+            double loopProbability = probabilities.get(loop.loopBegin());
+            if (loopProbability > (1D / Integer.MAX_VALUE)) {
+                addSectionCounters(loop.loopBegin(), loop.blocks, loop.children, schedule, probabilities);
+            }
+        }
+        addSectionCounters(graph.start(), Arrays.asList(cfg.getBlocks()), Arrays.asList(cfg.getLoops()), schedule, probabilities);
+    }
+
+    private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop> childLoops, SchedulePhase schedule, NodesToDoubles probabilities) {
+        HashSet<Block> blocks = new HashSet<>(sectionBlocks);
+        for (Loop loop : childLoops) {
+            blocks.removeAll(loop.blocks);
+        }
+        double weight = getSectionWeight(schedule, probabilities, blocks) / probabilities.get(start);
+        DynamicCounterNode.addCounterBefore(GROUP_NAME, sectionHead(start), (long) weight, true, start.next());
+        if (!hasInvoke(blocks)) {
+            DynamicCounterNode.addCounterBefore(GROUP_NAME_WITHOUT, sectionHead(start), (long) weight, true, start.next());
+        }
+    }
+
+    private static String sectionHead(Node node) {
+        if (WITH_SECTION_HEADER) {
+            return node.toString();
+        } else {
+            return "";
+        }
+    }
+
+    private static double getSectionWeight(SchedulePhase schedule, NodesToDoubles probabilities, Collection<Block> blocks) {
+        double count = 0;
+        for (Block block : blocks) {
+            double blockProbability = probabilities.get(block.getBeginNode());
+            for (ScheduledNode node : schedule.getBlockToNodesMap().get(block)) {
+                count += blockProbability * getNodeWeight(node);
+            }
+        }
+        return count;
+    }
+
+    private static double getNodeWeight(ScheduledNode node) {
+        if (node instanceof MergeNode) {
+            return ((MergeNode) node).phiPredecessorCount();
+        } else if (node instanceof AbstractBeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode ||
+                        node instanceof CallTargetNode || node instanceof ValueProxy || node instanceof VirtualObjectNode || node instanceof ReinterpretNode) {
+            return 0;
+        } else if (node instanceof AccessMonitorNode) {
+            return 10;
+        } else if (node instanceof Access) {
+            return 2;
+        } else if (node instanceof LogicNode || node instanceof ConvertNode || node instanceof BinaryNode || node instanceof NotNode) {
+            return 1;
+        } else if (node instanceof IntegerDivNode || node instanceof FloatDivNode || node instanceof IntegerRemNode || node instanceof FloatRemNode) {
+            return 10;
+        } else if (node instanceof IntegerMulNode || node instanceof FloatMulNode) {
+            return 3;
+        } else if (node instanceof Invoke) {
+            return 5;
+        } else if (node instanceof IfNode || node instanceof SafepointNode) {
+            return 1;
+        } else if (node instanceof SwitchNode) {
+            return node.successors().count();
+        } else if (node instanceof ReturnNode || node instanceof UnwindNode || node instanceof DeoptimizeNode) {
+            return node.successors().count();
+        } else if (node instanceof AbstractNewObjectNode) {
+            return 10;
+        }
+        return 2;
+    }
+
+    private static boolean hasInvoke(Collection<Block> blocks) {
+        boolean hasInvoke = false;
+        for (Block block : blocks) {
+            for (FixedNode fixed : block.getNodes()) {
+                if (fixed instanceof Invoke) {
+                    hasInvoke = true;
+                }
+            }
+        }
+        return hasInvoke;
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -76,7 +76,7 @@
         AbstractBeginNode nonTrappingContinuation = ifNode.falseSuccessor();
         AbstractBeginNode trappingContinuation = ifNode.trueSuccessor();
         NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.object()));
-        trappingNullCheck.setDeoptimizationState(deopt.getDeoptimizationState());
+        trappingNullCheck.setStateBefore(deopt.stateBefore());
         deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
 
         GraphUtil.killCFG(trappingContinuation);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -73,7 +73,7 @@
             BasePhase.this.run(graph, context);
             phaseMetric.increment();
             if (dumpGraph) {
-                Debug.dump(graph, "After phase %s", name);
+                Debug.dump(graph, "After phase %s", getName());
             }
             assert graph.verify();
         } catch (Throwable t) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Wed Mar 26 20:44:11 2014 +0100
@@ -271,6 +271,8 @@
     public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true);
     @Option(help = "")
     public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
+    @Option(help = "Allow backend to emit arithmetic and compares directly against memory.")
+    public static final OptionValue<Boolean> OptFoldMemory = new OptionValue<>(true);
 
 
     /**
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -59,7 +59,7 @@
         /**
          * This constructor creates a {@link SchedulingError} with a message assembled via
          * {@link String#format(String, Object...)}.
-         * 
+         *
          * @param format a {@linkplain Formatter format} string
          * @param args parameters to {@link String#format(String, Object...)}
          */
@@ -164,9 +164,9 @@
 
     /**
      * gather all kill locations by iterating trough the nodes assigned to a block.
-     * 
+     *
      * assumptions: {@link MemoryCheckpoint MemoryCheckPoints} are {@link FixedNode FixedNodes}.
-     * 
+     *
      * @param block block to analyze
      * @param excludeNode if null, compute normal set of kill locations. if != null, don't add kills
      *            until we reach excludeNode.
@@ -457,9 +457,9 @@
      * this method tries to find the "optimal" schedule for a read, by pushing it down towards its
      * latest schedule starting by the earliest schedule. By doing this, it takes care of memory
      * dependencies using kill sets.
-     * 
+     *
      * In terms of domination relation, it looks like this:
-     * 
+     *
      * <pre>
      *    U      upperbound block, defined by last access location of the floating read
      *    &#9650;
@@ -469,9 +469,9 @@
      *    &#9650;
      *    L      latest block
      * </pre>
-     * 
+     *
      * i.e. <code>upperbound `dom` earliest `dom` optimal `dom` latest</code>.
-     * 
+     *
      */
     private Block optimalBlock(FloatingReadNode n, SchedulingStrategy strategy) {
         assert memsched == MemoryScheduling.OPTIMAL;
@@ -540,7 +540,7 @@
 
     /**
      * compute path in dominator tree from earliest schedule to latest schedule.
-     * 
+     *
      * @return the order of the stack is such as the first element is the earliest schedule.
      */
     private static Deque<Block> computePathInDominatorTree(Block earliestBlock, Block latestBlock) {
@@ -582,7 +582,7 @@
     /**
      * Calculates the last block that the given node could be scheduled in, i.e., the common
      * dominator of all usages. To do so all usages are also assigned to blocks.
-     * 
+     *
      * @param strategy
      */
     private Block latestBlock(ScheduledNode node, SchedulingStrategy strategy) {
@@ -680,7 +680,7 @@
      * Schedules a node out of loop based on its earliest schedule. Note that this movement is only
      * valid if it's done for <b>every</b> other node in the schedule, otherwise this movement is
      * not valid.
-     * 
+     *
      * @param n Node to schedule
      * @param latestBlock latest possible schedule for {@code n}
      * @param earliest earliest possible schedule for {@code n}
@@ -705,7 +705,7 @@
     /**
      * Passes all blocks that a specific usage of a node is in to a given closure. This is more
      * complex than just taking the usage's block because of of PhiNodes and FrameStates.
-     * 
+     *
      * @param node the node that needs to be scheduled
      * @param usage the usage whose blocks need to be considered
      * @param closure the closure that will be called for each block
@@ -966,14 +966,18 @@
             return;
         }
 
-        FrameState state = null;
+        FrameState stateAfter = null;
+        if (i instanceof StateSplit) {
+            stateAfter = ((StateSplit) i).stateAfter();
+        }
+
         for (Node input : i.inputs()) {
             if (input instanceof FrameState) {
-                assert state == null;
-                state = (FrameState) input;
+                if (input != stateAfter) {
+                    addUnscheduledToLatestSorting(b, (FrameState) input, sortedInstructions, visited, reads, beforeLastLocation);
+                }
             } else {
                 addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation);
-
             }
         }
 
@@ -991,7 +995,7 @@
 
         addToLatestSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited, reads, beforeLastLocation);
         visited.mark(i);
-        addUnscheduledToLatestSorting(b, state, sortedInstructions, visited, reads, beforeLastLocation);
+        addUnscheduledToLatestSorting(b, stateAfter, sortedInstructions, visited, reads, beforeLastLocation);
 
         // Now predecessors and inputs are scheduled => we can add this node.
         if (!sortedInstructions.contains(i)) {
@@ -1038,7 +1042,7 @@
             }
 
             if (instruction instanceof AbstractBeginNode) {
-                ArrayList<ProxyNode> proxies = (instruction instanceof LoopExitNode) ? new ArrayList<ProxyNode>() : null;
+                ArrayList<ProxyNode> proxies = (instruction instanceof LoopExitNode) ? new ArrayList<>() : null;
                 for (ScheduledNode inBlock : blockToNodesMap.get(b)) {
                     if (!visited.isMarked(inBlock)) {
                         if (inBlock instanceof ProxyNode) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Mar 26 20:44:11 2014 +0100
@@ -60,7 +60,13 @@
                         if (input instanceof FrameState && node instanceof StateSplit && input == ((StateSplit) node).stateAfter()) {
                             // nothing to do - after frame states are known, allowed cycles
                         } else {
-                            assert false : "unexpected cycle detected at input " + node + " -> " + input;
+                            /*
+                             * TODO assertion does not hold for Substrate VM (in general for all
+                             * notDataflow inputs)
+                             * 
+                             * assert false : "unexpected cycle detected at input " + node + " -> "
+                             * + input;
+                             */
                         }
                     }
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyDebugUsage.java	Wed Mar 26 20:44:11 2014 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.verify;
+
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * Verifies that no argument to one of the {@link Debug#log(String)} methods is the result of
+ * {@link StringBuilder#toString()} or {@link StringBuffer#toString()}. Instead, one of the
+ * multi-parameter {@code log()} methods should be used. The goal is to minimize/prevent allocation
+ * at logging call sites.
+ */
+public class VerifyDebugUsage extends VerifyPhase<PhaseContext> {
+
+    @Override
+    protected boolean verify(StructuredGraph graph, PhaseContext context) {
+        for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.class)) {
+            ResolvedJavaMethod callee = t.targetMethod();
+            ResolvedJavaType debugType = context.getMetaAccess().lookupJavaType(Debug.class);
+            if (callee.getDeclaringClass().equals(debugType)) {
+                if (callee.getName().equals("log")) {
+                    int argIdx = 1;
+                    for (ValueNode arg : t.arguments()) {
+                        if (arg instanceof Invoke) {
+                            Invoke invoke = (Invoke) arg;
+                            CallTargetNode callTarget = invoke.callTarget();
+                            if (callTarget instanceof MethodCallTargetNode) {
+                                ResolvedJavaMethod m = ((MethodCallTargetNode) callTarget).targetMethod();
+                                if (m.getName().equals("toString")) {
+                                    String holder = m.getDeclaringClass().getName();
+                                    if (holder.equals("Ljava/lang/StringBuilder;") || holder.equals("Ljava/lang/StringBuffer;")) {
+                                        StackTraceElement e = graph.method().asStackTraceElement(invoke.bci());
+                                        throw new VerificationError(String.format("%s: parameter %d of call to %s appears to be a String concatenation expression.%n"
+                                                        + "    Use one of the multi-parameter Debug.log() methods or Debug.logv() instead.", e, argIdx, format("%H.%n(%p)", callee)));
+                                    }
+                                }
+                            }
+                        }
+                        argIdx++;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Wed Mar 26 20:44:11 2014 +0100
@@ -115,7 +115,7 @@
             if (PrintBinaryGraphs.getValue()) {
                 printer = new BinaryGraphPrinter(FileChannel.open(file.toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW));
             } else {
-                printer = new IdealGraphPrinter(new FileOutputStream(file));
+                printer = new IdealGraphPrinter(new FileOutputStream(file), true);
             }
             TTY.println("Dumping IGV graphs to %s", file.getName());
         } catch (IOException e) {
@@ -132,7 +132,7 @@
             if (PrintBinaryGraphs.getValue()) {
                 printer = new BinaryGraphPrinter(SocketChannel.open(new InetSocketAddress(host, port)));
             } else {
-                IdealGraphPrinter xmlPrinter = new IdealGraphPrinter(new Socket(host, port).getOutputStream());
+                IdealGraphPrinter xmlPrinter = new IdealGraphPrinter(new Socket(host, port).getOutputStream(), true);
                 printer = xmlPrinter;
             }
             TTY.println("Connected to the IGV on %s:%d", host, port);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Mar 26 20:44:11 2014 +0100
@@ -42,12 +42,18 @@
  */
 public class IdealGraphPrinter extends BasicIdealGraphPrinter implements GraphPrinter {
 
+    private final boolean tryToSchedule;
+
     /**
      * Creates a new {@link IdealGraphPrinter} that writes to the specified output stream.
+     * 
+     * @param tryToSchedule If false, no scheduling is done, which avoids exceptions for
+     *            non-schedulable graphs.
      */
-    public IdealGraphPrinter(OutputStream stream) {
+    public IdealGraphPrinter(OutputStream stream, boolean tryToSchedule) {
         super(stream);
         this.begin();
+        this.tryToSchedule = tryToSchedule;
     }
 
     /**
@@ -80,7 +86,7 @@
         beginGraph(title);
         Set<Node> noBlockNodes = new HashSet<>();
         SchedulePhase schedule = predefinedSchedule;
-        if (schedule == null) {
+        if (schedule == null && tryToSchedule) {
             try {
                 schedule = new SchedulePhase();
                 schedule.apply((StructuredGraph) graph);
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java	Wed Mar 26 20:44:11 2014 +0100
@@ -30,12 +30,16 @@
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 
-@SupportedSourceVersion(SourceVersion.RELEASE_7)
 public class VerifierAnnotationProcessor extends AbstractProcessor {
 
     private List<AbstractVerifier> verifiers;
 
     @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (!roundEnv.processingOver()) {
             for (AbstractVerifier verifier : getVerifiers()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -175,7 +175,7 @@
             for (Node returnSideEffect : returnSideEffects) {
                 if (!unwindSideEffects.contains(returnSideEffect) && !maskedSideEffects.contains(returnSideEffect)) {
                     StateSplit split = (StateSplit) returnSideEffect;
-                    if (split.getState() != null) {
+                    if (split.stateAfter() != null) {
                         split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI)));
                     }
                 }
@@ -184,7 +184,7 @@
             for (Node unwindSideEffect : unwindSideEffects) {
                 if (!returnSideEffects.contains(unwindSideEffect) && !maskedSideEffects.contains(unwindSideEffect)) {
                     StateSplit split = (StateSplit) unwindSideEffect;
-                    if (split.getState() != null) {
+                    if (split.stateAfter() != null) {
                         split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_EXCEPTION_BCI)));
                     }
                 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Mar 26 20:44:11 2014 +0100
@@ -40,6 +40,7 @@
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.java.GraphBuilderPhase.Instance;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
@@ -233,7 +234,9 @@
         } else {
             original = metaAccess.lookupJavaConstructor((Constructor) originalMember);
         }
-        Debug.log("substitution: " + MetaUtil.format("%H.%n(%p) %r", original) + " --> " + MetaUtil.format("%H.%n(%p) %r", substitute));
+        if (Debug.isLogEnabled()) {
+            Debug.log("substitution: %s --> %s", MetaUtil.format("%H.%n(%p) %r", original), MetaUtil.format("%H.%n(%p) %r", substitute));
+        }
 
         registeredMethodSubstitutions.put(original, substitute);
         return original;
@@ -340,7 +343,7 @@
 
         public StructuredGraph makeGraph(final SnippetInliningPolicy policy) {
             try (Scope s = Debug.scope("BuildSnippetGraph", method)) {
-                StructuredGraph graph = parseGraph(method, policy);
+                StructuredGraph graph = parseGraph(method, policy, 0);
 
                 // Cannot have a finalized version of a graph in the cache
                 graph = graph.copy();
@@ -380,12 +383,14 @@
             new DeadCodeEliminationPhase().apply(graph);
         }
 
-        private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy) {
+        private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough
+
+        private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy, int inliningDepth) {
             StructuredGraph graph = graphCache.get(methodToParse);
             if (graph == null) {
                 StructuredGraph newGraph = null;
                 try (Scope s = Debug.scope("ParseGraph", methodToParse)) {
-                    newGraph = buildGraph(methodToParse, policy == null ? inliningPolicy(methodToParse) : policy);
+                    newGraph = buildGraph(methodToParse, policy == null ? inliningPolicy(methodToParse) : policy, inliningDepth);
                 } catch (Throwable e) {
                     throw Debug.handle(e);
                 }
@@ -404,7 +409,7 @@
             final StructuredGraph graph = new StructuredGraph(methodToParse);
             try (Scope s = Debug.scope("buildInitialGraph", graph)) {
                 MetaAccessProvider metaAccess = providers.getMetaAccess();
-                new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
+                createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
                 new WordTypeVerificationPhase(metaAccess, target.wordKind).apply(graph);
                 new WordTypeRewriterPhase(metaAccess, target.wordKind).apply(graph);
 
@@ -417,6 +422,10 @@
             return graph;
         }
 
+        protected Instance createGraphBuilder(MetaAccessProvider metaAccess, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
+            return new GraphBuilderPhase.Instance(metaAccess, graphBuilderConfig, optimisticOpts);
+        }
+
         protected Object beforeInline(@SuppressWarnings("unused") MethodCallTargetNode callTarget, @SuppressWarnings("unused") StructuredGraph callee) {
             return null;
         }
@@ -445,7 +454,8 @@
             }
         }
 
-        private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy) {
+        private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy, int inliningDepth) {
+            assert inliningDepth < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded";
             assert isInlinableSnippet(methodToParse) : methodToParse;
             final StructuredGraph graph = buildInitialGraph(methodToParse);
             try (Scope s = Debug.scope("buildGraph", graph)) {
@@ -477,7 +487,7 @@
                                                         " while preparing replacement " + format("%H.%n(%p)", method) + ". Placing \"//JaCoCo Exclude\" anywhere in " +
                                                         methodToParse.getDeclaringClass().getSourceFileName() + " should fix this.");
                                     }
-                                    targetGraph = parseGraph(callee, policy);
+                                    targetGraph = parseGraph(callee, policy, inliningDepth + 1);
                                 }
                                 Object beforeInlineData = beforeInline(callTarget, targetGraph);
                                 InliningUtil.inline(callTarget.invoke(), targetGraph, true);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Mar 26 20:44:11 2014 +0100
@@ -99,8 +99,8 @@
 
         protected SnippetInfo(ResolvedJavaMethod method) {
             this.method = method;
-            instantiationCounter = Debug.metric("SnippetInstantiationCount[%#s]", method);
-            instantiationTimer = Debug.timer("SnippetInstantiationTime[%#s]", method);
+            instantiationCounter = Debug.metric("SnippetInstantiationCount[%s]", method);
+            instantiationTimer = Debug.timer("SnippetInstantiationTime[%s]", method);
             assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
             int count = method.getSignature().getParameterCount(false);
             constantParameters = new boolean[count];
@@ -728,8 +728,8 @@
     private final ArrayList<StateSplit> sideEffectNodes;
 
     /**
-     * Nodes that inherit the {@link DeoptimizingNode#getDeoptimizationState()} from the replacee
-     * during instantiation.
+     * Nodes that inherit a deoptimization {@link FrameState} from the replacee during
+     * instantiation.
      */
     private final ArrayList<DeoptimizingNode> deoptNodes;
 
@@ -1024,11 +1024,50 @@
 
             if (replacee instanceof DeoptimizingNode) {
                 DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee;
-                FrameState state = replaceeDeopt.getDeoptimizationState();
+
+                FrameState stateBefore = null;
+                FrameState stateDuring = null;
+                FrameState stateAfter = null;
+                if (replaceeDeopt.canDeoptimize()) {
+                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptBefore) {
+                        stateBefore = ((DeoptimizingNode.DeoptBefore) replaceeDeopt).stateBefore();
+                    }
+                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptDuring) {
+                        stateDuring = ((DeoptimizingNode.DeoptDuring) replaceeDeopt).stateDuring();
+                    }
+                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptAfter) {
+                        stateAfter = ((DeoptimizingNode.DeoptAfter) replaceeDeopt).stateAfter();
+                    }
+                }
+
                 for (DeoptimizingNode deoptNode : deoptNodes) {
                     DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode);
-                    assert replaceeDeopt.canDeoptimize() || !deoptDup.canDeoptimize();
-                    deoptDup.setDeoptimizationState(state);
+                    if (deoptDup.canDeoptimize()) {
+                        if (deoptDup instanceof DeoptimizingNode.DeoptBefore) {
+                            ((DeoptimizingNode.DeoptBefore) deoptDup).setStateBefore(stateBefore);
+                        }
+                        if (deoptDup instanceof DeoptimizingNode.DeoptDuring) {
+                            DeoptimizingNode.DeoptDuring deoptDupDuring = (DeoptimizingNode.DeoptDuring) deoptDup;
+                            if (stateDuring != null) {
+                                deoptDupDuring.setStateDuring(stateDuring);
+                            } else if (stateAfter != null) {
+                                deoptDupDuring.computeStateDuring(stateAfter);
+                            } else if (stateBefore != null) {
+                                assert !deoptDupDuring.hasSideEffect() : "can't use stateBefore as stateDuring for state split " + deoptDupDuring;
+                                deoptDupDuring.setStateDuring(stateBefore);
+                            }
+                        }
+                        if (deoptDup instanceof DeoptimizingNode.DeoptAfter) {
+                            DeoptimizingNode.DeoptAfter deoptDupAfter = (DeoptimizingNode.DeoptAfter) deoptDup;
+                            if (stateAfter != null) {
+                                deoptDupAfter.setStateAfter(stateAfter);
+                            } else {
+                                assert !deoptDupAfter.hasSideEffect() : "can't use stateBefore as stateAfter for state split " + deoptDupAfter;
+                                deoptDupAfter.setStateAfter(stateBefore);
+                            }
+
+                        }
+                    }
                 }
             }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -88,7 +88,7 @@
 
     public Constant evalConst(Constant... inputs) {
         assert inputs.length == 1;
-        return Constant.forDouble(compute(inputs[0].asDouble(), operation()));
+        return Constant.forDouble(doCompute(inputs[0].asDouble(), operation()));
     }
 
     @Override
@@ -101,6 +101,10 @@
 
     @NodeIntrinsic
     public static double compute(double value, @ConstantNodeParameter Operation op) {
+        return doCompute(value, op);
+    }
+
+    private static double doCompute(double value, Operation op) throws GraalInternalError {
         switch (op) {
             case ABS:
                 return Math.abs(value);
--- a/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java	Wed Mar 26 20:44:11 2014 +0100
@@ -34,12 +34,16 @@
 
 import com.oracle.graal.api.runtime.*;
 
-@SupportedSourceVersion(SourceVersion.RELEASE_7)
 @SupportedAnnotationTypes("com.oracle.graal.api.runtime.ServiceProvider")
 public class ServiceProviderProcessor extends AbstractProcessor {
 
     private final Set<TypeElement> processed = new HashSet<>();
 
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
     private boolean verifyAnnotation(TypeMirror serviceInterface, TypeElement serviceProvider) {
         if (!processingEnv.getTypeUtils().isSubtype(serviceProvider.asType(), serviceInterface)) {
             String msg = String.format("Service provider class %s doesn't implement service interface %s", serviceProvider.getSimpleName(), serviceInterface);
--- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java	Wed Mar 26 20:44:11 2014 +0100
@@ -48,6 +48,15 @@
                 found = m;
             }
         }
+        if (found == null) {
+            /* Now look for non-public methods (but this does not look in superclasses). */
+            for (Method m : clazz.getDeclaredMethods()) {
+                if (m.getName().equals(methodName)) {
+                    Assert.assertNull(found);
+                    found = m;
+                }
+            }
+        }
         if (found != null) {
             return found;
         } else {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Wed Mar 26 20:44:11 2014 +0100
@@ -137,6 +137,13 @@
         callAndLoopCount++;
     }
 
+    void reportInlinedCall() {
+        callCount++;
+        callAndLoopCount++;
+        compilationCallThreshold++;
+        compilationCallAndLoopThreshold++;
+    }
+
     void reportInterpreterCalls(int calls) {
         this.callCount += calls;
         this.callAndLoopCount += calls;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Wed Mar 26 20:44:11 2014 +0100
@@ -78,7 +78,7 @@
             throw new IllegalStateException("CallNode must be adopted before it is split.");
         }
 
-        return replace(new InlinedOptimizedCallNode(getCallTarget(), getSplitCallTarget(), getCurrentCallTarget().getRootNode(), callCount));
+        return replace(new InlinedOptimizedCallNode(getCallTarget(), getSplitCallTarget(), callCount));
     }
 
     public static OptimizedCallNode create(OptimizedCallTarget target) {
@@ -211,12 +211,10 @@
 
     private static final class InlinedOptimizedCallNode extends OptimizedCallNode {
 
-        private final RootNode inlinedRoot;
         private final OptimizedCallTarget splittedTarget;
 
-        public InlinedOptimizedCallNode(OptimizedCallTarget target, OptimizedCallTarget splittedTarget, RootNode inlinedRoot, int callCount) {
+        public InlinedOptimizedCallNode(OptimizedCallTarget target, OptimizedCallTarget splittedTarget, int callCount) {
             super(target);
-            this.inlinedRoot = inlinedRoot;
             this.splittedTarget = splittedTarget;
             this.callCount = callCount;
         }
@@ -226,7 +224,7 @@
             if (CompilerDirectives.inInterpreter()) {
                 callCount++;
             }
-            return inlinedRoot.execute(Truffle.getRuntime().createVirtualFrame(caller, arguments, inlinedRoot.getFrameDescriptor()));
+            return getCurrentCallTarget().callInlined(caller, arguments);
         }
 
         @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNodeProfile.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNodeProfile.java	Wed Mar 26 20:44:11 2014 +0100
@@ -45,6 +45,7 @@
     private final int targetShallowNodeCount;
     private final double averageFrequency;
     private final double score;
+    private final boolean leaf;
     private String reason;
 
     public OptimizedCallNodeProfile(OptimizedCallTarget target, OptimizedCallNode callNode) {
@@ -56,6 +57,22 @@
         this.compilationRoots = findCompilationRoots(callNode);
         this.averageFrequency = calculateFrequency();
         this.score = calculateScore();
+        this.leaf = calculateLeaf();
+
+    }
+
+    private boolean calculateLeaf() {
+        return NodeUtil.countNodes(callNode.getCurrentRootNode(), new NodeCountFilter() {
+            public boolean isCounted(Node node) {
+                if (node instanceof CallNode) {
+                    CallNode childCall = (CallNode) node;
+                    if (!childCall.isInlined()) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }, true) <= 0;
     }
 
     private double calculateFrequency() {
@@ -71,7 +88,7 @@
     }
 
     public double calculateScore() {
-        return averageFrequency / targetDeepNodeCount;
+        return averageFrequency / Math.max(1, targetDeepNodeCount);
     }
 
     public boolean isInliningAllowed() {
@@ -188,17 +205,13 @@
         for (OptimizedCallNode c : callStack) {
             int childCallCount = c.getCallCount();
             frequency *= childCallCount / (double) parentCallCount;
-            if (c.isInlined() || c.isSplit()) {
-                parentCallCount = childCallCount;
-            } else {
-                parentCallCount = c.getCurrentCallTarget().getCompilationProfile().getCallCount();
-            }
+            parentCallCount = c.getCurrentCallTarget().getCompilationProfile().getCallCount();
         }
         return frequency;
     }
 
     double calculateSimpleFrequency() {
-        return callNode.getCallCount() / (double) callTarget.getCompilationProfile().getCallCount();
+        return callNode.getCallCount() / (double) ((OptimizedCallTarget) callNode.getRootNode().getCallTarget()).getCompilationProfile().getCallCount();
     }
 
     static List<OptimizedCallTarget> findCompilationRoots(Node call) {
@@ -218,7 +231,11 @@
 
     public int compareTo(TruffleInliningProfile o) {
         if (o instanceof OptimizedCallNodeProfile) {
-            return Double.compare(((OptimizedCallNodeProfile) o).getScore(), getScore());
+            int cmp = Boolean.compare(((OptimizedCallNodeProfile) o).leaf, leaf);
+            if (cmp == 0) {
+                return Double.compare(((OptimizedCallNodeProfile) o).getScore(), getScore());
+            }
+            return cmp;
         }
         return 0;
     }
@@ -231,7 +248,7 @@
         properties.put("inlinedTotalCount", calculateInlinedTotalNodeCount(getCallNode()));
         properties.put("score", score);
         properties.put("frequency", averageFrequency);
-        properties.put("callCount", callNode.getCallCount());
+        properties.put("leaf", leaf);
         properties.put("reason", reason);
         return properties;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Mar 26 20:44:11 2014 +0100
@@ -102,6 +102,13 @@
         return callHelper(caller, args);
     }
 
+    public Object callInlined(PackedFrame caller, Arguments arguments) {
+        if (CompilerDirectives.inInterpreter()) {
+            compilationProfile.reportInlinedCall();
+        }
+        return executeHelper(caller, arguments);
+    }
+
     private Object callHelper(PackedFrame caller, Arguments args) {
         if (installedCode != null && installedCode.isValid()) {
             reinstallCallMethodShortcut();
@@ -196,8 +203,8 @@
         while (callSite != null) {
             if (callSite.isInliningAllowed()) {
                 OptimizedCallNode callNode = callSite.getCallNode();
+                RootNode inlinedRoot = callNode.inlineImpl().getCurrentRootNode();
                 logInlined(this, callSite);
-                RootNode inlinedRoot = callNode.inlineImpl().getCurrentRootNode();
                 assert inlinedRoot != null;
                 queueCallSitesForInlining(this, inlinedRoot, visitedCallNodes, queue);
             } else {
@@ -334,7 +341,7 @@
         }
     }
 
-    private static void logInlined(@SuppressWarnings("unused") final OptimizedCallTarget target, TruffleInliningProfile callSite) {
+    private static void logInlined(final OptimizedCallTarget target, TruffleInliningProfile callSite) {
         if (TraceTruffleInliningDetails.getValue() || TraceTruffleInlining.getValue()) {
             log(2, "inline success", callSite.getCallNode().getCurrentCallTarget().toString(), callSite.getDebugProperties());
 
@@ -348,13 +355,23 @@
                             OptimizedCallNode callNode = ((OptimizedCallNode) node);
                             RootNode inlinedRoot = callNode.getCurrentRootNode();
 
-                            if (inlinedRoot != null && callNode.isInlined()) {
+                            if (inlinedRoot != null) {
                                 Map<String, Object> properties = new LinkedHashMap<>();
                                 addASTSizeProperty(callNode.getCurrentRootNode(), properties);
-                                log(2 + (depth * 2), "inline success", callNode.getCurrentCallTarget().toString(), properties);
-                                depth++;
-                                inlinedRoot.accept(this);
-                                depth--;
+                                properties.putAll(callNode.createInliningProfile(target).getDebugProperties());
+                                String message;
+                                if (callNode.isInlined()) {
+                                    message = "inline success";
+                                } else {
+                                    message = "inline dispatch";
+                                }
+                                log(2 + (depth * 2), message, callNode.getCurrentCallTarget().toString(), properties);
+
+                                if (callNode.isInlined()) {
+                                    depth++;
+                                    inlinedRoot.accept(this);
+                                    depth--;
+                                }
                             }
                         }
                         return true;
@@ -566,4 +583,5 @@
             });
         }
     }
+
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java	Wed Mar 26 20:44:11 2014 +0100
@@ -43,7 +43,7 @@
     }
 
     public void preExpand(MethodCallTargetNode callTarget, StructuredGraph inliningGraph) {
-        ResolvedJavaMethod sourceMethod = callTarget.invoke().getState().method();
+        ResolvedJavaMethod sourceMethod = callTarget.invoke().stateAfter().method();
 
         int sourceMethodBci = callTarget.invoke().bci();
         ResolvedJavaMethod targetMethod = callTarget.targetMethod();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -42,8 +42,8 @@
     }
 
     public static final void trace(String format, Object... obj) {
-        if (TraceEscapeAnalysis.getValue()) {
-            Debug.log(format, obj);
+        if (TraceEscapeAnalysis.getValue() && Debug.isLogEnabled()) {
+            Debug.logv(format, obj);
         }
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Mar 26 20:44:11 2014 +0100
@@ -132,75 +132,78 @@
     }
 
     private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) {
-        FrameState frameState = nodeWithState.getState();
-        if (frameState != null) {
-            if (frameState.usages().count() > 1) {
-                nodeWithState.asNode().replaceFirstInput(frameState, frameState.copyWithInputs());
-                frameState = nodeWithState.getState();
-            }
-            final Set<ObjectState> virtual = new ArraySet<>();
-            frameState.applyToNonVirtual(new NodeClosure<ValueNode>() {
+        for (Node input : nodeWithState.asNode().inputs()) {
+            if (input instanceof FrameState) {
+                FrameState frameState = (FrameState) input;
+                if (frameState.usages().count() > 1) {
+                    FrameState copy = (FrameState) frameState.copyWithInputs();
+                    nodeWithState.asNode().replaceFirstInput(frameState, copy);
+                    frameState = copy;
+                }
+                final Set<ObjectState> virtual = new ArraySet<>();
+                frameState.applyToNonVirtual(new NodeClosure<ValueNode>() {
 
-                @Override
-                public void apply(Node usage, ValueNode value) {
-                    ObjectState valueObj = getObjectState(state, value);
-                    if (valueObj != null) {
-                        virtual.add(valueObj);
-                        effects.replaceFirstInput(usage, value, valueObj.virtual);
-                    } else if (value instanceof VirtualObjectNode) {
-                        ObjectState virtualObj = null;
-                        for (ObjectState obj : state.getStates()) {
-                            if (value == obj.virtual) {
-                                virtualObj = obj;
-                                break;
+                    @Override
+                    public void apply(Node usage, ValueNode value) {
+                        ObjectState valueObj = getObjectState(state, value);
+                        if (valueObj != null) {
+                            virtual.add(valueObj);
+                            effects.replaceFirstInput(usage, value, valueObj.virtual);
+                        } else if (value instanceof VirtualObjectNode) {
+                            ObjectState virtualObj = null;
+                            for (ObjectState obj : state.getStates()) {
+                                if (value == obj.virtual) {
+                                    virtualObj = obj;
+                                    break;
+                                }
+                            }
+                            if (virtualObj != null) {
+                                virtual.add(virtualObj);
                             }
                         }
-                        if (virtualObj != null) {
-                            virtual.add(virtualObj);
-                        }
+                    }
+                });
+                for (ObjectState obj : state.getStates()) {
+                    if (obj.isVirtual() && obj.hasLocks()) {
+                        virtual.add(obj);
                     }
                 }
-            });
-            for (ObjectState obj : state.getStates()) {
-                if (obj.isVirtual() && obj.hasLocks()) {
-                    virtual.add(obj);
-                }
-            }
 
-            ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
-            while (!queue.isEmpty()) {
-                ObjectState obj = queue.removeLast();
-                if (obj.isVirtual()) {
-                    for (ValueNode field : obj.getEntries()) {
-                        if (field instanceof VirtualObjectNode) {
-                            ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
-                            if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
-                                virtual.add(fieldObj);
-                                queue.addLast(fieldObj);
+                ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
+                while (!queue.isEmpty()) {
+                    ObjectState obj = queue.removeLast();
+                    if (obj.isVirtual()) {
+                        for (ValueNode field : obj.getEntries()) {
+                            if (field instanceof VirtualObjectNode) {
+                                ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
+                                if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
+                                    virtual.add(fieldObj);
+                                    queue.addLast(fieldObj);
+                                }
                             }
                         }
                     }
                 }
-            }
-            for (ObjectState obj : virtual) {
-                EscapeObjectState v;
-                if (obj.isVirtual()) {
-                    ValueNode[] fieldState = obj.getEntries().clone();
-                    for (int i = 0; i < fieldState.length; i++) {
-                        ObjectState valueObj = getObjectState(state, fieldState[i]);
-                        if (valueObj != null) {
-                            if (valueObj.isVirtual()) {
-                                fieldState[i] = valueObj.virtual;
-                            } else {
-                                fieldState[i] = valueObj.getMaterializedValue();
+                for (ObjectState obj : virtual) {
+                    EscapeObjectState v;
+                    if (obj.isVirtual()) {
+                        ValueNode[] fieldState = obj.getEntries().clone();
+                        for (int i = 0; i < fieldState.length; i++) {
+                            ObjectState valueObj = getObjectState(state, fieldState[i]);
+                            if (valueObj != null) {
+                                if (valueObj.isVirtual()) {
+                                    fieldState[i] = valueObj.virtual;
+                                } else {
+                                    fieldState[i] = valueObj.getMaterializedValue();
+                                }
                             }
                         }
+                        v = new VirtualObjectState(obj.virtual, fieldState);
+                    } else {
+                        v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
                     }
-                    v = new VirtualObjectState(obj.virtual, fieldState);
-                } else {
-                    v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
+                    effects.addVirtualMapping(frameState, v);
                 }
-                effects.addVirtualMapping(frameState, v);
             }
         }
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Wed Mar 26 20:44:11 2014 +0100
@@ -94,6 +94,9 @@
                 ReadCacheEntry identifier = new ReadCacheEntry(object, read.location());
                 ValueNode cachedValue = state.getCacheEntry(identifier);
                 if (cachedValue != null) {
+                    if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
+                        effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read);
+                    }
                     effects.replaceAtUsages(read, cachedValue);
                     addScalarAlias(read, cachedValue);
                     deleted = true;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Wed Mar 26 20:44:11 2014 +0100
@@ -109,8 +109,8 @@
     }
 
     public static void trace(String format, Object... obj) {
-        if (TraceEscapeAnalysis.getValue()) {
-            Debug.log(format, obj);
+        if (TraceEscapeAnalysis.getValue() && Debug.isLogEnabled()) {
+            Debug.logv(format, obj);
         }
     }
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Mar 26 20:44:11 2014 +0100
@@ -214,7 +214,7 @@
                 } else {
                     location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
                 }
-                replace(invoke, readOp(graph, arguments.get(0), invoke, location, readKind, BarrierType.NONE, false));
+                replace(invoke, readOp(graph, arguments.get(0), invoke, location, StampFactory.forKind(readKind.getStackKind()), BarrierType.NONE, false));
                 break;
             }
             case READ_HEAP: {
@@ -222,7 +222,8 @@
                 Kind readKind = asKind(callTargetNode.returnType());
                 LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
                 BarrierType barrierType = (BarrierType) arguments.get(2).asConstant().asObject();
-                replace(invoke, readOp(graph, arguments.get(0), invoke, location, readKind, barrierType, arguments.get(3).asConstant().asInt() == 0 ? false : true));
+                boolean compressible = arguments.get(3).asConstant().asInt() != 0;
+                replace(invoke, readOp(graph, arguments.get(0), invoke, location, StampFactory.forKind(readKind.getStackKind()), barrierType, compressible));
                 break;
             }
             case WRITE:
@@ -369,8 +370,8 @@
         return IndexedLocationNode.create(locationIdentity, readKind, 0, fromSigned(graph, offset), graph, 1);
     }
 
-    protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, Kind readKind, BarrierType barrierType, boolean compressible) {
-        ReadNode read = graph.add(new ReadNode(base, location, StampFactory.forKind(readKind.getStackKind()), barrierType, compressible));
+    protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, Stamp stamp, BarrierType barrierType, boolean compressible) {
+        ReadNode read = graph.add(new ReadNode(base, location, stamp, barrierType, compressible));
         graph.addBeforeFixed(invoke.asNode(), read);
         /*
          * The read must not float outside its block otherwise it may float above an explicit zero
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Wed Mar 26 20:44:11 2014 +0100
@@ -64,7 +64,7 @@
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.NONE, node.getNode().getCost());
+        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -75,7 +75,7 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.NONE, node.getNode().getCost());
+        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Wed Mar 26 20:44:11 2014 +0100
@@ -42,7 +42,7 @@
         assertEquals(21, executeWith(node, false, false));
         assertEquals(42, executeWith(node, 21, 21));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(NodeCost.NONE, node.getNode().getCost());
+        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Mar 26 20:44:11 2014 +0100
@@ -122,6 +122,20 @@
                 return unsafe.getObject(node, offset);
             }
         }
+
+        @Override
+        public int hashCode() {
+            return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof NodeField) {
+                NodeField other = (NodeField) obj;
+                return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind);
+            }
+            return false;
+        }
     }
 
     /**
@@ -198,6 +212,21 @@
         public long[] getChildrenOffsets() {
             return childrenOffsets;
         }
+
+        @Override
+        public int hashCode() {
+            return Arrays.hashCode(fields) ^ Arrays.hashCode(childOffsets) ^ Arrays.hashCode(childrenOffsets) ^ ((Long) parentOffset).hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof NodeClass) {
+                NodeClass other = (NodeClass) obj;
+                return Arrays.equals(fields, other.fields) && Arrays.equals(childOffsets, other.childOffsets) && Arrays.equals(childrenOffsets, other.childrenOffsets) &&
+                                parentOffset == other.parentOffset;
+            }
+            return false;
+        }
     }
 
     static class NodeIterator implements Iterator<Node> {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Wed Mar 26 17:02:45 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Wed Mar 26 20:44:11 2014 +0100
@@ -98,13 +98,17 @@
         return param.getLocalName();
     }
 
-    private static CodeTree createAccessChild(NodeExecutionData targetExecution) {
+    private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) {
+        String reference = thisReference;
+        if (reference == null) {
+            reference = "this";
+        }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         Element accessElement = targetExecution.getChild().getAccessElement();
         if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
-            builder.string("this.").string(targetExecution.getChild().getName());
+            builder.string(reference).string(".").string(targetExecution.getChild().getName());
         } else if (accessElement.getKind() == ElementKind.FIELD) {
-            builder.string("this.").string(accessElement.getSimpleName().toString());
+            builder.string(reference).string(".").string(accessElement.getSimpleName().toString());
         } else {
             throw new AssertionError();
         }
@@ -357,7 +361,7 @@
                     nodes.nullLiteral();
                     arguments.string(valueName(parameter.getPreviousParameter()));
                 }
-                nodes.tree(createAccessChild(executionData));
+                nodes.tree(createAccessChild(executionData, null));
                 arguments.string(valueName(parameter));
                 empty = false;
             }
@@ -928,12 +932,6 @@
                     var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
                     clazz.add(var);
 
-                    CodeExecutableElement setter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(void.class), "setNext0");
-                    setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0"));
-                    CodeTreeBuilder builder = setter.createBuilder();
-                    builder.statement("this.next0 = insert(next0)");
-                    clazz.add(setter);
-
                     CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
                     clazz.add(genericCachedExecute);
 
@@ -948,41 +946,21 @@
             }
 
             if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createInvokeCopyConstructor(clazz.asType(), null));
-                clazz.add(createCopyPolymorphicConstructor(clazz.asType()));
+                clazz.add(createCopy(clazz.asType(), null));
             }
 
             if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
                 clazz.add(createGenericExecute(node, rootGroup));
             }
 
-            clazz.add(createGetCost(node, null, NodeCost.MONOMORPHIC));
         }
 
         protected boolean needsInvokeCopyConstructorMethod() {
             return getModel().getNode().isPolymorphic();
         }
 
-        protected CodeExecutableElement createGetCost(NodeData node, SpecializationData specialization, NodeCost cost) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getNodeCost(), "getCost");
-
-            TypeMirror nodeInfoKind = context.getTruffleTypes().getNodeCost();
-
-            CodeTreeBuilder builder = method.createBuilder();
-            if (node.isPolymorphic() && specialization == null) {
-                // assume next0 exists
-                builder.startIf().string("next0 != null && next0.getCost() != ").staticReference(nodeInfoKind, "UNINITIALIZED").end();
-                builder.startBlock();
-                builder.startReturn().staticReference(nodeInfoKind, "POLYMORPHIC").end();
-                builder.end();
-            }
-
-            builder.startReturn().staticReference(nodeInfoKind, cost.name()).end();
-            return method;
-        }
-
-        protected CodeExecutableElement createInvokeCopyConstructor(TypeMirror baseType, SpecializationData specialization) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), baseType, "invokeCopyConstructor");
+        protected CodeExecutableElement createCopy(TypeMirror baseType, SpecializationData specialization) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), baseType, "copyWithConstructor");
             if (specialization == null) {
                 method.getModifiers().add(ABSTRACT);
             } else {
@@ -998,36 +976,6 @@
             return method;
         }
 
-        protected CodeExecutableElement createCopyPolymorphicConstructor(TypeMirror baseType) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), baseType, "copyPolymorphic");
-            CodeTreeBuilder builder = method.createBuilder();
-            CodeTreeBuilder nullBuilder = builder.create();
-            CodeTreeBuilder oldBuilder = builder.create();
-            CodeTreeBuilder resetBuilder = builder.create();
-
-            for (ActualParameter param : getModel().getSignatureParameters()) {
-                NodeExecutionData execution = param.getSpecification().getExecution();
-
-                CodeTree access = createAccessChild(execution);
-
-                String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName());
-                oldBuilder.declaration(execution.getChild().getNodeData().getNodeType(), oldName, access);
-                nullBuilder.startStatement().tree(access).string(" = null").end();
-                resetBuilder.startStatement().tree(access).string(" = ").string(oldName).end();
-            }
-
-            builder.tree(oldBuilder.getRoot());
-            builder.tree(nullBuilder.getRoot());
-
-            builder.startStatement().type(baseType).string(" copy = ");
-            builder.startCall("invokeCopyConstructor").end();
-            builder.end();
-
-            builder.tree(resetBuilder.getRoot());
-            builder.startReturn().string("copy").end();
-            return method;
-        }
-
         private List<CodeExecutableElement> createImplicitChildrenAccessors() {
             NodeData node = getModel().getNode();
             // Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>();
@@ -1280,7 +1228,7 @@
 
         private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node, SpecializationGroup rootGroup) {
             TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_SPECIALIZE_NAME);
             method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState"));
             addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
             method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
@@ -1341,7 +1289,7 @@
 
         private CodeExecutableElement createGenericExecute(NodeData node, SpecializationGroup group) {
             TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_GENERIC_NAME);
 
             if (!node.needsFrame(getContext())) {
                 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
@@ -1816,11 +1764,16 @@
             String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
             CodeTreeBuilder builder = parent.create();
 
-            builder.declaration(getElement().asType(), "currentCopy", currentNode + ".copyPolymorphic()");
+            builder.declaration(getElement().asType(), "currentCopy", currentNode + ".copyWithConstructor()");
+            for (ActualParameter param : getModel().getSignatureParameters()) {
+                NodeExecutionData execution = param.getSpecification().getExecution();
+                builder.startStatement().tree(createAccessChild(execution, "currentCopy")).string(" = ").nullLiteral().end();
+            }
+            builder.startStatement().string("currentCopy.next0 = ").startNew(uninitializedName).string("currentCopy").end().end();
+
             builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end());
+            builder.startStatement().string("polymorphic.next0 = ").string("currentCopy").end();
             builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end();
-            builder.startStatement().startCall("polymorphic", "setNext0").string("currentCopy").end().end();
-            builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end();
 
             builder.startReturn();
             builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME);
@@ -2300,7 +2253,7 @@
         private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             if (targetExecution != null) {
-                builder.tree(createAccessChild(targetExecution));
+                builder.tree(createAccessChild(targetExecution, null));
                 builder.string(".");
             }
 
@@ -2465,7 +2418,7 @@
             }
             CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
 
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.NONE));
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC));
 
             for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) {
                 if (!polymorphParameter.getTypeSystemType().isGeneric()) {
@@ -2508,11 +2461,10 @@
             }
 
             if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization));
+                clazz.add(createCopy(nodeGen.asType(), specialization));
             }
 
             createCachedExecuteMethods(specialization);
-            clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.NONE));
         }
 
         private ExecutableElement createUpdateType(ActualParameter parameter) {
@@ -2558,7 +2510,7 @@
             } else if (specialization.isUninitialized()) {
                 cost = NodeCost.UNINITIALIZED;
             } else if (specialization.isPolymorphic()) {
-                cost = NodeCost.NONE;
+                cost = NodeCost.POLYMORPHIC;
             } else if (specialization.isSpecialized()) {
                 cost = NodeCost.MONOMORPHIC;
             } else {
@@ -2594,13 +2546,7 @@
                 getElement().add(createUpdateTypes(nodeGen.asType()));
             }
             if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization));
-            }
-
-            if (specialization.isGeneric()) {
-                clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.MEGAMORPHIC));
-            } else if (specialization.isUninitialized()) {
-                clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.UNINITIALIZED));
+                clazz.add(createCopy(nodeGen.asType(), specialization));
             }
         }
 
@@ -2726,9 +2672,9 @@
             builder.end();
 
             builder.startElseBlock();
-            builder.startStatement().startCall("setNext0");
+            builder.startStatement().string("next0 = ");
             builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
-            builder.end().end();
+            builder.end();
 
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
             specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
--- a/mx/mx_graal.py	Wed Mar 26 17:02:45 2014 +0100
+++ b/mx/mx_graal.py	Wed Mar 26 20:44:11 2014 +0100
@@ -79,7 +79,8 @@
 
 _make_eclipse_launch = False
 
-_minVersion = mx.VersionSpec('1.7.0_04')
+# @CallerSensitive introduced in 7u25
+_minVersion = mx.VersionSpec('1.7.0_25')
 
 JDK_UNIX_PERMISSIONS = 0755
 
@@ -647,11 +648,17 @@
             env.setdefault('ALT_BOOTDIR', mx.java().jdk)
 
             # extract latest release tag for graal
-            tags = [x.split(' ')[0] for x in subprocess.check_output(['hg', 'tags']).split('\n') if x.startswith("graal-")]
+            try:
+                tags = [x.split(' ')[0] for x in subprocess.check_output(['hg', 'tags']).split('\n') if x.startswith("graal-")]
+            except:
+                # not a mercurial repository or hg commands are not available.
+                tags = None
+
             if tags:
                 # extract the most recent tag
                 tag = sorted(tags, key=lambda e: [int(x) for x in e[len("graal-"):].split('.')], reverse=True)[0]
                 env.setdefault('USER_RELEASE_SUFFIX', tag)
+
             if not mx._opts.verbose:
                 runCmd.append('MAKE_VERBOSE=')
             env['JAVA_HOME'] = jdk
@@ -784,7 +791,7 @@
     matches = lambda line: len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
     return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
 
-def _extract_VM_args(args, allowClasspath=False, useDoubleDash=False):
+def _extract_VM_args(args, allowClasspath=False, useDoubleDash=False, defaultAllVMArgs=True):
     """
     Partitions a command line into a leading sequence of HotSpot VM options and the rest.
     """
@@ -805,7 +812,10 @@
                 remainder = args[i:]
                 return vmArgs, remainder
 
-    return args, []
+    if defaultAllVMArgs:
+        return args, []
+    else:
+        return [], args
 
 def _run_tests(args, harness, annotations, testfile):
 
@@ -1139,6 +1149,11 @@
             t.abort('Checkstyle warnings were found')
         tasks.append(t.stop())
 
+        t = Task('FindBugs')
+        if findbugs([]) != 0:
+            t.abort('FindBugs warnings were found')
+        tasks.append(t.stop())
+
         if exists('jacoco.exec'):
             os.unlink('jacoco.exec')
 
--- a/mx/projects	Wed Mar 26 17:02:45 2014 +0100
+++ b/mx/projects	Wed Mar 26 20:44:11 2014 +0100
@@ -39,7 +39,7 @@
 library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim-src.jar
 
 library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar
-library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter.jar
+library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-67ad4ee8beb6.jar
 library@JAVA_ALLOCATION_INSTRUMENTER@sha1=1cd4073f57d7d461a53b0ddc1ea4ee2aa0c60e66
 
 distribution@GRAAL@path=graal.jar
@@ -56,7 +56,7 @@
 project@com.oracle.graal.api.runtime@subDir=graal
 project@com.oracle.graal.api.runtime@sourceDirs=src
 project@com.oracle.graal.api.runtime@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.api.runtime@javaCompliance=1.7
+project@com.oracle.graal.api.runtime@javaCompliance=1.8
 project@com.oracle.graal.api.runtime@workingSets=API,Graal
 
 # graal.api.test
@@ -64,14 +64,14 @@
 project@com.oracle.graal.api.test@sourceDirs=src
 project@com.oracle.graal.api.test@dependencies=JUNIT,com.oracle.graal.api.runtime
 project@com.oracle.graal.api.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.api.test@javaCompliance=1.7
+project@com.oracle.graal.api.test@javaCompliance=1.8
 project@com.oracle.graal.api.test@workingSets=API,Graal,Test
 
 # graal.api.meta
 project@com.oracle.graal.api.meta@subDir=graal
 project@com.oracle.graal.api.meta@sourceDirs=src
 project@com.oracle.graal.api.meta@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.api.meta@javaCompliance=1.7
+project@com.oracle.graal.api.meta@javaCompliance=1.8
 project@com.oracle.graal.api.meta@workingSets=API,Graal
 
 # graal.api.meta.test
@@ -79,7 +79,7 @@
 project@com.oracle.graal.api.meta.test@sourceDirs=src
 project@com.oracle.graal.api.meta.test@dependencies=JUNIT,com.oracle.graal.runtime,com.oracle.graal.java
 project@com.oracle.graal.api.meta.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.api.meta.test@javaCompliance=1.7
+project@com.oracle.graal.api.meta.test@javaCompliance=1.8
 project@com.oracle.graal.api.meta.test@workingSets=API,Graal,Test
 
 # graal.api.meta.jdk8.test
@@ -95,7 +95,7 @@
 project@com.oracle.graal.api.code@sourceDirs=src
 project@com.oracle.graal.api.code@dependencies=com.oracle.graal.api.meta
 project@com.oracle.graal.api.code@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.api.code@javaCompliance=1.7
+project@com.oracle.graal.api.code@javaCompliance=1.8
 project@com.oracle.graal.api.code@workingSets=API,Graal
 
 # graal.api.replacements
@@ -103,7 +103,7 @@
 project@com.oracle.graal.api.replacements@sourceDirs=src
 project@com.oracle.graal.api.replacements@dependencies=com.oracle.graal.api.meta
 project@com.oracle.graal.api.replacements@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.api.replacements@javaCompliance=1.7
+project@com.oracle.graal.api.replacements@javaCompliance=1.8
 project@com.oracle.graal.api.replacements@workingSets=API,Graal,Replacements
 
 # graal.service.processor
@@ -111,7 +111,7 @@
 project@com.oracle.graal.service.processor@sourceDirs=src
 project@com.oracle.graal.service.processor@dependencies=com.oracle.graal.api.runtime
 project@com.oracle.graal.service.processor@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.service.processor@javaCompliance=1.7
+project@com.oracle.graal.service.processor@javaCompliance=1.8
 project@com.oracle.graal.service.processor@workingSets=Codegen,HotSpot
 
 # graal.amd64
@@ -119,7 +119,7 @@
 project@com.oracle.graal.amd64@sourceDirs=src
 project@com.oracle.graal.amd64@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.amd64@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.amd64@javaCompliance=1.7
+project@com.oracle.graal.amd64@javaCompliance=1.8
 project@com.oracle.graal.amd64@workingSets=Graal,AMD64
 
 # graal.ptx
@@ -127,7 +127,7 @@
 project@com.oracle.graal.ptx@sourceDirs=src
 project@com.oracle.graal.ptx@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.ptx@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.ptx@javaCompliance=1.7
+project@com.oracle.graal.ptx@javaCompliance=1.8
 project@com.oracle.graal.ptx@workingSets=Graal,PTX
 
 # graal.sparc
@@ -135,7 +135,7 @@
 project@com.oracle.graal.sparc@sourceDirs=src
 project@com.oracle.graal.sparc@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.sparc@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.sparc@javaCompliance=1.7
+project@com.oracle.graal.sparc@javaCompliance=1.8
 project@com.oracle.graal.sparc@workingSets=Graal,SPARC
 
 # graal.hotspot
@@ -144,7 +144,7 @@
 project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer, com.oracle.graal.baseline
 project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor
-project@com.oracle.graal.hotspot@javaCompliance=1.7
+project@com.oracle.graal.hotspot@javaCompliance=1.8
 project@com.oracle.graal.hotspot@workingSets=Graal,HotSpot
 
 # graal.hotspot.amd64
@@ -153,7 +153,7 @@
 project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.compiler.amd64,com.oracle.graal.hotspot,com.oracle.graal.replacements.amd64
 project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor
-project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7
+project@com.oracle.graal.hotspot.amd64@javaCompliance=1.8
 project@com.oracle.graal.hotspot.amd64@workingSets=Graal,HotSpot,AMD64
 
 # graal.hotspot.sparc
@@ -162,7 +162,7 @@
 project@com.oracle.graal.hotspot.sparc@dependencies=com.oracle.graal.compiler.sparc
 project@com.oracle.graal.hotspot.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.sparc@annotationProcessors=com.oracle.graal.service.processor
-project@com.oracle.graal.hotspot.sparc@javaCompliance=1.7
+project@com.oracle.graal.hotspot.sparc@javaCompliance=1.8
 project@com.oracle.graal.hotspot.sparc@workingSets=Graal,HotSpot,SPARC
 
 # graal.hotspot.ptx
@@ -171,7 +171,7 @@
 project@com.oracle.graal.hotspot.ptx@dependencies=com.oracle.graal.ptx,com.oracle.graal.compiler.ptx,com.oracle.graal.hotspot
 project@com.oracle.graal.hotspot.ptx@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.ptx@annotationProcessors=com.oracle.graal.service.processor
-project@com.oracle.graal.hotspot.ptx@javaCompliance=1.7
+project@com.oracle.graal.hotspot.ptx@javaCompliance=1.8
 project@com.oracle.graal.hotspot.ptx@workingSets=Graal,HotSpot,PTX
 
 # graal.hotspot.hsail
@@ -180,7 +180,7 @@
 project@com.oracle.graal.hotspot.hsail@dependencies=com.oracle.graal.replacements.hsail,com.oracle.graal.hotspot
 project@com.oracle.graal.hotspot.hsail@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.hsail@annotationProcessors=com.oracle.graal.service.processor
-project@com.oracle.graal.hotspot.hsail@javaCompliance=1.7
+project@com.oracle.graal.hotspot.hsail@javaCompliance=1.8
 project@com.oracle.graal.hotspot.hsail@workingSets=Graal,HotSpot,PTX
 
 # graal.hotspot.server
@@ -188,7 +188,7 @@
 project@com.oracle.graal.hotspot.server@sourceDirs=src
 project@com.oracle.graal.hotspot.server@dependencies=com.oracle.graal.hotspot
 project@com.oracle.graal.hotspot.server@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.hotspot.server@javaCompliance=1.7
+project@com.oracle.graal.hotspot.server@javaCompliance=1.8
 project@com.oracle.graal.hotspot.server@workingSets=Graal,HotSpot
 
 # graal.hotspot.test
@@ -196,7 +196,7 @@
 project@com.oracle.graal.hotspot.test@sourceDirs=src
 project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test,com.oracle.graal.hotspot
 project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.hotspot.test@javaCompliance=1.7
+project@com.oracle.graal.hotspot.test@javaCompliance=1.8
 project@com.oracle.graal.hotspot.test@workingSets=Graal,HotSpot,Test
 
 # graal.hotspot.jdk8.test
@@ -212,14 +212,14 @@
 project@com.oracle.graal.hotspot.amd64.test@sourceDirs=src
 project@com.oracle.graal.hotspot.amd64.test@dependencies=com.oracle.graal.asm.amd64,com.oracle.graal.compiler.test
 project@com.oracle.graal.hotspot.amd64.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.7
+project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.8
 project@com.oracle.graal.hotspot.amd64.test@workingSets=Graal,HotSpot,AMD64,Test
 
 # graal.options
 project@com.oracle.graal.options@subDir=graal
 project@com.oracle.graal.options@sourceDirs=src
 project@com.oracle.graal.options@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.options@javaCompliance=1.7
+project@com.oracle.graal.options@javaCompliance=1.8
 project@com.oracle.graal.options@annotationProcessorForDependents=true
 project@com.oracle.graal.options@workingSets=Graal,Codegen
 
@@ -228,14 +228,14 @@
 project@com.oracle.graal.options.test@sourceDirs=src
 project@com.oracle.graal.options.test@dependencies=com.oracle.graal.options,JUNIT
 project@com.oracle.graal.options.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.options.test@javaCompliance=1.7
+project@com.oracle.graal.options.test@javaCompliance=1.8
 project@com.oracle.graal.options.test@workingSets=Graal
 
 # graal.graph
 project@com.oracle.graal.graph@subDir=graal
 project@com.oracle.graal.graph@sourceDirs=src
 project@com.oracle.graal.graph@dependencies=com.oracle.graal.debug,com.oracle.graal.api.code
-project@com.oracle.graal.graph@javaCompliance=1.7
+project@com.oracle.graal.graph@javaCompliance=1.8
 project@com.oracle.graal.graph@workingSets=Graal,Graph
 
 # graal.graph.test
@@ -243,14 +243,14 @@
 project@com.oracle.graal.graph.test@sourceDirs=src
 project@com.oracle.graal.graph.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.graph.test@dependencies=JUNIT,com.oracle.graal.graph
-project@com.oracle.graal.graph.test@javaCompliance=1.7
+project@com.oracle.graal.graph.test@javaCompliance=1.8
 project@com.oracle.graal.graph.test@workingSets=Graal,Graph,Test
 
 # graal.debug
 project@com.oracle.graal.debug@subDir=graal
 project@com.oracle.graal.debug@sourceDirs=src
 project@com.oracle.graal.debug@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.debug@javaCompliance=1.7
+project@com.oracle.graal.debug@javaCompliance=1.8
 project@com.oracle.graal.debug@workingSets=Graal,Debug
 
 # graal.debug.test
@@ -258,7 +258,7 @@
 project@com.oracle.graal.debug.test@sourceDirs=src
 project@com.oracle.graal.debug.test@dependencies=JUNIT,com.oracle.graal.debug
 project@com.oracle.graal.debug.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.debug.test@javaCompliance=1.7
+project@com.oracle.graal.debug.test@javaCompliance=1.8
 project@com.oracle.graal.debug.test@workingSets=Graal,Debug,Test
 
 # graal.lir
@@ -266,7 +266,7 @@
 project@com.oracle.graal.lir@sourceDirs=src
 project@com.oracle.graal.lir@dependencies=com.oracle.graal.asm,com.oracle.graal.nodes
 project@com.oracle.graal.lir@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.lir@javaCompliance=1.7
+project@com.oracle.graal.lir@javaCompliance=1.8
 project@com.oracle.graal.lir@workingSets=Graal,LIR
 
 # graal.lir.amd64
@@ -274,7 +274,7 @@
 project@com.oracle.graal.lir.amd64@sourceDirs=src
 project@com.oracle.graal.lir.amd64@dependencies=com.oracle.graal.lir,com.oracle.graal.asm.amd64
 project@com.oracle.graal.lir.amd64@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.lir.amd64@javaCompliance=1.7
+project@com.oracle.graal.lir.amd64@javaCompliance=1.8
 project@com.oracle.graal.lir.amd64@workingSets=Graal,LIR,AMD64
 
 # graal.lir.ptx
@@ -282,7 +282,7 @@
 project@com.oracle.graal.lir.ptx@sourceDirs=src
 project@com.oracle.graal.lir.ptx@dependencies=com.oracle.graal.asm.ptx
 project@com.oracle.graal.lir.ptx@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.lir.ptx@javaCompliance=1.7
+project@com.oracle.graal.lir.ptx@javaCompliance=1.8
 project@com.oracle.graal.lir.ptx@workingSets=Graal,LIR,PTX
 
 # graal.lir.sparc
@@ -290,7 +290,7 @@
 project@com.oracle.graal.lir.sparc@sourceDirs=src
 project@com.oracle.graal.lir.sparc@dependencies=com.oracle.graal.asm.sparc
 project@com.oracle.graal.lir.sparc@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.lir.sparc@javaCompliance=1.7
+project@com.oracle.graal.lir.sparc@javaCompliance=1.8
 project@com.oracle.graal.lir.sparc@workingSets=Graal,LIR,SPARC
 
 # graal.alloc
@@ -298,7 +298,7 @@
 project@com.oracle.graal.alloc@sourceDirs=src
 project@com.oracle.graal.alloc@dependencies=com.oracle.graal.nodes
 project@com.oracle.graal.alloc@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.alloc@javaCompliance=1.7
+project@com.oracle.graal.alloc@javaCompliance=1.8
 project@com.oracle.graal.alloc@workingSets=Graal
 
 # graal.word
@@ -306,7 +306,7 @@
 project@com.oracle.graal.word@sourceDirs=src
 project@com.oracle.graal.word@dependencies=com.oracle.graal.phases
 project@com.oracle.graal.word@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.word@javaCompliance=1.7
+project@com.oracle.graal.word@javaCompliance=1.8
 project@com.oracle.graal.word@workingSets=API,Graal
 
 # graal.replacements
@@ -314,7 +314,7 @@
 project@com.oracle.graal.replacements@sourceDirs=src
 project@com.oracle.graal.replacements@dependencies=com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.word
 project@com.oracle.graal.replacements@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.replacements@javaCompliance=1.7
+project@com.oracle.graal.replacements@javaCompliance=1.8
 project@com.oracle.graal.replacements@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor
 project@com.oracle.graal.replacements@workingSets=Graal,Replacements
 
@@ -323,7 +323,7 @@
 project@com.oracle.graal.replacements.amd64@sourceDirs=src
 project@com.oracle.graal.replacements.amd64@dependencies=com.oracle.graal.replacements
 project@com.oracle.graal.replacements.amd64@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.replacements.amd64@javaCompliance=1.7
+project@com.oracle.graal.replacements.amd64@javaCompliance=1.8
 project@com.oracle.graal.replacements.amd64@annotationProcessors=com.oracle.graal.service.processor
 project@com.oracle.graal.replacements.amd64@workingSets=Graal,Replacements,AMD64
 
@@ -332,7 +332,7 @@
 project@com.oracle.graal.replacements.hsail@sourceDirs=src
 project@com.oracle.graal.replacements.hsail@dependencies=com.oracle.graal.compiler.hsail
 project@com.oracle.graal.replacements.hsail@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.replacements.hsail@javaCompliance=1.7
+project@com.oracle.graal.replacements.hsail@javaCompliance=1.8
 project@com.oracle.graal.replacements.hsail@workingSets=Graal,Replacements,HSAIL
 
 # graal.replacements.test
@@ -340,7 +340,7 @@
 project@com.oracle.graal.replacements.test@sourceDirs=src
 project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test,com.oracle.graal.replacements
 project@com.oracle.graal.replacements.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.replacements.test@javaCompliance=1.7
+project@com.oracle.graal.replacements.test@javaCompliance=1.8
 project@com.oracle.graal.replacements.test@workingSets=Graal,Replacements,Test
 
 # graal.replacements.verifier
@@ -348,7 +348,7 @@
 project@com.oracle.graal.replacements.verifier@sourceDirs=src
 project@com.oracle.graal.replacements.verifier@dependencies=com.oracle.graal.api.replacements,com.oracle.graal.graph
 project@com.oracle.graal.replacements.verifier@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.replacements.verifier@javaCompliance=1.7
+project@com.oracle.graal.replacements.verifier@javaCompliance=1.8
 project@com.oracle.graal.replacements.verifier@workingSets=Graal,Replacements
 
 # graal.nodes
@@ -356,7 +356,7 @@
 project@com.oracle.graal.nodes@sourceDirs=src
 project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements
 project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.nodes@javaCompliance=1.7
+project@com.oracle.graal.nodes@javaCompliance=1.8
 project@com.oracle.graal.nodes@annotationProcessors=com.oracle.graal.replacements.verifier
 project@com.oracle.graal.nodes@workingSets=Graal,Graph
 
@@ -365,7 +365,7 @@
 project@com.oracle.graal.nodes.test@sourceDirs=src
 project@com.oracle.graal.nodes.test@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.nodes.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.nodes.test@javaCompliance=1.7
+project@com.oracle.graal.nodes.test@javaCompliance=1.8
 project@com.oracle.graal.nodes.test@workingSets=Graal,Graph
 
 # graal.phases
@@ -373,7 +373,7 @@
 project@com.oracle.graal.phases@sourceDirs=src
 project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes,com.oracle.graal.options
 project@com.oracle.graal.phases@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.phases@javaCompliance=1.7
+project@com.oracle.graal.phases@javaCompliance=1.8
 project@com.oracle.graal.phases@workingSets=Graal,Phases
 
 # graal.phases.common
@@ -381,7 +381,7 @@
 project@com.oracle.graal.phases.common@sourceDirs=src
 project@com.oracle.graal.phases.common@dependencies=com.oracle.graal.phases
 project@com.oracle.graal.phases.common@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.phases.common@javaCompliance=1.7
+project@com.oracle.graal.phases.common@javaCompliance=1.8
 project@com.oracle.graal.phases.common@workingSets=Graal,Phases
 
 # graal.virtual
@@ -389,7 +389,7 @@
 project@com.oracle.graal.virtual@sourceDirs=src
 project@com.oracle.graal.virtual@dependencies=com.oracle.graal.phases.common
 project@com.oracle.graal.virtual@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.virtual@javaCompliance=1.7
+project@com.oracle.graal.virtual@javaCompliance=1.8
 project@com.oracle.graal.virtual@workingSets=Graal,Phases
 
 # graal.loop
@@ -397,7 +397,7 @@
 project@com.oracle.graal.loop@sourceDirs=src
 project@com.oracle.graal.loop@dependencies=com.oracle.graal.phases.common
 project@com.oracle.graal.loop@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.loop@javaCompliance=1.7
+project@com.oracle.graal.loop@javaCompliance=1.8
 project@com.oracle.graal.loop@workingSets=Graal,Phases
 
 # graal.compiler
@@ -405,7 +405,7 @@
 project@com.oracle.graal.compiler@sourceDirs=src
 project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir
 project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler@javaCompliance=1.7
+project@com.oracle.graal.compiler@javaCompliance=1.8
 project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor
 project@com.oracle.graal.compiler@workingSets=Graal
 
@@ -414,7 +414,7 @@
 project@com.oracle.graal.compiler.amd64@sourceDirs=src
 project@com.oracle.graal.compiler.amd64@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.amd64
 project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.amd64@javaCompliance=1.7
+project@com.oracle.graal.compiler.amd64@javaCompliance=1.8
 project@com.oracle.graal.compiler.amd64@workingSets=Graal,AMD64
 
 # graal.compiler.amd64.test
@@ -422,7 +422,7 @@
 project@com.oracle.graal.compiler.amd64.test@sourceDirs=src
 project@com.oracle.graal.compiler.amd64.test@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.amd64.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.amd64.test@javaCompliance=1.7
+project@com.oracle.graal.compiler.amd64.test@javaCompliance=1.8
 project@com.oracle.graal.compiler.amd64.test@workingSets=Graal,AMD64,Test
 
 # graal.compiler.ptx
@@ -430,7 +430,7 @@
 project@com.oracle.graal.compiler.ptx@sourceDirs=src
 project@com.oracle.graal.compiler.ptx@dependencies=com.oracle.graal.lir.ptx,com.oracle.graal.compiler
 project@com.oracle.graal.compiler.ptx@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.ptx@javaCompliance=1.7
+project@com.oracle.graal.compiler.ptx@javaCompliance=1.8
 project@com.oracle.graal.compiler.ptx@workingSets=Graal,PTX
 
 # graal.compiler.ptx.test
@@ -438,7 +438,7 @@
 project@com.oracle.graal.compiler.ptx.test@sourceDirs=src
 project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.hotspot.ptx,com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7
+project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.8
 project@com.oracle.graal.compiler.ptx.test@workingSets=Graal,PTX,Test
 
 # graal.compiler.sparc
@@ -446,7 +446,7 @@
 project@com.oracle.graal.compiler.sparc@sourceDirs=src
 project@com.oracle.graal.compiler.sparc@dependencies=com.oracle.graal.lir.sparc
 project@com.oracle.graal.compiler.sparc@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.sparc@javaCompliance=1.7
+project@com.oracle.graal.compiler.sparc@javaCompliance=1.8
 project@com.oracle.graal.compiler.sparc@workingSets=Graal,SPARC
 
 # graal.compiler.sparc.test
@@ -454,7 +454,7 @@
 project@com.oracle.graal.compiler.sparc.test@sourceDirs=src
 project@com.oracle.graal.compiler.sparc.test@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.sparc.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.sparc.test@javaCompliance=1.7
+project@com.oracle.graal.compiler.sparc.test@javaCompliance=1.8
 project@com.oracle.graal.compiler.sparc.test@workingSets=Graal,SPARC,Test
 
 # graal.runtime
@@ -462,14 +462,14 @@
 project@com.oracle.graal.runtime@sourceDirs=src
 project@com.oracle.graal.runtime@dependencies=com.oracle.graal.compiler
 project@com.oracle.graal.runtime@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.runtime@javaCompliance=1.7
+project@com.oracle.graal.runtime@javaCompliance=1.8
 project@com.oracle.graal.runtime@workingSets=Graal
 
 # graal.bytecode
 project@com.oracle.graal.bytecode@subDir=graal
 project@com.oracle.graal.bytecode@sourceDirs=src
 project@com.oracle.graal.bytecode@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.bytecode@javaCompliance=1.7
+project@com.oracle.graal.bytecode@javaCompliance=1.8
 project@com.oracle.graal.bytecode@workingSets=Graal,Java
 
 # graal.java
@@ -477,7 +477,7 @@
 project@com.oracle.graal.java@sourceDirs=src
 project@com.oracle.graal.java@dependencies=com.oracle.graal.phases,com.oracle.graal.bytecode
 project@com.oracle.graal.java@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.java@javaCompliance=1.7
+project@com.oracle.graal.java@javaCompliance=1.8
 project@com.oracle.graal.java@workingSets=Graal,Java
 
 # graal.baseline
@@ -485,7 +485,7 @@
 project@com.oracle.graal.baseline@sourceDirs=src
 project@com.oracle.graal.baseline@dependencies=com.oracle.graal.java,com.oracle.graal.lir,com.oracle.graal.compiler
 project@com.oracle.graal.baseline@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.baseline@javaCompliance=1.7
+project@com.oracle.graal.baseline@javaCompliance=1.8
 project@com.oracle.graal.baseline@workingSets=Graal,Java
 
 # graal.java.decompiler
@@ -493,7 +493,7 @@
 project@com.oracle.graal.java.decompiler@sourceDirs=src
 project@com.oracle.graal.java.decompiler@dependencies=com.oracle.graal.java
 project@com.oracle.graal.java.decompiler@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.java.decompiler@javaCompliance=1.7
+project@com.oracle.graal.java.decompiler@javaCompliance=1.8
 project@com.oracle.graal.java.decompiler@workingSets=Graal
 
 # graal.java.decompiler.test
@@ -501,7 +501,7 @@
 project@com.oracle.graal.java.decompiler.test@sourceDirs=src
 project@com.oracle.graal.java.decompiler.test@dependencies=JUNIT,com.oracle.graal.printer,com.oracle.graal.runtime
 project@com.oracle.graal.java.decompiler.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.java.decompiler.test@javaCompliance=1.7
+project@com.oracle.graal.java.decompiler.test@javaCompliance=1.8
 project@com.oracle.graal.java.decompiler.test@workingSets=Graal,Test
 
 # graal.printer
@@ -509,7 +509,7 @@
 project@com.oracle.graal.printer@sourceDirs=src
 project@com.oracle.graal.printer@dependencies=com.oracle.graal.java.decompiler,com.oracle.graal.compiler
 project@com.oracle.graal.printer@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.printer@javaCompliance=1.7
+project@com.oracle.graal.printer@javaCompliance=1.8
 project@com.oracle.graal.printer@workingSets=Graal,Graph
 
 # graal.test
@@ -517,7 +517,7 @@
 project@com.oracle.graal.test@sourceDirs=src
 project@com.oracle.graal.test@dependencies=JUNIT
 project@com.oracle.graal.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.test@javaCompliance=1.7
+project@com.oracle.graal.test@javaCompliance=1.8
 project@com.oracle.graal.test@workingSets=Graal,Test
 
 # graal.compiler.test
@@ -525,7 +525,7 @@
 project@com.oracle.graal.compiler.test@sourceDirs=src
 project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer,com.oracle.graal.runtime,com.oracle.graal.baseline,JAVA_ALLOCATION_INSTRUMENTER
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.test@javaCompliance=1.7
+project@com.oracle.graal.compiler.test@javaCompliance=1.8
 project@com.oracle.graal.compiler.test@workingSets=Graal,Test
 
 # graal.jtt
@@ -533,7 +533,7 @@
 project@com.oracle.graal.jtt@sourceDirs=src
 project@com.oracle.graal.jtt@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.jtt@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.jtt@javaCompliance=1.7
+project@com.oracle.graal.jtt@javaCompliance=1.8
 project@com.oracle.graal.jtt@workingSets=Graal,Test
 
 # graal.asm
@@ -541,7 +541,7 @@
 project@com.oracle.graal.asm@sourceDirs=src
 project@com.oracle.graal.asm@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.asm@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.asm@javaCompliance=1.7
+project@com.oracle.graal.asm@javaCompliance=1.8
 project@com.oracle.graal.asm@workingSets=Graal,Assembler
 
 # graal.asm.test
@@ -549,7 +549,7 @@
 project@com.oracle.graal.asm.test@sourceDirs=src
 project@com.oracle.graal.asm.test@dependencies=com.oracle.graal.test,com.oracle.graal.runtime
 project@com.oracle.graal.asm.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.asm.test@javaCompliance=1.7
+project@com.oracle.graal.asm.test@javaCompliance=1.8
 project@com.oracle.graal.asm.test@workingSets=Graal,Assembler,Test
 
 # graal.asm.amd64
@@ -557,7 +557,7 @@
 project@com.oracle.graal.asm.amd64@sourceDirs=src
 project@com.oracle.graal.asm.amd64@dependencies=com.oracle.graal.asm,com.oracle.graal.amd64
 project@com.oracle.graal.asm.amd64@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.asm.amd64@javaCompliance=1.7
+project@com.oracle.graal.asm.amd64@javaCompliance=1.8
 project@com.oracle.graal.asm.amd64@workingSets=Graal,Assembler,AMD64
 
 # graal.asm.amd64.test
@@ -565,7 +565,7 @@
 project@com.oracle.graal.asm.amd64.test@sourceDirs=src
 project@com.oracle.graal.asm.amd64.test@dependencies=com.oracle.graal.asm.test,com.oracle.graal.asm.amd64
 project@com.oracle.graal.asm.amd64.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.asm.amd64.test@javaCompliance=1.7
+project@com.oracle.graal.asm.amd64.test@javaCompliance=1.8
 project@com.oracle.graal.asm.amd64.test@workingSets=Graal,Assembler,AMD64,Test
 
 # graal.hsail
@@ -573,49 +573,49 @@
 project@com.oracle.graal.hsail@sourceDirs=src
 project@com.oracle.graal.hsail@dependencies=com.oracle.graal.graph
 project@com.oracle.graal.hsail@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.hsail@javaCompliance=1.7
+project@com.oracle.graal.hsail@javaCompliance=1.8
 
 # graal.lir.hsail
 project@com.oracle.graal.lir.hsail@subDir=graal
 project@com.oracle.graal.lir.hsail@sourceDirs=src
 project@com.oracle.graal.lir.hsail@dependencies=com.oracle.graal.lir,com.oracle.graal.asm.hsail
 project@com.oracle.graal.lir.hsail@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.lir.hsail@javaCompliance=1.7
+project@com.oracle.graal.lir.hsail@javaCompliance=1.8
 
 # graal.compiler.hsail
 project@com.oracle.graal.compiler.hsail@subDir=graal
 project@com.oracle.graal.compiler.hsail@sourceDirs=src
 project@com.oracle.graal.compiler.hsail@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.hsail
 project@com.oracle.graal.compiler.hsail@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.hsail@javaCompliance=1.7
+project@com.oracle.graal.compiler.hsail@javaCompliance=1.8
 
 # graal.compiler.hsail.test.infra - HSAIL compiler test infrastructure
 project@com.oracle.graal.compiler.hsail.test.infra@subDir=graal
 project@com.oracle.graal.compiler.hsail.test.infra@sourceDirs=src
 project@com.oracle.graal.compiler.hsail.test.infra@dependencies=com.oracle.graal.hotspot.hsail,JUNIT,OKRA_WITH_SIM
 project@com.oracle.graal.compiler.hsail.test.infra@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.hsail.test.infra@javaCompliance=1.7
+project@com.oracle.graal.compiler.hsail.test.infra@javaCompliance=1.8
 
 # graal.compiler.hsail.test
 project@com.oracle.graal.compiler.hsail.test@subDir=graal
 project@com.oracle.graal.compiler.hsail.test@sourceDirs=src
 project@com.oracle.graal.compiler.hsail.test@dependencies=com.oracle.graal.compiler.hsail.test.infra,com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.hsail.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.compiler.hsail.test@javaCompliance=1.7
+project@com.oracle.graal.compiler.hsail.test@javaCompliance=1.8
 
 # graal.asm.hsail
 project@com.oracle.graal.asm.hsail@subDir=graal
 project@com.oracle.graal.asm.hsail@sourceDirs=src
 project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm
 project@com.oracle.graal.asm.hsail@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.asm.hsail@javaCompliance=1.7
+project@com.oracle.graal.asm.hsail@javaCompliance=1.8
 
 # graal.asm.ptx
 project@com.oracle.graal.asm.ptx@subDir=graal
 project@com.oracle.graal.asm.ptx@sourceDirs=src
 project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.lir
 project@com.oracle.graal.asm.ptx@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.asm.ptx@javaCompliance=1.7
+project@com.oracle.graal.asm.ptx@javaCompliance=1.8
 project@com.oracle.graal.asm.ptx@workingSets=Graal,Assembler,PTX
 
 # graal.asm.sparc
@@ -623,7 +623,7 @@
 project@com.oracle.graal.asm.sparc@sourceDirs=src
 project@com.oracle.graal.asm.sparc@dependencies=com.oracle.graal.hotspot,com.oracle.graal.sparc
 project@com.oracle.graal.asm.sparc@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.asm.sparc@javaCompliance=1.7
+project@com.oracle.graal.asm.sparc@javaCompliance=1.8
 project@com.oracle.graal.asm.sparc@workingSets=Graal,Assembler,SPARC
 
 # truffle.api
@@ -688,7 +688,7 @@
 project@com.oracle.graal.truffle@sourceDirs=src
 project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer
 project@com.oracle.graal.truffle@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.truffle@javaCompliance=1.7
+project@com.oracle.graal.truffle@javaCompliance=1.8
 project@com.oracle.graal.truffle@workingSets=Graal,Truffle
 
 # graal.truffle.test
@@ -696,7 +696,7 @@
 project@com.oracle.graal.truffle.test@sourceDirs=src
 project@com.oracle.graal.truffle.test@dependencies=com.oracle.graal.truffle,com.oracle.graal.compiler.test
 project@com.oracle.graal.truffle.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.truffle.test@javaCompliance=1.7
+project@com.oracle.graal.truffle.test@javaCompliance=1.8
 project@com.oracle.graal.truffle.test@workingSets=Graal,Truffle,Test
 
 # graal.truffle.hotspot
@@ -704,7 +704,7 @@
 project@com.oracle.graal.truffle.hotspot@sourceDirs=src
 project@com.oracle.graal.truffle.hotspot@dependencies=com.oracle.graal.truffle,com.oracle.graal.hotspot
 project@com.oracle.graal.truffle.hotspot@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.truffle.hotspot@javaCompliance=1.7
+project@com.oracle.graal.truffle.hotspot@javaCompliance=1.8
 project@com.oracle.graal.truffle.hotspot@annotationProcessors=com.oracle.graal.service.processor
 project@com.oracle.graal.truffle.hotspot@workingSets=Graal,Truffle
 
@@ -713,6 +713,6 @@
 project@com.oracle.graal.truffle.hotspot.amd64@sourceDirs=src
 project@com.oracle.graal.truffle.hotspot.amd64@dependencies=com.oracle.graal.truffle.hotspot,com.oracle.graal.hotspot.amd64
 project@com.oracle.graal.truffle.hotspot.amd64@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.truffle.hotspot.amd64@javaCompliance=1.7
+project@com.oracle.graal.truffle.hotspot.amd64@javaCompliance=1.8
 project@com.oracle.graal.truffle.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor
 project@com.oracle.graal.truffle.hotspot.amd64@workingSets=Graal,Truffle
--- a/mxtool/mx.py	Wed Mar 26 17:02:45 2014 +0100
+++ b/mxtool/mx.py	Wed Mar 26 20:44:11 2014 +0100
@@ -54,7 +54,7 @@
 _primary_suite_path = None
 _primary_suite = None
 _opts = None
-_java = None
+_java_homes = None
 _warn = False
 
 """
@@ -117,6 +117,13 @@
         self.workingSets = workingSets
         self.dir = d
 
+        # Verify that a JDK exists for this project if its compliance level is
+        # less than the compliance level of the default JDK
+        jdk = java(self.javaCompliance)
+        if jdk is None and self.javaCompliance < java().javaCompliance:
+            abort('Cannot find ' + str(self.javaCompliance) + ' JDK required by ' + name + '. ' +
+                  'Specify it with --extra-java-homes option or EXTRA_JAVA_HOMES environment variable.')
+
         # Create directories for projects that don't yet exist
         if not exists(d):
             os.mkdir(d)
@@ -1036,7 +1043,8 @@
         self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[])
         self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[])
         self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
-        self.add_argument('--java-home', help='bootstrap JDK installation directory (must be JDK 6 or later)', metavar='<path>')
+        self.add_argument('--java-home', help='primary JDK directory (must be JDK 7 or later)', metavar='<path>')
+        self.add_argument('--extra-java-homes', help='secondary JDK directories separated by "' + os.pathsep + '"', metavar='<path>')
         self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
         self.add_argument('--kill-with-sigquit', action='store_true', dest='killwithsigquit', help='send sigquit first before killing child processes')
         if get_os() != 'windows':
@@ -1061,6 +1069,8 @@
 
         if opts.java_home is None:
             opts.java_home = os.environ.get('JAVA_HOME')
+        if opts.extra_java_homes is None:
+            opts.extra_java_homes = os.environ.get('EXTRA_JAVA_HOMES')
 
         if opts.java_home is None or opts.java_home == '':
             opts.java_home = _handle_missing_java_home()
@@ -1089,12 +1099,21 @@
         msg += ' {0:<20} {1}\n'.format(cmd, doc.split('\n', 1)[0])
     return msg + '\n'
 
-def java():
+def java(requiredCompliance=None):
     """
     Get a JavaConfig object containing Java commands launch details.
+    If requiredCompliance is None, the compliance level specified by --java-home/JAVA_HOME
+    is returned. Otherwise, the JavaConfig exactly matching requiredCompliance is returned
+    or None if there is no exact match.
     """
-    assert _java is not None
-    return _java
+    assert _java_homes
+    if not requiredCompliance:
+        return _java_homes[0]
+    for java in _java_homes:
+        if java.javaCompliance == requiredCompliance:
+            return java
+    return None
+
 
 def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, addDefaultArgs=True):
     return run(java().format_cmd(args, addDefaultArgs), nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd)
@@ -1350,9 +1369,9 @@
 A JavaConfig object encapsulates info on how Java commands are run.
 """
 class JavaConfig:
-    def __init__(self, opts):
-        self.jdk = opts.java_home
-        self.debug_port = opts.java_dbg_port
+    def __init__(self, java_home, java_dbg_port):
+        self.jdk = java_home
+        self.debug_port = java_dbg_port
         self.jar = exe_suffix(join(self.jdk, 'bin', 'jar'))
         self.java = exe_suffix(join(self.jdk, 'bin', 'java'))
         self.javac = exe_suffix(join(self.jdk, 'bin', 'javac'))
@@ -1361,7 +1380,7 @@
         self._bootclasspath = None
 
         if not exists(self.java):
-            abort('Java launcher derived from JAVA_HOME does not exist: ' + self.java)
+            abort('Java launcher does not exist: ' + self.java)
 
         def delAtAndSplit(s):
             return shlex.split(s.lstrip('@'))
@@ -1389,6 +1408,14 @@
         if self.debug_port is not None:
             self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(self.debug_port)]
 
+    def __hash__(self):
+        return hash(self.jdk)
+
+    def __cmp__(self, other):
+        if isinstance(other, JavaConfig):
+            return cmp(self.javaCompliance, other.javaCompliance)
+        raise TypeError()
+
     def format_cmd(self, args, addDefaultArgs):
         if addDefaultArgs:
             return [self.java] + self.processArgs(args)
@@ -1624,14 +1651,12 @@
     if not suppliedParser:
         parser = ArgumentParser(prog='mx build')
 
-    javaCompliance = java().javaCompliance
-
     defaultEcjPath = get_env('JDT', join(_primary_suite.mxDir, 'ecj.jar'))
 
     parser = parser if parser is not None else ArgumentParser(prog='mx build')
     parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)')
     parser.add_argument('-c', action='store_true', dest='clean', help='removes existing build output')
-    parser.add_argument('--source', dest='compliance', help='Java compliance level for projects without an explicit one', default=str(javaCompliance))
+    parser.add_argument('--source', dest='compliance', help='Java compliance level for projects without an explicit one')
     parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs')
     parser.add_argument('--projects', action='store', help='comma separated projects to build (omit to build all projects)')
     parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)')
@@ -1710,9 +1735,12 @@
                 continue
 
         # skip building this Java project if its Java compliance level is "higher" than the configured JDK
-        if javaCompliance < p.javaCompliance:
-            log('Excluding {0} from build (Java compliance level {1} required)'.format(p.name, p.javaCompliance))
+        requiredCompliance = p.javaCompliance if p.javaCompliance else JavaCompliance(args.compliance) if args.compliance else None
+        jdk = java(requiredCompliance)
+        if not jdk:
+            log('Excluding {0} from build (Java compliance level {1} required)'.format(p.name, requiredCompliance))
             continue
+        compliance = str(jdk.javaCompliance)
 
         outputDir = prepareOutputDirs(p, args.clean)
 
@@ -1817,14 +1845,11 @@
 
         toBeDeleted = [argfileName]
         try:
-            compliance = str(p.javaCompliance) if p.javaCompliance is not None else args.compliance
             if jdtJar is None:
                 log('Compiling Java sources for {0} with javac...'.format(p.name))
-
-
-                javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir]
-                if java().debug_port is not None:
-                    javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
+                javacCmd = [jdk.javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir]
+                if jdk.debug_port is not None:
+                    javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)]
                 javacCmd += processorArgs
                 javacCmd += ['@' + argfile.name]
 
@@ -1834,9 +1859,9 @@
             else:
                 log('Compiling Java sources for {0} with JDT...'.format(p.name))
 
-                jdtArgs = [java().java, '-Xmx1g']
-                if java().debug_port is not None:
-                    jdtArgs += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
+                jdtArgs = [jdk.java, '-Xmx1g']
+                if jdk.debug_port is not None:
+                    jdtArgs += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)]
 
                 jdtArgs += ['-jar', jdtJar,
                          '-' + compliance,
@@ -1912,13 +1937,14 @@
         projects = [project(name) for name in args.projects.split(',')]
 
     class Batch:
-        def __init__(self, settingsFile):
+        def __init__(self, settingsFile, javaCompliance):
             self.path = settingsFile
+            self.javaCompliance = javaCompliance
             self.javafiles = list()
 
         def settings(self):
             with open(self.path) as fp:
-                return fp.read()
+                return fp.read() + java(self.javaCompliance).java
 
     class FileInfo:
         def __init__(self, path):
@@ -1943,7 +1969,7 @@
             continue
         sourceDirs = p.source_dirs()
 
-        batch = Batch(join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs'))
+        batch = Batch(join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs'), p.javaCompliance)
 
         if not exists(batch.path):
             if _opts.verbose:
@@ -1962,8 +1988,15 @@
         if res is not batch:
             res.javafiles = res.javafiles + batch.javafiles
 
+    print "we have: " + str(len(batches)) + " batches"
     for batch in batches.itervalues():
-        run([args.eclipse_exe, '-nosplash', '-application', 'org.eclipse.jdt.core.JavaCodeFormatter', '-config', batch.path] + [f.path for f in batch.javafiles])
+        run([args.eclipse_exe,
+            '-nosplash',
+            '-application',
+            'org.eclipse.jdt.core.JavaCodeFormatter',
+            '-vm', java(batch.javaCompliance).java,
+            '-config', batch.path]
+            + [f.path for f in batch.javafiles])
         for fi in batch.javafiles:
             if fi.update():
                 modified.append(fi)
@@ -2115,7 +2148,8 @@
                     else:
                         p = dep
                         # skip a  Java project if its Java compliance level is "higher" than the configured JDK
-                        if java().javaCompliance < p.javaCompliance:
+                        jdk = java(p.javaCompliance)
+                        if not jdk:
                             log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, d.path))
                             continue
 
@@ -2296,7 +2330,8 @@
             abort('ERROR: .checkstyle for Project {0} is missing'.format(p.name))
 
         # skip checking this Java project if its Java compliance level is "higher" than the configured JDK
-        if java().javaCompliance < p.javaCompliance:
+        jdk = java(p.javaCompliance)
+        if not jdk:
             log('Excluding {0} from checking (Java compliance level {1} required)'.format(p.name, p.javaCompliance))
             continue
 
@@ -2720,6 +2755,10 @@
         if p.native:
             continue
 
+        if not java(p.javaCompliance):
+            log('Excluding {0} (JDK with compliance level {1} not available)'.format(p.name, p.javaCompliance))
+            continue
+
         if not exists(p.dir):
             os.makedirs(p.dir)
 
@@ -2867,20 +2906,41 @@
         if not exists(settingsDir):
             os.mkdir(settingsDir)
 
+        # collect the defaults from mxtool
+        defaultEclipseSettingsDir = join(dirname(__file__), 'eclipse-settings')
+        esdict = {}
+        if exists(defaultEclipseSettingsDir):
+            for name in os.listdir(defaultEclipseSettingsDir):
+                if isfile(join(defaultEclipseSettingsDir, name)):
+                    esdict[name] = os.path.abspath(join(defaultEclipseSettingsDir, name))
+
+        # check for suite overrides
         eclipseSettingsDir = join(p.suite.mxDir, 'eclipse-settings')
         if exists(eclipseSettingsDir):
             for name in os.listdir(eclipseSettingsDir):
-                if name == "org.eclipse.jdt.apt.core.prefs" and not len(p.annotation_processors()) > 0:
-                    continue
-                path = join(eclipseSettingsDir, name)
-                if isfile(path):
-                    with open(join(eclipseSettingsDir, name)) as f:
-                        content = f.read()
-                    content = content.replace('${javaCompliance}', str(p.javaCompliance))
-                    if len(p.annotation_processors()) > 0:
-                        content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled')
-                    update_file(join(settingsDir, name), content)
-                    files.append(join(settingsDir, name))
+                if isfile(join(eclipseSettingsDir, name)):
+                    esdict[name] = os.path.abspath(join(eclipseSettingsDir, name))
+
+        # check for project overrides
+        projectSettingsDir = join(p.dir, 'eclipse-settings')
+        if exists(projectSettingsDir):
+            for name in os.listdir(projectSettingsDir):
+                if isfile(join(projectSettingsDir, name)):
+                    esdict[name] = os.path.abspath(join(projectSettingsDir, name))
+
+        # copy a possibly modified file to the project's .settings directory
+        for name, path in esdict.iteritems():
+            # ignore this file altogether if this project has no annotation processors
+            if name == "org.eclipse.jdt.apt.core.prefs" and not len(p.annotation_processors()) > 0:
+                continue
+
+            with open(path) as f:
+                content = f.read()
+            content = content.replace('${javaCompliance}', str(p.javaCompliance))
+            if len(p.annotation_processors()) > 0:
+                content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled')
+            update_file(join(settingsDir, name), content)
+            files.append(join(settingsDir, name))
 
         if len(p.annotation_processors()) > 0:
             out = XMLDoc()
@@ -2943,7 +3003,7 @@
     launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'})
     launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': consoleOn})
     launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'})
-    launchOut.element('mapEntry', {'key' : 'JAVA_HOME', 'value' : java().jdk})
+    launchOut.element('mapEntry', {'key' : 'JAVA_HOME', 'value' : java(p.javaCompliance).jdk})
     launchOut.close('mapAttribute')
 
     if refresh:
@@ -3190,6 +3250,7 @@
     updated = False
     files = []
     libFiles = []
+    jdks = set()
     for p in suite.projects:
         if p.native:
             continue
@@ -3200,13 +3261,21 @@
         if not exists(join(p.dir, 'nbproject')):
             os.makedirs(join(p.dir, 'nbproject'))
 
+        jdk = java(p.javaCompliance)
+
+        if not jdk:
+            log('Excluding {0} (JDK with compliance level {1} not available)'.format(p.name, p.javaCompliance))
+            continue
+
+        jdks.add(jdk)
+
         out = XMLDoc()
         out.open('project', {'name' : p.name, 'default' : 'default', 'basedir' : '.'})
         out.element('description', data='Builds, tests, and runs the project ' + p.name + '.')
         out.element('import', {'file' : 'nbproject/build-impl.xml'})
         out.open('target', {'name' : '-post-compile'})
         out.open('exec', {'executable' : sys.executable})
-        out.element('env', {'key' : 'JAVA_HOME', 'value' : java().jdk})
+        out.element('env', {'key' : 'JAVA_HOME', 'value' : jdk.jdk})
         out.element('arg', {'value' : os.path.abspath(__file__)})
         out.element('arg', {'value' : 'archive'})
         out.element('arg', {'value' : '@GRAAL'})
@@ -3261,7 +3330,7 @@
         files.append(join(p.dir, 'nbproject', 'project.xml'))
 
         out = StringIO.StringIO()
-        jdkPlatform = 'JDK_' + str(java().version)
+        jdkPlatform = 'JDK_' + str(jdk.version)
 
         annotationProcessorEnabled = "false"
         annotationProcessorReferences = ""
@@ -3324,7 +3393,7 @@
 manifest.file=manifest.mf
 meta.inf.dir=${src.dir}/META-INF
 mkdist.disabled=false
-platforms.""" + jdkPlatform + """.home=""" + java().jdk + """
+platforms.""" + jdkPlatform + """.home=""" + jdk.jdk + """
 platform.active=""" + jdkPlatform + """
 run.classpath=\\
     ${javac.classpath}:\\
@@ -3404,7 +3473,9 @@
 
     if updated:
         log('If using NetBeans:')
-        log('  1. Ensure that a platform named "JDK_' + str(java().version) + '" is defined (Tools -> Java Platforms)')
+        log('  1. Ensure that the following platform(s) are defined (Tools -> Java Platforms):')
+        for jdk in jdks:
+            log('        JDK_' + str(jdk.version))
         log('  2. Open/create a Project Group for the directory containing the projects (File -> Project Group -> New Group... -> Folder of Projects)')
 
     _zip_files(files, suite.dir, configZip.path)
@@ -3575,7 +3646,7 @@
                 windowTitle = ['-windowtitle', p.name + ' javadoc']
             try:
                 log('Generating {2} for {0} in {1}'.format(p.name, out, docDir))
-                run([java().javadoc, memory,
+                run([java(p.javaCompliance).javadoc, memory,
                      '-XDignore.symbol.file',
                      '-classpath', cp,
                      '-quiet',
@@ -3604,7 +3675,7 @@
             sp += p.source_dirs()
             names.append(p.name)
 
-        links = ['-link', 'http://docs.oracle.com/javase/' + str(_java.javaCompliance.value) + '/docs/api/']
+        links = ['-link', 'http://docs.oracle.com/javase/' + str(java().javaCompliance.value) + '/docs/api/']
         out = join(_primary_suite.dir, docDir)
         if args.base is not None:
             out = join(args.base, docDir)
@@ -4084,9 +4155,16 @@
 
     opts, commandAndArgs = _argParser._parse_cmd_line()
 
-    global _opts, _java
+    global _opts, _java_homes
     _opts = opts
-    _java = JavaConfig(opts)
+    defaultJdk = JavaConfig(opts.java_home, opts.java_dbg_port)
+    _java_homes = [defaultJdk]
+    if opts.extra_java_homes:
+        for java_home in opts.extra_java_homes.split(os.pathsep):
+            extraJdk = JavaConfig(java_home, opts.java_dbg_port)
+            if extraJdk > defaultJdk:
+                abort('Secondary JDK ' + extraJdk.jdk + ' has higher compliance level than default JDK ' + defaultJdk.jdk)
+            _java_homes.append(extraJdk)
 
     for s in suites():
         s._post_init(opts)
--- a/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Wed Mar 26 20:44:11 2014 +0100
@@ -45,7 +45,7 @@
 define_pd_global(intx, NewSizeThreadIncrease,        4*K  );
 define_pd_global(uintx,MetaspaceSize,                12*M );
 define_pd_global(bool, NeverActAsServerClassMachine, false);
-define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
+define_pd_global(uint64_t,MaxRAM,                    128ULL*G);
 define_pd_global(bool, CICompileOSR,                 true );
 define_pd_global(bool, ProfileTraps,                 true );
 define_pd_global(bool, UseOnStackReplacement,        true );
--- a/src/cpu/x86/vm/graalGlobals_x86.hpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/cpu/x86/vm/graalGlobals_x86.hpp	Wed Mar 26 20:44:11 2014 +0100
@@ -45,7 +45,7 @@
 define_pd_global(intx, NewSizeThreadIncrease,        4*K  );
 define_pd_global(uintx,MetaspaceSize,                12*M );
 define_pd_global(bool, NeverActAsServerClassMachine, false);
-define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
+define_pd_global(uint64_t,MaxRAM,                    128ULL*G);
 define_pd_global(bool, CICompileOSR,                 true );
 define_pd_global(bool, ProfileTraps,                 true );
 define_pd_global(bool, UseOnStackReplacement,        true );
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Mar 26 20:44:11 2014 +0100
@@ -184,6 +184,7 @@
   do_klass(Long_klass,                                  java_lang_Long,                            Pre                 ) \
                                                                                                                          \
   /* Support for Graal */                                                                                                \
+  do_klass(CompilerThread_klass,                  com_oracle_graal_compiler_CompilerThread,                     Opt) \
   do_klass(BitSet_klass,                          java_util_BitSet,                                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompiledCode_klass,             com_oracle_graal_hotspot_HotSpotCompiledCode,                 Opt) \
@@ -203,7 +204,6 @@
   do_klass(HotSpotResolvedJavaMethod_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,      Opt) \
   do_klass(HotSpotResolvedObjectType_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,      Opt) \
   do_klass(HotSpotMonitorValue_klass,             com_oracle_graal_hotspot_meta_HotSpotMonitorValue,            Opt) \
-  do_klass(CompilerThread_klass,                  com_oracle_graal_hotspot_CompilerThread,                      Opt) \
   /* graal.api.code */                                                                                               \
   do_klass(Assumptions_klass,                     com_oracle_graal_api_code_Assumptions,                        Opt) \
   do_klass(Assumptions_ConcreteMethod_klass,      com_oracle_graal_api_code_Assumptions_ConcreteMethod,         Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Mar 26 20:44:11 2014 +0100
@@ -288,10 +288,11 @@
   NOT_LP64(  do_alias(intptr_signature,               int_signature)  )                           \
   LP64_ONLY( do_alias(intptr_signature,               long_signature) )                           \
   template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \
-                                                                                                                                       \
-  /* Support for Graal */                                                                                                              \
-  template(java_util_BitSet,	                                       "java/util/BitSet")                                               \
-  /* graal.hotspot */                                                                                                                  \
+                                                                                                                                      \
+  /* Support for Graal */                                                                                                             \
+  template(com_oracle_graal_compiler_CompilerThread,                 "com/oracle/graal/compiler/CompilerThread")                      \
+  template(java_util_BitSet,	                                       "java/util/BitSet")                                              \
+  /* graal.hotspot */                                                                                                                 \
   template(com_oracle_graal_hotspot_HotSpotGraalRuntime,             "com/oracle/graal/hotspot/HotSpotGraalRuntime")                  \
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
   template(com_oracle_graal_hotspot_HotSpotOptions,                  "com/oracle/graal/hotspot/HotSpotOptions")                       \
@@ -314,7 +315,6 @@
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,  "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod")       \
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,  "com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType")       \
   template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")             \
-  template(com_oracle_graal_hotspot_CompilerThread,                  "com/oracle/graal/hotspot/CompilerThread")                       \
   /* graal.api.meta */                                                                                                                \
   template(com_oracle_graal_api_meta_Constant,                       "com/oracle/graal/api/meta/Constant")                            \
   template(com_oracle_graal_api_meta_ConstantPool,                   "com/oracle/graal/api/meta/ConstantPool")                        \
--- a/src/share/vm/code/nmethod.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/code/nmethod.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -105,7 +105,6 @@
 //   PrintC1Statistics, PrintOptoStatistics, LogVMOutput, and LogCompilation.
 // (In the latter two cases, they like other stats are printed to the log only.)
 
-#ifndef PRODUCT
 // These variables are put into one block to reduce relocations
 // and make it simpler to print from the debugger.
 struct java_nmethod_stats_struct {
@@ -233,7 +232,6 @@
     unknown_java_nmethod_stats.note_nmethod(nm);
   }
 }
-#endif
 
 //---------------------------------------------------------------------------------
 
@@ -536,7 +534,7 @@
                                             code_buffer, frame_size,
                                             basic_lock_owner_sp_offset,
                                             basic_lock_sp_offset, oop_maps);
-    NOT_PRODUCT(if (nm != NULL)  note_java_nmethod(nm));
+    if (nm != NULL)  note_java_nmethod(nm);
     if (PrintAssembly && nm != NULL) {
       Disassembler::decode(nm);
     }
@@ -572,7 +570,7 @@
     nm = new (nmethod_size) nmethod(method(), nmethod_size,
                                     &offsets, code_buffer, frame_size);
 
-    NOT_PRODUCT(if (nm != NULL)  note_java_nmethod(nm));
+    if (nm != NULL)  note_java_nmethod(nm);
     if (PrintAssembly && nm != NULL) {
       Disassembler::decode(nm);
     }
@@ -652,7 +650,7 @@
         // record this nmethod as dependent on this klass
         InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
       }
-      NOT_PRODUCT(if (nm != NULL)  note_java_nmethod(nm));
+      if (nm != NULL)  note_java_nmethod(nm);
       if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
         Disassembler::decode(nm);
       }
@@ -3058,6 +3056,7 @@
 void nmethod::print_nul_chk_table() {
   ImplicitExceptionTable(this).print(code_begin());
 }
+#endif // PRODUCT
 
 void nmethod::print_statistics() {
   ttyLocker ttyl;
@@ -3078,4 +3077,3 @@
   Dependencies::print_statistics();
   if (xtty != NULL)  xtty->tail("statistics");
 }
-#endif // PRODUCT
--- a/src/share/vm/code/nmethod.hpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/code/nmethod.hpp	Wed Mar 26 20:44:11 2014 +0100
@@ -694,7 +694,7 @@
 
   // Prints a comment for one native instruction (reloc info, pc desc)
   void print_code_comment_on(outputStream* st, int column, address begin, address end);
-  static void print_statistics()                  PRODUCT_RETURN;
+  static void print_statistics();
 
   // Compiler task identification.  Note that all OSR methods
   // are numbered in an independent sequence if CICountOSR is true,
--- a/src/share/vm/compiler/disassembler.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/compiler/disassembler.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -159,397 +159,397 @@
   nmethod*      _nm;
   CodeBlob*     _code;
   CodeStrings   _strings;
-  outputStream* _output;
-  address       _start, _end;
-
-  char          _option_buf[512];
-  char          _print_raw;
-  bool          _print_pc;
-  bool          _print_bytes;
-  address       _cur_insn;
-  int           _total_ticks;
-  int           _bytes_per_line; // arch-specific formatting option
-
-  static bool match(const char* event, const char* tag) {
-    size_t taglen = strlen(tag);
-    if (strncmp(event, tag, taglen) != 0)
-      return false;
-    char delim = event[taglen];
-    return delim == '\0' || delim == ' ' || delim == '/' || delim == '=';
-  }
-
-  void collect_options(const char* p) {
-    if (p == NULL || p[0] == '\0')  return;
-    size_t opt_so_far = strlen(_option_buf);
-    if (opt_so_far + 1 + strlen(p) + 1 > sizeof(_option_buf))  return;
-    char* fillp = &_option_buf[opt_so_far];
-    if (opt_so_far > 0) *fillp++ = ',';
-    strcat(fillp, p);
-    // replace white space by commas:
-    char* q = fillp;
-    while ((q = strpbrk(q, " \t\n")) != NULL)
-      *q++ = ',';
-    // Note that multiple PrintAssemblyOptions flags accumulate with \n,
-    // which we want to be changed to a comma...
-  }
-
-  void print_insn_labels();
-  void print_insn_bytes(address pc0, address pc);
-  void print_address(address value);
-
- public:
+  outputStream* _output;
+  address       _start, _end;
+
+  char          _option_buf[512];
+  char          _print_raw;
+  bool          _print_pc;
+  bool          _print_bytes;
+  address       _cur_insn;
+  int           _total_ticks;
+  int           _bytes_per_line; // arch-specific formatting option
+
+  static bool match(const char* event, const char* tag) {
+    size_t taglen = strlen(tag);
+    if (strncmp(event, tag, taglen) != 0)
+      return false;
+    char delim = event[taglen];
+    return delim == '\0' || delim == ' ' || delim == '/' || delim == '=';
+  }
+
+  void collect_options(const char* p) {
+    if (p == NULL || p[0] == '\0')  return;
+    size_t opt_so_far = strlen(_option_buf);
+    if (opt_so_far + 1 + strlen(p) + 1 > sizeof(_option_buf))  return;
+    char* fillp = &_option_buf[opt_so_far];
+    if (opt_so_far > 0) *fillp++ = ',';
+    strcat(fillp, p);
+    // replace white space by commas:
+    char* q = fillp;
+    while ((q = strpbrk(q, " \t\n")) != NULL)
+      *q++ = ',';
+    // Note that multiple PrintAssemblyOptions flags accumulate with \n,
+    // which we want to be changed to a comma...
+  }
+
+  void print_insn_labels();
+  void print_insn_bytes(address pc0, address pc);
+  void print_address(address value);
+
+ public:
   decode_env(CodeBlob* code, outputStream* output, CodeStrings c = CodeStrings());
-
-  address decode_instructions(address start, address end);
-
-  void start_insn(address pc) {
-    _cur_insn = pc;
-    output()->bol();
-    print_insn_labels();
-  }
-
-  void end_insn(address pc) {
-    address pc0 = cur_insn();
-    outputStream* st = output();
-    if (_print_bytes && pc > pc0)
-      print_insn_bytes(pc0, pc);
-    if (_nm != NULL) {
-      _nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc);
-      // this calls reloc_string_for which calls oop::print_value_on
-    }
-
-    // Output pc bucket ticks if we have any
-    if (total_ticks() != 0) {
-      address bucket_pc = FlatProfiler::bucket_start_for(pc);
-      if (bucket_pc != NULL && bucket_pc > pc0 && bucket_pc <= pc) {
-        int bucket_count = FlatProfiler::bucket_count_for(pc0);
-        if (bucket_count != 0) {
-          st->bol();
-          st->print_cr("%3.1f%% [%d]", bucket_count*100.0/total_ticks(), bucket_count);
-        }
-      }
-    }
-    // follow each complete insn by a nice newline
-    st->cr();
-  }
-
-  address handle_event(const char* event, address arg);
-
-  outputStream* output() { return _output; }
-  address cur_insn() { return _cur_insn; }
-  int total_ticks() { return _total_ticks; }
-  void set_total_ticks(int n) { _total_ticks = n; }
-  const char* options() { return _option_buf; }
-};
-
+
+  address decode_instructions(address start, address end);
+
+  void start_insn(address pc) {
+    _cur_insn = pc;
+    output()->bol();
+    print_insn_labels();
+  }
+
+  void end_insn(address pc) {
+    address pc0 = cur_insn();
+    outputStream* st = output();
+    if (_print_bytes && pc > pc0)
+      print_insn_bytes(pc0, pc);
+    if (_nm != NULL) {
+      _nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc);
+      // this calls reloc_string_for which calls oop::print_value_on
+    }
+
+    // Output pc bucket ticks if we have any
+    if (total_ticks() != 0) {
+      address bucket_pc = FlatProfiler::bucket_start_for(pc);
+      if (bucket_pc != NULL && bucket_pc > pc0 && bucket_pc <= pc) {
+        int bucket_count = FlatProfiler::bucket_count_for(pc0);
+        if (bucket_count != 0) {
+          st->bol();
+          st->print_cr("%3.1f%% [%d]", bucket_count*100.0/total_ticks(), bucket_count);
+        }
+      }
+    }
+    // follow each complete insn by a nice newline
+    st->cr();
+  }
+
+  address handle_event(const char* event, address arg);
+
+  outputStream* output() { return _output; }
+  address cur_insn() { return _cur_insn; }
+  int total_ticks() { return _total_ticks; }
+  void set_total_ticks(int n) { _total_ticks = n; }
+  const char* options() { return _option_buf; }
+};
+
 decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) {
-  memset(this, 0, sizeof(*this));
-  _output = output ? output : tty;
-  _code = code;
-  if (code != NULL && code->is_nmethod())
-    _nm = (nmethod*) code;
+  memset(this, 0, sizeof(*this));
+  _output = output ? output : tty;
+  _code = code;
+  if (code != NULL && code->is_nmethod())
+    _nm = (nmethod*) code;
   _strings.assign(c);
-
-  // by default, output pc but not bytes:
-  _print_pc       = true;
-  _print_bytes    = false;
-  _bytes_per_line = Disassembler::pd_instruction_alignment();
-
-  // parse the global option string:
-  collect_options(Disassembler::pd_cpu_opts());
-  collect_options(PrintAssemblyOptions);
-
-  if (strstr(options(), "hsdis-")) {
-    if (strstr(options(), "hsdis-print-raw"))
-      _print_raw = (strstr(options(), "xml") ? 2 : 1);
-    if (strstr(options(), "hsdis-print-pc"))
-      _print_pc = !_print_pc;
-    if (strstr(options(), "hsdis-print-bytes"))
-      _print_bytes = !_print_bytes;
-  }
-  if (strstr(options(), "help")) {
-    tty->print_cr("PrintAssemblyOptions help:");
-    tty->print_cr("  hsdis-print-raw       test plugin by requesting raw output");
-    tty->print_cr("  hsdis-print-raw-xml   test plugin by requesting raw xml");
-    tty->print_cr("  hsdis-print-pc        turn off PC printing (on by default)");
-    tty->print_cr("  hsdis-print-bytes     turn on instruction byte output");
-    tty->print_cr("combined options: %s", options());
-  }
-}
-
-address decode_env::handle_event(const char* event, address arg) {
-  if (match(event, "insn")) {
-    start_insn(arg);
-  } else if (match(event, "/insn")) {
-    end_insn(arg);
-  } else if (match(event, "addr")) {
-    if (arg != NULL) {
-      print_address(arg);
-      return arg;
-    }
-  } else if (match(event, "mach")) {
-    static char buffer[32] = { 0, };
-    if (strcmp(buffer, (const char*)arg) != 0 ||
-        strlen((const char*)arg) > sizeof(buffer) - 1) {
-      // Only print this when the mach changes
-      strncpy(buffer, (const char*)arg, sizeof(buffer) - 1);
-      output()->print_cr("[Disassembling for mach='%s']", arg);
-    }
-  } else if (match(event, "format bytes-per-line")) {
-    _bytes_per_line = (int) (intptr_t) arg;
-  } else {
-    // ignore unrecognized markup
-  }
-  return NULL;
-}
-
-// called by the disassembler to print out jump targets and data addresses
-void decode_env::print_address(address adr) {
-  outputStream* st = _output;
-
-  if (adr == NULL) {
-    st->print("NULL");
-    return;
-  }
-
-  int small_num = (int)(intptr_t)adr;
-  if ((intptr_t)adr == (intptr_t)small_num
-      && -1 <= small_num && small_num <= 9) {
-    st->print("%d", small_num);
-    return;
-  }
-
-  if (Universe::is_fully_initialized()) {
-    if (StubRoutines::contains(adr)) {
-      StubCodeDesc* desc = StubCodeDesc::desc_for(adr);
-      if (desc == NULL)
-        desc = StubCodeDesc::desc_for(adr + frame::pc_return_offset);
-      if (desc != NULL) {
-        st->print("Stub::%s", desc->name());
-        if (desc->begin() != adr)
-          st->print("%+d 0x%p",adr - desc->begin(), adr);
-        else if (WizardMode) st->print(" " PTR_FORMAT, adr);
-        return;
-      }
-      st->print("Stub::<unknown> " PTR_FORMAT, adr);
-      return;
-    }
-
-    BarrierSet* bs = Universe::heap()->barrier_set();
-    if (bs->kind() == BarrierSet::CardTableModRef &&
-        adr == (address)((CardTableModRefBS*)(bs))->byte_map_base) {
-      st->print("word_map_base");
-      if (WizardMode) st->print(" " INTPTR_FORMAT, (intptr_t)adr);
-      return;
-    }
-
-    oop obj;
-    if (_nm != NULL
-        && (obj = _nm->embeddedOop_at(cur_insn())) != NULL
-        && (address) obj == adr
-        && Universe::heap()->is_in(obj)
-        && Universe::heap()->is_in(obj->klass())) {
-      julong c = st->count();
-      obj->print_value_on(st);
-      if (st->count() == c) {
-        // No output.  (Can happen in product builds.)
-        st->print("(a %s)", obj->klass()->external_name());
-      }
-      return;
-    }
-  }
-
-  // Fall through to a simple (hexadecimal) numeral.
-  st->print(PTR_FORMAT, adr);
-}
-
-void decode_env::print_insn_labels() {
-  address p = cur_insn();
-  outputStream* st = output();
-  CodeBlob* cb = _code;
-  if (cb != NULL) {
-    cb->print_block_comment(st, p);
-  }
+
+  // by default, output pc but not bytes:
+  _print_pc       = true;
+  _print_bytes    = false;
+  _bytes_per_line = Disassembler::pd_instruction_alignment();
+
+  // parse the global option string:
+  collect_options(Disassembler::pd_cpu_opts());
+  collect_options(PrintAssemblyOptions);
+
+  if (strstr(options(), "hsdis-")) {
+    if (strstr(options(), "hsdis-print-raw"))
+      _print_raw = (strstr(options(), "xml") ? 2 : 1);
+    if (strstr(options(), "hsdis-print-pc"))
+      _print_pc = !_print_pc;
+    if (strstr(options(), "hsdis-print-bytes"))
+      _print_bytes = !_print_bytes;
+  }
+  if (strstr(options(), "help")) {
+    tty->print_cr("PrintAssemblyOptions help:");
+    tty->print_cr("  hsdis-print-raw       test plugin by requesting raw output");
+    tty->print_cr("  hsdis-print-raw-xml   test plugin by requesting raw xml");
+    tty->print_cr("  hsdis-print-pc        turn off PC printing (on by default)");
+    tty->print_cr("  hsdis-print-bytes     turn on instruction byte output");
+    tty->print_cr("combined options: %s", options());
+  }
+}
+
+address decode_env::handle_event(const char* event, address arg) {
+  if (match(event, "insn")) {
+    start_insn(arg);
+  } else if (match(event, "/insn")) {
+    end_insn(arg);
+  } else if (match(event, "addr")) {
+    if (arg != NULL) {
+      print_address(arg);
+      return arg;
+    }
+  } else if (match(event, "mach")) {
+    static char buffer[32] = { 0, };
+    if (strcmp(buffer, (const char*)arg) != 0 ||
+        strlen((const char*)arg) > sizeof(buffer) - 1) {
+      // Only print this when the mach changes
+      strncpy(buffer, (const char*)arg, sizeof(buffer) - 1);
+      output()->print_cr("[Disassembling for mach='%s']", arg);
+    }
+  } else if (match(event, "format bytes-per-line")) {
+    _bytes_per_line = (int) (intptr_t) arg;
+  } else {
+    // ignore unrecognized markup
+  }
+  return NULL;
+}
+
+// called by the disassembler to print out jump targets and data addresses
+void decode_env::print_address(address adr) {
+  outputStream* st = _output;
+
+  if (adr == NULL) {
+    st->print("NULL");
+    return;
+  }
+
+  int small_num = (int)(intptr_t)adr;
+  if ((intptr_t)adr == (intptr_t)small_num
+      && -1 <= small_num && small_num <= 9) {
+    st->print("%d", small_num);
+    return;
+  }
+
+  if (Universe::is_fully_initialized()) {
+    if (StubRoutines::contains(adr)) {
+      StubCodeDesc* desc = StubCodeDesc::desc_for(adr);
+      if (desc == NULL)
+        desc = StubCodeDesc::desc_for(adr + frame::pc_return_offset);
+      if (desc != NULL) {
+        st->print("Stub::%s", desc->name());
+        if (desc->begin() != adr)
+          st->print("%+d 0x%p",adr - desc->begin(), adr);
+        else if (WizardMode) st->print(" " PTR_FORMAT, adr);
+        return;
+      }
+      st->print("Stub::<unknown> " PTR_FORMAT, adr);
+      return;
+    }
+
+    BarrierSet* bs = Universe::heap()->barrier_set();
+    if (bs->kind() == BarrierSet::CardTableModRef &&
+        adr == (address)((CardTableModRefBS*)(bs))->byte_map_base) {
+      st->print("word_map_base");
+      if (WizardMode) st->print(" " INTPTR_FORMAT, (intptr_t)adr);
+      return;
+    }
+
+    oop obj;
+    if (_nm != NULL
+        && (obj = _nm->embeddedOop_at(cur_insn())) != NULL
+        && (address) obj == adr
+        && Universe::heap()->is_in(obj)
+        && Universe::heap()->is_in(obj->klass())) {
+      julong c = st->count();
+      obj->print_value_on(st);
+      if (st->count() == c) {
+        // No output.  (Can happen in product builds.)
+        st->print("(a %s)", obj->klass()->external_name());
+      }
+      return;
+    }
+  }
+
+  // Fall through to a simple (hexadecimal) numeral.
+  st->print(PTR_FORMAT, adr);
+}
+
+void decode_env::print_insn_labels() {
+  address p = cur_insn();
+  outputStream* st = output();
+  CodeBlob* cb = _code;
+  if (cb != NULL) {
+    cb->print_block_comment(st, p);
+  }
   _strings.print_block_comment(st, (intptr_t)(p - _start));
-  if (_print_pc) {
-    st->print("  " PTR_FORMAT ": ", p);
-  }
-}
-
-void decode_env::print_insn_bytes(address pc, address pc_limit) {
-  outputStream* st = output();
-  size_t incr = 1;
-  size_t perline = _bytes_per_line;
-  if ((size_t) Disassembler::pd_instruction_alignment() >= sizeof(int)
-      && !((uintptr_t)pc % sizeof(int))
-      && !((uintptr_t)pc_limit % sizeof(int))) {
-    incr = sizeof(int);
-    if (perline % incr)  perline += incr - (perline % incr);
-  }
-  while (pc < pc_limit) {
-    // tab to the desired column:
-    st->move_to(COMMENT_COLUMN);
-    address pc0 = pc;
-    address pc1 = pc + perline;
-    if (pc1 > pc_limit)  pc1 = pc_limit;
-    for (; pc < pc1; pc += incr) {
-      if (pc == pc0)
-        st->print(BYTES_COMMENT);
-      else if ((uint)(pc - pc0) % sizeof(int) == 0)
-        st->print(" ");         // put out a space on word boundaries
-      if (incr == sizeof(int))
-            st->print("%08lx", *(int*)pc);
-      else  st->print("%02x",   (*pc)&0xFF);
-    }
-    st->cr();
-  }
-}
-
-
-static void* event_to_env(void* env_pv, const char* event, void* arg) {
-  decode_env* env = (decode_env*) env_pv;
-  return env->handle_event(event, (address) arg);
-}
-
-static int printf_to_env(void* env_pv, const char* format, ...) {
-  decode_env* env = (decode_env*) env_pv;
-  outputStream* st = env->output();
-  size_t flen = strlen(format);
-  const char* raw = NULL;
-  if (flen == 0)  return 0;
-  if (flen == 1 && format[0] == '\n') { st->bol(); return 1; }
-  if (flen < 2 ||
-      strchr(format, '%') == NULL) {
-    raw = format;
-  } else if (format[0] == '%' && format[1] == '%' &&
-             strchr(format+2, '%') == NULL) {
-    // happens a lot on machines with names like %foo
-    flen--;
-    raw = format+1;
-  }
-  if (raw != NULL) {
-    st->print_raw(raw, (int) flen);
-    return (int) flen;
-  }
-  va_list ap;
-  va_start(ap, format);
-  julong cnt0 = st->count();
-  st->vprint(format, ap);
-  julong cnt1 = st->count();
-  va_end(ap);
-  return (int)(cnt1 - cnt0);
-}
-
-address decode_env::decode_instructions(address start, address end) {
-  _start = start; _end = end;
-
-  assert(((((intptr_t)start | (intptr_t)end) % Disassembler::pd_instruction_alignment()) == 0), "misaligned insn addr");
-
-  const int show_bytes = false; // for disassembler debugging
-
-  //_version = Disassembler::pd_cpu_version();
-
-  if (!Disassembler::can_decode()) {
-    return NULL;
-  }
-
-  // decode a series of instructions and return the end of the last instruction
-
-  if (_print_raw) {
-    // Print whatever the library wants to print, w/o fancy callbacks.
-    // This is mainly for debugging the library itself.
-    FILE* out = stdout;
-    FILE* xmlout = (_print_raw > 1 ? out : NULL);
-    return use_new_version ?
-      (address)
-      (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
-                                                    start, end - start,
-                                                    NULL, (void*) xmlout,
-                                                    NULL, (void*) out,
-                                                    options(), 0/*nice new line*/)
-      :
-      (address)
-      (*Disassembler::_decode_instructions)(start, end,
-                                            NULL, (void*) xmlout,
-                                            NULL, (void*) out,
-                                            options());
-  }
-
-  return use_new_version ?
-    (address)
-    (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
-                                                  start, end - start,
-                                                  &event_to_env,  (void*) this,
-                                                  &printf_to_env, (void*) this,
-                                                  options(), 0/*nice new line*/)
-    :
-    (address)
-    (*Disassembler::_decode_instructions)(start, end,
-                                          &event_to_env,  (void*) this,
-                                          &printf_to_env, (void*) this,
-                                          options());
-}
-
-
-void Disassembler::decode(CodeBlob* cb, outputStream* st) {
-  if (!load_library())  return;
-  decode_env env(cb, st);
-  env.output()->print_cr("----------------------------------------------------------------------");
-  env.output()->print_cr("%s at  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", cb->name(), cb->code_begin(), cb->code_end(), ((jlong)(cb->code_end() - cb->code_begin())) * sizeof(unsigned char*));
-  env.decode_instructions(cb->code_begin(), cb->code_end());
-}
-
-void Disassembler::decode(address start, address end, outputStream* st, CodeStrings c) {
-  if (!load_library())  return;
-  decode_env env(CodeCache::find_blob_unsafe(start), st, c);
-  env.decode_instructions(start, end);
-}
-
-void Disassembler::decode(nmethod* nm, outputStream* st) {
-  if (!load_library())  return;
-  decode_env env(nm, st);
-  env.output()->print_cr("----------------------------------------------------------------------");
-
-#ifdef SHARK
-  SharkEntry* entry = (SharkEntry *) nm->code_begin();
-  unsigned char* p   = entry->code_start();
-  unsigned char* end = entry->code_limit();
-#else
-  unsigned char* p   = nm->code_begin();
-  unsigned char* end = nm->code_end();
-#endif // SHARK
-
-  nm->method()->method_holder()->name()->print_symbol_on(env.output());
-  env.output()->print(".");
-  nm->method()->name()->print_symbol_on(env.output());
-  env.output()->print_cr("  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", p, end, ((jlong)(end - p)) * sizeof(unsigned char*));
-
-  // If there has been profiling, print the buckets.
-  if (FlatProfiler::bucket_start_for(p) != NULL) {
-    unsigned char* p1 = p;
-    int total_bucket_count = 0;
-    while (p1 < end) {
-      unsigned char* p0 = p1;
-      p1 += pd_instruction_alignment();
-      address bucket_pc = FlatProfiler::bucket_start_for(p1);
-      if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p1)
-        total_bucket_count += FlatProfiler::bucket_count_for(p0);
-    }
-    env.set_total_ticks(total_bucket_count);
-  }
-
-  // Print constant table.
-  if (nm->consts_size() > 0) {
-    nm->print_nmethod_labels(env.output(), nm->consts_begin());
-    int offset = 0;
-    for (address p = nm->consts_begin(); p < nm->consts_end(); p += 4, offset += 4) {
-      if ((offset % 8) == 0) {
-        env.output()->print_cr("  " PTR_FORMAT " (offset: %4d): " PTR32_FORMAT "   " PTR64_FORMAT, p, offset, *((int32_t*) p), *((int64_t*) p));
-      } else {
-        env.output()->print_cr("  " PTR_FORMAT " (offset: %4d): " PTR32_FORMAT,                    p, offset, *((int32_t*) p));
-      }
-    }
-  }
-
-  env.decode_instructions(p, end);
-}
+  if (_print_pc) {
+    st->print("  " PTR_FORMAT ": ", p);
+  }
+}
+
+void decode_env::print_insn_bytes(address pc, address pc_limit) {
+  outputStream* st = output();
+  size_t incr = 1;
+  size_t perline = _bytes_per_line;
+  if ((size_t) Disassembler::pd_instruction_alignment() >= sizeof(int)
+      && !((uintptr_t)pc % sizeof(int))
+      && !((uintptr_t)pc_limit % sizeof(int))) {
+    incr = sizeof(int);
+    if (perline % incr)  perline += incr - (perline % incr);
+  }
+  while (pc < pc_limit) {
+    // tab to the desired column:
+    st->move_to(COMMENT_COLUMN);
+    address pc0 = pc;
+    address pc1 = pc + perline;
+    if (pc1 > pc_limit)  pc1 = pc_limit;
+    for (; pc < pc1; pc += incr) {
+      if (pc == pc0)
+        st->print(BYTES_COMMENT);
+      else if ((uint)(pc - pc0) % sizeof(int) == 0)
+        st->print(" ");         // put out a space on word boundaries
+      if (incr == sizeof(int))
+            st->print("%08lx", *(int*)pc);
+      else  st->print("%02x",   (*pc)&0xFF);
+    }
+    st->cr();
+  }
+}
+
+
+static void* event_to_env(void* env_pv, const char* event, void* arg) {
+  decode_env* env = (decode_env*) env_pv;
+  return env->handle_event(event, (address) arg);
+}
+
+static int printf_to_env(void* env_pv, const char* format, ...) {
+  decode_env* env = (decode_env*) env_pv;
+  outputStream* st = env->output();
+  size_t flen = strlen(format);
+  const char* raw = NULL;
+  if (flen == 0)  return 0;
+  if (flen == 1 && format[0] == '\n') { st->bol(); return 1; }
+  if (flen < 2 ||
+      strchr(format, '%') == NULL) {
+    raw = format;
+  } else if (format[0] == '%' && format[1] == '%' &&
+             strchr(format+2, '%') == NULL) {
+    // happens a lot on machines with names like %foo
+    flen--;
+    raw = format+1;
+  }
+  if (raw != NULL) {
+    st->print_raw(raw, (int) flen);
+    return (int) flen;
+  }
+  va_list ap;
+  va_start(ap, format);
+  julong cnt0 = st->count();
+  st->vprint(format, ap);
+  julong cnt1 = st->count();
+  va_end(ap);
+  return (int)(cnt1 - cnt0);
+}
+
+address decode_env::decode_instructions(address start, address end) {
+  _start = start; _end = end;
+
+  assert(((((intptr_t)start | (intptr_t)end) % Disassembler::pd_instruction_alignment()) == 0), "misaligned insn addr");
+
+  const int show_bytes = false; // for disassembler debugging
+
+  //_version = Disassembler::pd_cpu_version();
+
+  if (!Disassembler::can_decode()) {
+    return NULL;
+  }
+
+  // decode a series of instructions and return the end of the last instruction
+
+  if (_print_raw) {
+    // Print whatever the library wants to print, w/o fancy callbacks.
+    // This is mainly for debugging the library itself.
+    FILE* out = stdout;
+    FILE* xmlout = (_print_raw > 1 ? out : NULL);
+    return use_new_version ?
+      (address)
+      (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
+                                                    start, end - start,
+                                                    NULL, (void*) xmlout,
+                                                    NULL, (void*) out,
+                                                    options(), 0/*nice new line*/)
+      :
+      (address)
+      (*Disassembler::_decode_instructions)(start, end,
+                                            NULL, (void*) xmlout,
+                                            NULL, (void*) out,
+                                            options());
+  }
+
+  return use_new_version ?
+    (address)
+    (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
+                                                  start, end - start,
+                                                  &event_to_env,  (void*) this,
+                                                  &printf_to_env, (void*) this,
+                                                  options(), 0/*nice new line*/)
+    :
+    (address)
+    (*Disassembler::_decode_instructions)(start, end,
+                                          &event_to_env,  (void*) this,
+                                          &printf_to_env, (void*) this,
+                                          options());
+}
+
+
+void Disassembler::decode(CodeBlob* cb, outputStream* st) {
+  if (!load_library())  return;
+  decode_env env(cb, st);
+  env.output()->print_cr("----------------------------------------------------------------------");
+  env.output()->print_cr("%s at  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", cb->name(), cb->code_begin(), cb->code_end(), ((jlong)(cb->code_end() - cb->code_begin())) * sizeof(unsigned char*));
+  env.decode_instructions(cb->code_begin(), cb->code_end());
+}
+
+void Disassembler::decode(address start, address end, outputStream* st, CodeStrings c) {
+  if (!load_library())  return;
+  decode_env env(CodeCache::find_blob_unsafe(start), st, c);
+  env.decode_instructions(start, end);
+}
+
+void Disassembler::decode(nmethod* nm, outputStream* st) {
+  if (!load_library())  return;
+  decode_env env(nm, st);
+  env.output()->print_cr("----------------------------------------------------------------------");
+
+#ifdef SHARK
+  SharkEntry* entry = (SharkEntry *) nm->code_begin();
+  unsigned char* p   = entry->code_start();
+  unsigned char* end = entry->code_limit();
+#else
+  unsigned char* p   = nm->code_begin();
+  unsigned char* end = nm->code_end();
+#endif // SHARK
+
+  nm->method()->method_holder()->name()->print_symbol_on(env.output());
+  env.output()->print(".");
+  nm->method()->name()->print_symbol_on(env.output());
+  env.output()->print_cr("  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", p, end, ((jlong)(end - p)) * sizeof(unsigned char*));
+
+  // If there has been profiling, print the buckets.
+  if (FlatProfiler::bucket_start_for(p) != NULL) {
+    unsigned char* p1 = p;
+    int total_bucket_count = 0;
+    while (p1 < end) {
+      unsigned char* p0 = p1;
+      p1 += pd_instruction_alignment();
+      address bucket_pc = FlatProfiler::bucket_start_for(p1);
+      if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p1)
+        total_bucket_count += FlatProfiler::bucket_count_for(p0);
+    }
+    env.set_total_ticks(total_bucket_count);
+  }
+
+  // Print constant table.
+  if (nm->consts_size() > 0) {
+    nm->print_nmethod_labels(env.output(), nm->consts_begin());
+    int offset = 0;
+    for (address p = nm->consts_begin(); p < nm->consts_end(); p += 4, offset += 4) {
+      if ((offset % 8) == 0) {
+        env.output()->print_cr("  " PTR_FORMAT " (offset: %4d): " PTR32_FORMAT "   " PTR64_FORMAT, p, offset, *((int32_t*) p), *((int64_t*) p));
+      } else {
+        env.output()->print_cr("  " PTR_FORMAT " (offset: %4d): " PTR32_FORMAT,                    p, offset, *((int32_t*) p));
+      }
+    }
+  }
+
+  env.decode_instructions(p, end);
+}
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -513,6 +513,8 @@
       address dest = _constants->start() + CompilationResult_Site::pcOffset(patch);
       assert(!OopData::compressed(data), err_msg("unexpected compressed oop in data section"));
       _constants->relocate(dest, oop_Relocation::spec(oop_index));
+    } else {
+      ShouldNotReachHere();
     }
   }
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -329,13 +329,9 @@
   return (jlong) (address) klass->implementor();
 C2V_END
 
-C2V_VMENTRY(void, initializeMethod,(JNIEnv *, jobject, jlong metaspace_method, jobject hotspot_method))
+C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv *, jobject, jlong metaspace_method))
   methodHandle method = asMethod(metaspace_method);
-  InstanceKlass::cast(HotSpotResolvedJavaMethod::klass())->initialize(CHECK);
-  HotSpotResolvedJavaMethod::set_callerSensitive(hotspot_method, method->caller_sensitive());
-  HotSpotResolvedJavaMethod::set_forceInline(hotspot_method, method->force_inline());
-  HotSpotResolvedJavaMethod::set_dontInline(hotspot_method, method->dont_inline());
-  HotSpotResolvedJavaMethod::set_ignoredBySecurityStackWalk(hotspot_method, method->is_ignored_by_security_stack_walk());
+  return method->is_ignored_by_security_stack_walk();
 C2V_END
 
 C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jlong metaspace_method))
@@ -805,7 +801,7 @@
   {CC"findUniqueConcreteMethod",                     CC"("METASPACE_METHOD")"METASPACE_METHOD,                         FN_PTR(findUniqueConcreteMethod)},
   {CC"getKlassImplementor",                          CC"("METASPACE_KLASS")"METASPACE_KLASS,                           FN_PTR(getKlassImplementor)},
   {CC"getStackTraceElement",                         CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT,                     FN_PTR(getStackTraceElement)},
-  {CC"initializeMethod",                             CC"("METASPACE_METHOD HS_RESOLVED_METHOD")V",                     FN_PTR(initializeMethod)},
+  {CC"methodIsIgnoredBySecurityStackWalk",           CC"("METASPACE_METHOD")Z",                                        FN_PTR(methodIsIgnoredBySecurityStackWalk)},
   {CC"doNotInlineOrCompile",                         CC"("METASPACE_METHOD")V",                                        FN_PTR(doNotInlineOrCompile)},
   {CC"canInlineMethod",                              CC"("METASPACE_METHOD")Z",                                        FN_PTR(canInlineMethod)},
   {CC"shouldInlineMethod",                           CC"("METASPACE_METHOD")Z",                                        FN_PTR(shouldInlineMethod)},
--- a/src/share/vm/graal/graalJavaAccess.hpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Mar 26 20:44:11 2014 +0100
@@ -55,10 +55,6 @@
     oop_field(HotSpotResolvedJavaMethod, name, "Ljava/lang/String;")                                                                                           \
     oop_field(HotSpotResolvedJavaMethod, holder, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;")                                                  \
     long_field(HotSpotResolvedJavaMethod, metaspaceMethod)                                                                                                     \
-    boolean_field(HotSpotResolvedJavaMethod, callerSensitive)                                                                                                  \
-    boolean_field(HotSpotResolvedJavaMethod, forceInline)                                                                                                      \
-    boolean_field(HotSpotResolvedJavaMethod, dontInline)                                                                                                       \
-    boolean_field(HotSpotResolvedJavaMethod, ignoredBySecurityStackWalk)                                                                                       \
   end_class                                                                                                                                                    \
   start_class(HotSpotJavaType)                                                                                                                                 \
     oop_field(HotSpotJavaType, name, "Ljava/lang/String;")                                                                                                     \
--- a/src/share/vm/graal/graalRuntime.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -438,13 +438,12 @@
   return (jint)ret;
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oopDesc* where, oopDesc* format, jlong value))
+JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, jlong where, jlong format, jlong value))
   ResourceMark rm;
-  assert(where == NULL || java_lang_String::is_instance(where), "must be");
-  const char *error_msg = where == NULL ? "<internal Graal error>" : java_lang_String::as_utf8_string(where);
+  const char *error_msg = where == 0L ? "<internal Graal error>" : (char*) (address) where;
   char *detail_msg = NULL;
-  if (format != NULL) {
-    const char* buf = java_lang_String::as_utf8_string(format);
+  if (format != 0L) {
+    const char* buf = (char*) (address) format;
     size_t detail_msg_length = strlen(buf) * 2;
     detail_msg = (char *) NEW_RESOURCE_ARRAY(u_char, detail_msg_length);
     jio_snprintf(detail_msg, detail_msg_length, buf, value);
--- a/src/share/vm/graal/graalRuntime.hpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/graal/graalRuntime.hpp	Wed Mar 26 20:44:11 2014 +0100
@@ -43,7 +43,7 @@
   static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
   static void create_null_exception(JavaThread* thread);
   static void create_out_of_bounds_exception(JavaThread* thread, jint index);
-  static void vm_error(JavaThread* thread, oopDesc* where, oopDesc* format, jlong value);
+  static void vm_error(JavaThread* thread, jlong where, jlong format, jlong value);
   static oopDesc* load_and_clear_exception(JavaThread* thread);
   static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3);
   static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
--- a/src/share/vm/oops/method.hpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/oops/method.hpp	Wed Mar 26 20:44:11 2014 +0100
@@ -108,12 +108,15 @@
 #endif
   u2                _method_size;                // size of this object
   u1                _intrinsic_id;               // vmSymbols::intrinsic_id (0 == _none)
-  u1                _jfr_towrite      : 1,       // Flags
-                    _caller_sensitive : 1,
-                    _force_inline     : 1,
-                    _hidden           : 1,
-                    _dont_inline      : 1,
-                                      : 3;
+  // Flags
+  enum Flags {
+    _jfr_towrite      = 1 << 0,
+    _caller_sensitive = 1 << 1,
+    _force_inline     = 1 << 2,
+    _dont_inline      = 1 << 3,
+    _hidden           = 1 << 4
+  };
+  u1 _flags;
 
 #ifndef PRODUCT
   int               _compiled_invocation_count;  // Number of nmethod invocations so far (for perf. debugging)
@@ -759,16 +762,41 @@
   void init_intrinsic_id();     // updates from _none if a match
   static vmSymbols::SID klass_id_for_intrinsics(Klass* holder);
 
-  bool     jfr_towrite()            { return _jfr_towrite;          }
-  void set_jfr_towrite(bool x)      {        _jfr_towrite = x;      }
-  bool     caller_sensitive()       { return _caller_sensitive;     }
-  void set_caller_sensitive(bool x) {        _caller_sensitive = x; }
-  bool     force_inline()           { return _force_inline;         }
-  void set_force_inline(bool x)     {        _force_inline = x;     }
-  bool     dont_inline()            { return _dont_inline;          }
-  void set_dont_inline(bool x)      {        _dont_inline = x;      }
-  bool  is_hidden()                 { return _hidden;               }
-  void set_hidden(bool x)           {        _hidden = x;           }
+  bool jfr_towrite() {
+    return (_flags & _jfr_towrite) != 0;
+  }
+  void set_jfr_towrite(bool x) {
+    _flags = x ? (_flags | _jfr_towrite) : (_flags & ~_jfr_towrite);
+  }
+
+  bool caller_sensitive() {
+    return (_flags & _caller_sensitive) != 0;
+  }
+  void set_caller_sensitive(bool x) {
+    _flags = x ? (_flags | _caller_sensitive) : (_flags & ~_caller_sensitive);
+  }
+
+  bool force_inline() {
+    return (_flags & _force_inline) != 0;
+  }
+  void set_force_inline(bool x) {
+    _flags = x ? (_flags | _force_inline) : (_flags & ~_force_inline);
+  }
+
+  bool dont_inline() {
+    return (_flags & _dont_inline) != 0;
+  }
+  void set_dont_inline(bool x) {
+    _flags = x ? (_flags | _dont_inline) : (_flags & ~_dont_inline);
+  }
+
+  bool is_hidden() {
+    return (_flags & _hidden) != 0;
+  }
+  void set_hidden(bool x) {
+    _flags = x ? (_flags | _hidden) : (_flags & ~_hidden);
+  }
+
   ConstMethod::MethodType method_type() const {
       return _constMethod->method_type();
   }
--- a/src/share/vm/opto/node.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/opto/node.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -476,6 +476,7 @@
 #pragma clang diagnostic pop
 #endif
 
+
 //------------------------------clone------------------------------------------
 // Clone a Node.
 Node *Node::clone() const {
--- a/src/share/vm/opto/runtime.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/opto/runtime.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
-
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/vm/runtime/sharedRuntime.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -886,7 +886,10 @@
           _implicit_null_throws++;
 #endif
 #ifdef GRAAL
-          if (nm->is_compiled_by_graal()) {
+          if (nm->is_compiled_by_graal() && nm->pc_desc_at(pc) != NULL) {
+            // If there's no PcDesc then we'll die way down inside of
+            // deopt instead of just getting normal error reporting,
+            // so only go there if it will succeed.
             target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check);
           } else {
 #endif
--- a/src/share/vm/runtime/vmStructs.cpp	Wed Mar 26 17:02:45 2014 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Mar 26 20:44:11 2014 +0100
@@ -374,6 +374,7 @@
   nonstatic_field(Method,               _vtable_index,                                 int)                                   \
   nonstatic_field(Method,               _method_size,                                  u2)                                    \
   nonstatic_field(Method,               _intrinsic_id,                                 u1)                                    \
+  nonstatic_field(Method,               _flags,                                        u1)                                    \
   nonproduct_nonstatic_field(Method,    _compiled_invocation_count,                    int)                                   \
   volatile_nonstatic_field(Method,      _code,                                         nmethod*)                              \
   nonstatic_field(Method,               _i2i_entry,                                    address)                               \
@@ -2410,6 +2411,12 @@
   /* ConstMethod anon-enum */                                             \
   /********************************/                                      \
                                                                           \
+  declare_constant(Method::_jfr_towrite)                                  \
+  declare_constant(Method::_caller_sensitive)                             \
+  declare_constant(Method::_force_inline)                                 \
+  declare_constant(Method::_dont_inline)                                  \
+  declare_constant(Method::_hidden)                                       \
+                                                                          \
   declare_constant(ConstMethod::_has_linenumber_table)                    \
   declare_constant(ConstMethod::_has_checked_exceptions)                  \
   declare_constant(ConstMethod::_has_localvariable_table)                 \
@@ -2439,6 +2446,7 @@
   declare_constant(DataLayout::call_type_data_tag)                        \
   declare_constant(DataLayout::virtual_call_type_data_tag)                \
   declare_constant(DataLayout::parameters_type_data_tag)                  \
+  declare_constant(DataLayout::speculative_trap_data_tag)                 \
                                                                           \
   /*************************************/                                 \
   /* InstanceKlass enum                */                                 \