changeset 15892:079229f002a3

Merge with f4510fd9e8b3ad6965b3162b27edb476baa7140d
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Sat, 24 May 2014 10:48:18 -0700
parents 09ac9ac9c4fc (current diff) f4510fd9e8b3 (diff)
children 839cb35354e8 14ac87c56a27
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java
diffstat 77 files changed, 1858 insertions(+), 1444 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java	Sat May 24 10:48:18 2014 -0700
@@ -45,6 +45,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java	Sat May 24 10:48:18 2014 -0700
@@ -45,6 +45,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java	Sat May 24 10:48:18 2014 -0700
@@ -45,6 +45,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java	Sat May 24 10:48:18 2014 -0700
@@ -45,6 +45,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java	Sat May 24 10:48:18 2014 -0700
@@ -47,6 +47,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java	Sat May 24 10:48:18 2014 -0700
@@ -46,6 +46,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java	Sat May 24 10:48:18 2014 -0700
@@ -44,6 +44,11 @@
     }
 
     @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canDeoptimize());
+    }
+
+    @Override
     public void runTest() {
         setupArrays();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ForEachToGraalTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ForEachToGraalTest.java	Sat May 24 10:48:18 2014 -0700
@@ -23,12 +23,13 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
-import java.util.stream.IntStream;
-
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static org.junit.Assert.*;
-import org.junit.Test;
-import java.util.Arrays;
-import java.util.ArrayList;
+
+import java.util.*;
+import java.util.stream.*;
+
+import org.junit.*;
 
 /**
  * Several tests for the Sumatra APIs.
@@ -266,6 +267,10 @@
     // Graal throws NYI
     @Test
     public void testForEachIntRangeNoCapturesUseEscapingNew() {
+        if (runtime().getConfig().useHSAILDeoptimization == false) {
+            return;
+        }
+
         MyPoint[] dest = new MyPoint[size];
         IntStream range = IntStream.range(0, dest.length).parallel();
 
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VecmathNBodyDeoptTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VecmathNBodyDeoptTest.java	Sat May 24 10:48:18 2014 -0700
@@ -122,7 +122,7 @@
 
     @Override
     protected boolean supportsRequiredCapabilities() {
-        return (canHandleDeoptVirtualObjects());
+        return (canHandleDeoptVirtualObjects() && canDeoptimize());
     }
 
     @Test
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Sat May 24 10:48:18 2014 -0700
@@ -84,11 +84,11 @@
             // structure changes significantly
             StructuredGraph graph = parse(snippet);
             PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false));
-            new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+            CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+            new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
             new FloatingReadPhase().apply(graph);
             new OptimizeGuardAnchorsPhase().apply(graph);
-            new ReadEliminationPhase().apply(graph);
-            new CanonicalizerPhase(true).apply(graph, context);
+            canonicalizer.apply(graph, context);
 
             Debug.dump(graph, "After lowering");
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Sat May 24 10:48:18 2014 -0700
@@ -65,7 +65,7 @@
 
     boolean callKillsRegisters;
 
-    private static final int INITIAL_SPLIT_INTERVALS_CAPACITY = 32;
+    private static final int SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT = 1;
 
     public static class BlockData {
 
@@ -147,13 +147,6 @@
     BitMap2D intervalInLoop;
 
     /**
-     * The variable operands allocated from this pool. The {@linkplain #operandNumber(Value) number}
-     * of the first variable operand in this pool is one greater than the number of the last
-     * register operand in the pool.
-     */
-    private final ArrayList<Variable> variables;
-
-    /**
      * The {@linkplain #operandNumber(Value) number} of the first variable operand allocated.
      */
     private final int firstVariableNumber;
@@ -167,7 +160,6 @@
 
         this.registers = target.arch.getRegisters();
         this.firstVariableNumber = registers.length;
-        this.variables = new ArrayList<>(ir.numVariables() * 3 / 2);
         this.blockData = new BlockMap<>(ir.getControlFlowGraph());
     }
 
@@ -204,20 +196,6 @@
     }
 
     /**
-     * Gets the operand denoted by a given operand number.
-     */
-    private AllocatableValue operandFor(int operandNumber) {
-        if (operandNumber < firstVariableNumber) {
-            assert operandNumber >= 0;
-            return registers[operandNumber].asValue();
-        }
-        int index = operandNumber - firstVariableNumber;
-        Variable variable = variables.get(index);
-        assert variable.index == index;
-        return variable;
-    }
-
-    /**
      * Gets the number of operands. This value will increase by 1 for new variable.
      */
     private int operandSize() {
@@ -304,12 +282,10 @@
             firstDerivedIntervalIndex = intervalsSize;
         }
         if (intervalsSize == intervals.length) {
-            intervals = Arrays.copyOf(intervals, intervals.length * 2);
+            intervals = Arrays.copyOf(intervals, intervals.length + (intervals.length >> SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT));
         }
         intervalsSize++;
         Variable variable = new Variable(source.kind(), ir.nextVariable());
-        assert variables.size() == variable.index;
-        variables.add(variable);
 
         Interval interval = createInterval(variable);
         assert intervals[intervalsSize - 1] == interval;
@@ -342,6 +318,10 @@
         return intervalInLoop.at(interval, loop);
     }
 
+    Interval intervalFor(int operandNumber) {
+        return intervals[operandNumber];
+    }
+
     Interval intervalFor(Value operand) {
         int operandNumber = operandNumber(operand);
         assert operandNumber < intervalsSize;
@@ -609,16 +589,16 @@
      * {@linkplain ComputeBlockOrder linear scan order}.
      */
     void numberInstructions() {
+
+        intervalsSize = operandSize();
+        intervals = new Interval[intervalsSize + (intervalsSize >> SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT)];
+
         ValueProcedure setVariableProc = new ValueProcedure() {
 
             @Override
             public Value doValue(Value value) {
                 if (isVariable(value)) {
-                    int variableIdx = asVariable(value).index;
-                    while (variables.size() <= variableIdx) {
-                        variables.add(null);
-                    }
-                    variables.set(variableIdx, asVariable(value));
+                    getOrCreateInterval(asVariable(value));
                 }
                 return value;
             }
@@ -659,13 +639,6 @@
         }
         assert index == numInstructions : "must match";
         assert (index << 1) == opId : "must match: " + (index << 1);
-
-        if (DetailedAsserts.getValue()) {
-            for (int i = 0; i < variables.size(); i++) {
-                assert variables.get(i) != null && variables.get(i).index == i;
-            }
-            assert variables.size() == ir.numVariables();
-        }
     }
 
     /**
@@ -687,66 +660,66 @@
                 List<LIRInstruction> instructions = ir.getLIRforBlock(block);
                 int numInst = instructions.size();
 
+                ValueProcedure useProc = new ValueProcedure() {
+
+                    @Override
+                    protected Value doValue(Value operand) {
+                        if (isVariable(operand)) {
+                            int operandNum = operandNumber(operand);
+                            if (!liveKill.get(operandNum)) {
+                                liveGen.set(operandNum);
+                                Debug.log("liveGen for operand %d", operandNum);
+                            }
+                            if (block.getLoop() != null) {
+                                intervalInLoop.setBit(operandNum, block.getLoop().getIndex());
+                            }
+                        }
+
+                        if (DetailedAsserts.getValue()) {
+                            verifyInput(block, liveKill, operand);
+                        }
+                        return operand;
+                    }
+                };
+                ValueProcedure stateProc = new ValueProcedure() {
+
+                    @Override
+                    public Value doValue(Value operand) {
+                        int operandNum = operandNumber(operand);
+                        if (!liveKill.get(operandNum)) {
+                            liveGen.set(operandNum);
+                            Debug.log("liveGen in state for operand %d", operandNum);
+                        }
+                        return operand;
+                    }
+                };
+                ValueProcedure defProc = new ValueProcedure() {
+
+                    @Override
+                    public Value doValue(Value operand) {
+                        if (isVariable(operand)) {
+                            int varNum = operandNumber(operand);
+                            liveKill.set(varNum);
+                            Debug.log("liveKill for operand %d", varNum);
+                            if (block.getLoop() != null) {
+                                intervalInLoop.setBit(varNum, block.getLoop().getIndex());
+                            }
+                        }
+
+                        if (DetailedAsserts.getValue()) {
+                            // fixed intervals are never live at block boundaries, so
+                            // they need not be processed in live sets
+                            // process them only in debug mode so that this can be checked
+                            verifyTemp(liveKill, operand);
+                        }
+                        return operand;
+                    }
+                };
+
                 // iterate all instructions of the block
                 for (int j = 0; j < numInst; j++) {
                     final LIRInstruction op = instructions.get(j);
 
-                    ValueProcedure useProc = new ValueProcedure() {
-
-                        @Override
-                        protected Value doValue(Value operand) {
-                            if (isVariable(operand)) {
-                                int operandNum = operandNumber(operand);
-                                if (!liveKill.get(operandNum)) {
-                                    liveGen.set(operandNum);
-                                    Debug.log("liveGen for operand %d", operandNum);
-                                }
-                                if (block.getLoop() != null) {
-                                    intervalInLoop.setBit(operandNum, block.getLoop().getIndex());
-                                }
-                            }
-
-                            if (DetailedAsserts.getValue()) {
-                                verifyInput(block, liveKill, operand);
-                            }
-                            return operand;
-                        }
-                    };
-                    ValueProcedure stateProc = new ValueProcedure() {
-
-                        @Override
-                        public Value doValue(Value operand) {
-                            int operandNum = operandNumber(operand);
-                            if (!liveKill.get(operandNum)) {
-                                liveGen.set(operandNum);
-                                Debug.log("liveGen in state for operand %d", operandNum);
-                            }
-                            return operand;
-                        }
-                    };
-                    ValueProcedure defProc = new ValueProcedure() {
-
-                        @Override
-                        public Value doValue(Value operand) {
-                            if (isVariable(operand)) {
-                                int varNum = operandNumber(operand);
-                                liveKill.set(varNum);
-                                Debug.log("liveKill for operand %d", varNum);
-                                if (block.getLoop() != null) {
-                                    intervalInLoop.setBit(varNum, block.getLoop().getIndex());
-                                }
-                            }
-
-                            if (DetailedAsserts.getValue()) {
-                                // fixed intervals are never live at block boundaries, so
-                                // they need not be processed in live sets
-                                // process them only in debug mode so that this can be checked
-                                verifyTemp(liveKill, operand);
-                            }
-                            return operand;
-                        }
-                    };
-
                     try (Indent indent2 = Debug.logAndIndent("handle op %d", op.id())) {
                         op.forEachInput(useProc);
                         op.forEachAlive(useProc);
@@ -824,14 +797,12 @@
                         // liveOut(block) is the union of liveIn(sux), for successors sux of block
                         int n = block.getSuccessorCount();
                         if (n > 0) {
+                            liveOut.clear();
                             // block has successors
                             if (n > 0) {
-                                liveOut.clear();
                                 for (AbstractBlock<?> successor : block.getSuccessors()) {
                                     liveOut.or(blockData.get(successor).liveIn);
                                 }
-                            } else {
-                                liveOut.clear();
                             }
 
                             if (!blockSets.liveOut.equals(liveOut)) {
@@ -908,14 +879,14 @@
                 BitSet startBlockLiveIn = blockData.get(ir.getControlFlowGraph().getStartBlock()).liveIn;
                 try (Indent indent2 = Debug.logAndIndent("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):")) {
                     for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) {
-                        Value operand = operandFor(operandNum);
+                        Value operand = intervalFor(operandNum).operand;
                         Debug.log("var %d; operand=%s; node=%s", operandNum, operand, getValueForOperandFromDebugContext(operand));
                     }
                 }
 
                 // print some additional information to simplify debugging
                 for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) {
-                    Value operand = operandFor(operandNum);
+                    Value operand = intervalFor(operandNum).operand;
                     try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, getValueForOperandFromDebugContext(operand))) {
 
                         Deque<AbstractBlock<?>> definedIn = new ArrayDeque<>();
@@ -1153,9 +1124,6 @@
 
         try (Indent indent = Debug.logAndIndent("build intervals")) {
 
-            intervalsSize = operandSize();
-            intervals = new Interval[intervalsSize + INITIAL_SPLIT_INTERVALS_CAPACITY];
-
             // create a list with all caller-save registers (cpu, fpu, xmm)
             Register[] callerSaveRegs = frameMap.registerConfig.getCallerSaveRegisters();
 
@@ -1176,7 +1144,7 @@
                     BitSet live = blockData.get(block).liveOut;
                     for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) {
                         assert live.get(operandNum) : "should not stop here otherwise";
-                        AllocatableValue operand = operandFor(operandNum);
+                        AllocatableValue operand = intervalFor(operandNum).operand;
                         Debug.log("live in %d: %s", operandNum, operand);
 
                         addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, Kind.Illegal);
@@ -1186,7 +1154,7 @@
                         // that the block was part of a non-natural loop, so it might
                         // have an invalid loop index.
                         if (block.isLoopEnd() && block.getLoop() != null && isIntervalInLoop(operandNum, block.getLoop().getIndex())) {
-                            intervalFor(operand).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd);
+                            intervalFor(operandNum).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd);
                         }
                     }
 
@@ -1398,7 +1366,7 @@
         int newLen = newList.length;
 
         // conventional sort-algorithm for new intervals
-        Arrays.sort(newList, INTERVAL_COMPARATOR);
+        Arrays.sort(newList, (Interval a, Interval b) -> a.from() - b.from());
 
         // merge old and new list (both already sorted) into one combined list
         Interval[] combinedList = new Interval[oldLen + newLen];
@@ -1418,25 +1386,6 @@
         sortedIntervals = combinedList;
     }
 
-    private static final Comparator<Interval> INTERVAL_COMPARATOR = new Comparator<Interval>() {
-
-        public int compare(Interval a, Interval b) {
-            if (a != null) {
-                if (b != null) {
-                    return a.from() - b.from();
-                } else {
-                    return -1;
-                }
-            } else {
-                if (b != null) {
-                    return 1;
-                } else {
-                    return 0;
-                }
-            }
-        }
-    };
-
     public void allocateRegisters() {
         try (Indent indent = Debug.logAndIndent("allocate registers")) {
             Interval precoloredIntervals;
@@ -1469,25 +1418,12 @@
         throw new BailoutException("LinearScan: interval is null");
     }
 
-    Interval intervalAtBlockBegin(AbstractBlock<?> block, Value operand) {
-        assert isVariable(operand) : "register number out of bounds";
-        assert intervalFor(operand) != null : "no interval found";
-
-        return splitChildAtOpId(intervalFor(operand), getFirstLirInstructionId(block), LIRInstruction.OperandMode.DEF);
+    Interval intervalAtBlockBegin(AbstractBlock<?> block, int operandNumber) {
+        return splitChildAtOpId(intervalFor(operandNumber), getFirstLirInstructionId(block), LIRInstruction.OperandMode.DEF);
     }
 
-    Interval intervalAtBlockEnd(AbstractBlock<?> block, Value operand) {
-        assert isVariable(operand) : "register number out of bounds";
-        assert intervalFor(operand) != null : "no interval found";
-
-        return splitChildAtOpId(intervalFor(operand), getLastLirInstructionId(block) + 1, LIRInstruction.OperandMode.DEF);
-    }
-
-    Interval intervalAtOpId(Value operand, int opId) {
-        assert isVariable(operand) : "register number out of bounds";
-        assert intervalFor(operand) != null : "no interval found";
-
-        return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.USE);
+    Interval intervalAtBlockEnd(AbstractBlock<?> block, int operandNumber) {
+        return splitChildAtOpId(intervalFor(operandNumber), getLastLirInstructionId(block) + 1, LIRInstruction.OperandMode.DEF);
     }
 
     void resolveCollectMappings(AbstractBlock<?> fromBlock, AbstractBlock<?> toBlock, MoveResolver moveResolver) {
@@ -1501,9 +1437,8 @@
             assert operandNum < numOperands : "live information set for not exisiting interval";
             assert blockData.get(fromBlock).liveOut.get(operandNum) && blockData.get(toBlock).liveIn.get(operandNum) : "interval not live at this edge";
 
-            Value liveOperand = operandFor(operandNum);
-            Interval fromInterval = intervalAtBlockEnd(fromBlock, liveOperand);
-            Interval toInterval = intervalAtBlockBegin(toBlock, liveOperand);
+            Interval fromInterval = intervalAtBlockEnd(fromBlock, operandNum);
+            Interval toInterval = intervalAtBlockBegin(toBlock, operandNum);
 
             if (fromInterval != toInterval && !fromInterval.location().equals(toInterval.location())) {
                 // need to insert move instruction
@@ -1914,7 +1849,6 @@
             }
 
             printLir("After register number assignment", true);
-
         }
     }
 
@@ -1946,10 +1880,6 @@
         // (check that all intervals have a correct register and that no registers are overwritten)
         verifyIntervals();
 
-        // verifyNoOopsInFixedIntervals();
-
-        verifyConstants();
-
         verifyRegisters();
 
         Debug.log("no errors found");
@@ -2103,23 +2033,6 @@
         }
     }
 
-    void verifyConstants() {
-        try (Indent indent = Debug.logAndIndent("verifying that unpinned constants are not alive across block boundaries")) {
-            for (AbstractBlock<?> block : sortedBlocks) {
-                BitSet liveAtEdge = blockData.get(block).liveIn;
-
-                // visit all operands where the liveAtEdge bit is set
-                for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
-                    Debug.log("checking interval %d of block B%d", operandNum, block.getId());
-                    Value operand = operandFor(operandNum);
-                    assert isVariable(operand) : "value must have variable operand";
-                    // TKR assert value.asConstant() == null || value.isPinned() :
-                    // "only pinned constants can be alive accross block boundaries";
-                }
-            }
-        }
-    }
-
     /**
      * Returns a value for a interval definition, which can be used for re-materialization.
      *
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Sat May 24 10:48:18 2014 -0700
@@ -219,7 +219,7 @@
      */
     private static final boolean DEBUG = false;
 
-    private static final String MATCHPROCESSOR_LOG = "/tmp/matchprocessor.log";
+    private static final String LOGFILE = new File(System.getProperty("java.io.tmpdir"), "matchprocessor.log").getPath();
 
     private static PrintWriter log;
 
@@ -230,7 +230,7 @@
     private static synchronized PrintWriter getLog() {
         if (log == null) {
             try {
-                log = new PrintWriter(new FileWriter(MATCHPROCESSOR_LOG, true));
+                log = new PrintWriter(new FileWriter(LOGFILE, true));
             } catch (IOException e) {
                 // Do nothing
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Sat May 24 10:48:18 2014 -0700
@@ -52,9 +52,6 @@
 
         if (OptFloatingReads.getValue()) {
             appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase()));
-            if (OptReadElimination.getValue()) {
-                appendPhase(new ReadEliminationPhase());
-            }
         }
         appendPhase(new RemoveValueProxyPhase());
 
@@ -78,7 +75,7 @@
             appendPhase(canonicalizer);
         }
 
-        appendPhase(new LoopSafepointEliminationPhase());
+        appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopSafepointEliminationPhase()));
 
         appendPhase(new LoopSafepointInsertionPhase());
 
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Sat May 24 10:48:18 2014 -0700
@@ -277,7 +277,11 @@
     }
 
     public static Scope forceLog() {
-        return Debug.sandbox("forceLog", new DelegatingDebugConfig().enable(LOG).enable(LOG_METHOD));
+        ArrayList<Object> context = new ArrayList<>();
+        for (Object obj : context()) {
+            context.add(obj);
+        }
+        return Debug.sandbox("forceLog", new DelegatingDebugConfig().enable(LOG).enable(LOG_METHOD), context.toArray());
     }
 
     /**
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Sat May 24 10:48:18 2014 -0700
@@ -748,11 +748,7 @@
     }
 
     public <T> NodeMap<T> createNodeMap() {
-        return createNodeMap(false);
-    }
-
-    public <T> NodeMap<T> createNodeMap(boolean autoGrow) {
-        return new NodeMap<>(this, autoGrow);
+        return new NodeMap<>(this);
     }
 
     public NodeFlood createNodeFlood() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java	Sat May 24 10:48:18 2014 -0700
@@ -28,28 +28,21 @@
 
 public class NodeMap<T> extends NodeIdAccessor {
 
-    private final boolean autogrow;
     protected Object[] values;
 
     public NodeMap(Graph graph) {
-        this(graph, false);
-    }
-
-    public NodeMap(Graph graph, boolean autogrow) {
         super(graph);
         this.values = new Object[graph.nodeIdCount()];
-        this.autogrow = autogrow;
     }
 
     public NodeMap(NodeMap<T> copyFrom) {
         super(copyFrom.graph);
         this.values = Arrays.copyOf(copyFrom.values, copyFrom.values.length);
-        this.autogrow = copyFrom.autogrow;
     }
 
     @SuppressWarnings("unchecked")
     public T get(Node node) {
-        check(node);
+        assert check(node);
         return (T) values[getNodeId(node)];
     }
 
@@ -81,7 +74,7 @@
     }
 
     public void set(Node node, T value) {
-        check(node);
+        assert check(node);
         values[getNodeId(node)] = value;
     }
 
@@ -93,16 +86,10 @@
         return getNodeId(node) >= size();
     }
 
-    public void grow() {
-        this.values = Arrays.copyOf(values, graph.nodeIdCount());
-    }
-
-    private void check(Node node) {
-        if (autogrow && isNew(node)) {
-            grow();
-        }
+    private boolean check(Node node) {
         assert node.graph() == graph : String.format("%s is not part of the graph", node);
         assert !isNew(node) : "this node was added to the graph after creating the node map : " + node;
+        return true;
     }
 
     public void clear() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java	Sat May 24 10:48:18 2014 -0700
@@ -27,7 +27,7 @@
 public final class NodeNodeMap extends NodeMap<Node> implements Map<Node, Node> {
 
     public NodeNodeMap(Graph graph) {
-        super(graph, true);
+        super(graph);
     }
 
     public NodeNodeMap(NodeNodeMap copyFrom) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Sat May 24 10:48:18 2014 -0700
@@ -104,7 +104,7 @@
         HotSpotConstantReflectionProvider constantReflection = createConstantReflection(runtime);
         Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig());
         HotSpotHostForeignCallsProvider foreignCalls = createForeignCalls(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters);
-        HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers);
+        HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target);
         // Replacements cannot have speculative optimizations since they have
         // to be valid for the entire run of the VM.
         Assumptions assumptions = new Assumptions(false);
@@ -161,8 +161,9 @@
         return new HotSpotSnippetReflectionProvider();
     }
 
-    protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) {
-        return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers);
+    protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
+                    TargetDescription target) {
+        return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target);
     }
 
     protected Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Sat May 24 10:48:18 2014 -0700
@@ -35,8 +35,8 @@
 
     private AMD64ConvertSnippets.Templates convertSnippets;
 
-    public AMD64HotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) {
-        super(runtime, metaAccess, foreignCalls, registers);
+    public AMD64HotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) {
+        super(runtime, metaAccess, foreignCalls, registers, target);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Sat May 24 10:48:18 2014 -0700
@@ -59,7 +59,10 @@
 
     private static ValueNode filterCompression(ValueNode node) {
         ValueNode result = node;
-        while (result instanceof CompressionNode) {
+        if (result instanceof PiNode) {
+            result = ((PiNode) result).getOriginalNode();
+        }
+        if (result instanceof CompressionNode) {
             result = ((CompressionNode) result).getInput();
         }
         return result;
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Sat May 24 10:48:18 2014 -0700
@@ -489,6 +489,10 @@
         boolean useHSAILDeoptimization = config.useHSAILDeoptimization;
         boolean useHSAILSafepoints = config.useHSAILSafepoints;
 
+        if ((useHSAILSafepoints == true) && (useHSAILDeoptimization == false)) {
+            Debug.log("+UseHSAILSafepoints requires +UseHSAILDeoptimization");
+        }
+
         // see what graph nodes we have to see if we are using the thread register
         // if not, we don't have to emit the code that sets that up
         // maybe there is a better way to do this?
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Sat May 24 10:48:18 2014 -0700
@@ -36,8 +36,9 @@
 @ServiceProvider(HotSpotBackendFactory.class)
 public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory {
 
-    protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) {
-        return new HSAILHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers);
+    protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
+                    TargetDescription target) {
+        return new HSAILHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target);
     }
 
     @Override
@@ -46,10 +47,11 @@
 
         HotSpotRegisters registers = new HotSpotRegisters(HSAIL.threadRegister, Register.None, Register.None);
         HotSpotMetaAccessProvider metaAccess = host.getMetaAccess();
-        HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, createTarget());
+        TargetDescription target = createTarget();
+        HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, target);
         ConstantReflectionProvider constantReflection = host.getConstantReflection();
         HotSpotForeignCallsProvider foreignCalls = new HSAILHotSpotForeignCallsProvider(runtime, metaAccess, codeCache);
-        HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers);
+        HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target);
         // Replacements cannot have speculative optimizations since they have
         // to be valid for the entire run of the VM.
         Assumptions assumptions = new Assumptions(false);
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Sat May 24 10:48:18 2014 -0700
@@ -180,7 +180,7 @@
      * We need 64-bit and 32-bit scratch registers for the codegen $s0 can be live at this block.
      */
     private void emitDeoptimizeInner(Value actionAndReason, LIRFrameState lirFrameState, String emitName) {
-        DeoptimizeOp deopt = new DeoptimizeOp(actionAndReason, lirFrameState, emitName, getMetaAccess());
+        DeoptimizeOp deopt = new DeoptimizeOp(actionAndReason, lirFrameState, emitName, config.useHSAILDeoptimization, getMetaAccess());
         ((HSAILHotSpotLIRGenerationResult) getResult()).addDeopt(deopt);
         append(deopt);
     }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Sat May 24 10:48:18 2014 -0700
@@ -121,15 +121,14 @@
         return strategyMap.get(n.getClass());
     }
 
-    public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) {
-        super(runtime, metaAccess, foreignCalls, registers);
+    public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) {
+        super(runtime, metaAccess, foreignCalls, registers, target);
         initStrategyMap();
     }
 
     @Override
     public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
         super.initialize(providers, config);
-        TargetDescription target = providers.getCodeCache().getTarget();
         hsailNewObjectSnippets = new HSAILNewObjectSnippets.Templates(providers, target);
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Sat May 24 10:48:18 2014 -0700
@@ -104,7 +104,7 @@
     @Override
     public void visitSafepointNode(SafepointNode i) {
         HotSpotVMConfig config = getGen().config;
-        if (config.useHSAILSafepoints == true) {
+        if ((config.useHSAILSafepoints == true) && (config.useHSAILDeoptimization == true)) {
             LIRFrameState info = state(i);
             HSAILHotSpotSafepointOp safepoint = new HSAILHotSpotSafepointOp(info, config, this);
             ((HSAILHotSpotLIRGenerationResult) getGen().getResult()).addDeopt(safepoint);
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java	Sat May 24 10:48:18 2014 -0700
@@ -41,49 +41,54 @@
     @State protected LIRFrameState frameState;
     protected int codeBufferPos = -1;
     final int offsetToNoticeSafepoints;
+    final HotSpotVMConfig config;
 
     public HSAILHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRBuilderTool tool) {
         actionAndReason = tool.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(DeoptimizationAction.None, DeoptimizationReason.None, 0);
         frameState = state;
         offsetToNoticeSafepoints = config.hsailNoticeSafepointsOffset;
+        this.config = config;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+        if (config.useHSAILDeoptimization) {
+            // get a unique codeBuffer position
+            // when we save our state, we will save this as well (it can be used as a key to get the
+            // debugInfo)
+            codeBufferPos = masm.position();
 
-        // get a unique codeBuffer position
-        // when we save our state, we will save this as well (it can be used as a key to get the
-        // debugInfo)
-        codeBufferPos = masm.position();
+            masm.emitComment(" /* HSAIL safepoint bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */");
+            String afterSafepointLabel = "@LAfterSafepoint_at_pos_" + codeBufferPos;
 
-        masm.emitComment(" /* HSAIL safepoint bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */");
-        String afterSafepointLabel = "@LAfterSafepoint_at_pos_" + codeBufferPos;
+            AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object);
+            AllocatableValue spAddrReg = HSAIL.d17.asValue(Kind.Object);
+            AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int);
+            masm.emitLoadKernelArg(scratch64, masm.getDeoptInfoName(), "u64");
 
-        AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object);
-        AllocatableValue spAddrReg = HSAIL.d17.asValue(Kind.Object);
-        AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int);
-        masm.emitLoadKernelArg(scratch64, masm.getDeoptInfoName(), "u64");
+            // Build address of noticeSafepoints field
+            HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(Kind.Object, scratch64, offsetToNoticeSafepoints).toAddress();
+            masm.emitLoad(Kind.Object, spAddrReg, noticeSafepointsAddr);
 
-        // Build address of noticeSafepoints field
-        HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(Kind.Object, scratch64, offsetToNoticeSafepoints).toAddress();
-        masm.emitLoad(Kind.Object, spAddrReg, noticeSafepointsAddr);
-
-        // Load int value from that field
-        HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(Kind.Int, spAddrReg, 0).toAddress();
-        masm.emitLoadAcquire(scratch32, noticeSafepointsIntAddr);
-        masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false);
-        masm.cbr(afterSafepointLabel);
+            // Load int value from that field
+            HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(Kind.Int, spAddrReg, 0).toAddress();
+            masm.emitLoadAcquire(scratch32, noticeSafepointsIntAddr);
+            masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false);
+            masm.cbr(afterSafepointLabel);
 
-        AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
-        AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
-        masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason);
-        masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
-        masm.emitJumpToLabelName(masm.getDeoptLabelName());
+            AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
+            AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
+            masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason);
+            masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
+            masm.emitJumpToLabelName(masm.getDeoptLabelName());
 
-        masm.emitString0(afterSafepointLabel + ":\n");
+            masm.emitString0(afterSafepointLabel + ":\n");
 
-        // now record the debuginfo
-        crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.SAFEPOINT);
+            // now record the debuginfo
+            crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.SAFEPOINT);
+        } else {
+            masm.emitComment("/* HSAIL safepoint would have been here. */");
+        }
     }
 
     public LIRFrameState getFrameState() {
@@ -93,4 +98,4 @@
     public int getCodeBufferPos() {
         return codeBufferPos;
     }
-}
\ No newline at end of file
+}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Sat May 24 10:48:18 2014 -0700
@@ -221,7 +221,7 @@
             final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind);
             // lowerer extends HotSpotLoweringProvider so we can just use that
             HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
-            int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind));
+            int log2ElementSize = CodeUtil.log2(lowerer.arrayScalingFactor(elementKind));
 
             Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("hub", hub);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Sat May 24 10:48:18 2014 -0700
@@ -55,7 +55,7 @@
         HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
         Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig());
         HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters);
-        LoweringProvider lowerer = new SPARCHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers);
+        LoweringProvider lowerer = new SPARCHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target);
         // Replacements cannot have speculative optimizations since they have
         // to be valid for the entire run of the VM.
         Assumptions assumptions = new Assumptions(false);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java	Sat May 24 10:48:18 2014 -0700
@@ -32,8 +32,8 @@
 
 public class SPARCHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
 
-    public SPARCHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) {
-        super(runtime, metaAccess, foreignCalls, registers);
+    public SPARCHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) {
+        super(runtime, metaAccess, foreignCalls, registers, target);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Sat May 24 10:48:18 2014 -0700
@@ -20,103 +20,38 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package com.oracle.graal.hotspot;
 
 import static com.oracle.graal.compiler.GraalDebugConfig.*;
+import static com.oracle.graal.hotspot.HotSpotOptionsLoader.*;
 import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*;
-import static java.nio.file.Files.*;
+import static java.lang.Double.*;
 
-import java.io.*;
 import java.lang.reflect.*;
-import java.nio.charset.*;
-import java.nio.file.*;
 import java.util.*;
 
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.common.inlining.*;
 
 /**
- * Called from {@code graalCompiler.cpp} to parse any Graal specific options. Such options are
- * (currently) distinguished by a {@code "-G:"} prefix.
+ * Called from {@code graalCompiler.cpp} to set Graal options from the HotSpot command line. Such
+ * options are (currently) distinguished by a {@code "-G:"} prefix.
  */
 public class HotSpotOptions {
 
-    private static final Map<String, OptionDescriptor> options = new HashMap<>();
-
     /**
-     * Initializes {@link #options} from {@link Options} services.
-     */
-    private static void initializeOptions() {
-        ServiceLoader<Options> sl = ServiceLoader.loadInstalled(Options.class);
-        for (Options opts : sl) {
-            for (OptionDescriptor desc : opts) {
-                if (isHotSpotOption(desc)) {
-                    String name = desc.getName();
-                    OptionDescriptor existing = options.put(name, desc);
-                    assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
-                }
-            }
-        }
-    }
-
-    /**
-     * Determines if a given option is a HotSpot command line option.
+     * Parses the Graal specific options specified to HotSpot (e.g., on the command line).
+     *
+     * @return true if the CITime or CITimeEach HotSpot VM options are set
      */
-    public static boolean isHotSpotOption(OptionDescriptor desc) {
-        return desc.getClass().getName().startsWith("com.oracle.graal");
-    }
-
-    /**
-     * Loads default option value overrides from a {@code graal.options} file if it exists. Each
-     * line in this file starts with {@code "#"} and is ignored or must have the format of a Graal
-     * command line option without the leading {@code "-G:"} prefix. These option value are set
-     * prior to processing of any Graal options present on the command line.
-     */
-    private static void loadOptionOverrides() throws InternalError {
-        String javaHome = System.getProperty("java.home");
-        Path graalDotOptions = Paths.get(javaHome, "lib", "graal.options");
-        if (!exists(graalDotOptions)) {
-            graalDotOptions = Paths.get(javaHome, "jre", "lib", "graal.options");
-        }
-        if (exists(graalDotOptions)) {
-            try {
-                for (String line : Files.readAllLines(graalDotOptions, Charset.defaultCharset())) {
-                    if (!line.startsWith("#")) {
-                        if (!parseOption(line, null)) {
-                            throw new InternalError("Invalid option \"" + line + "\" specified in " + graalDotOptions);
-                        }
-                    }
-                }
-            } catch (IOException e) {
-                throw (InternalError) new InternalError().initCause(e);
-            }
-        }
-    }
-
-    /**
-     * Gets the Graal specific options specified to HotSpot (e.g., on the command line).
-     *
-     * @param timeCompilations (out) true if the CITime or CITimeEach HotSpot VM options are set
-     */
-    private static native String[] getVMOptions(boolean[] timeCompilations);
+    private static native boolean parseVMOptions();
 
     static {
-        initializeOptions();
-        loadOptionOverrides();
-
-        boolean[] timeCompilations = {false};
-        for (String option : getVMOptions(timeCompilations)) {
-            if (!parseOption(option, null)) {
-                throw new InternalError("Invalid Graal option \"-G:" + option + "\"");
-            }
-        }
-
-        if (timeCompilations[0] || PrintCompRate.getValue() != 0) {
+        boolean timeCompilations = parseVMOptions();
+        if (timeCompilations || PrintCompRate.getValue() != 0) {
             unconditionallyEnableTimerOrMetric(InliningUtil.class, "InlinedBytecodes");
             unconditionallyEnableTimerOrMetric(CompilationTask.class, "CompilationTime");
         }
@@ -138,6 +73,42 @@
     }
 
     /**
+     * Helper for the VM code called by {@link #parseVMOptions()}.
+     *
+     * @param name the name of a parsed option
+     * @param option the object encapsulating the option
+     * @param spec specification of boolean option value, type of option value or action to take
+     */
+    static void setOption(String name, OptionValue<?> option, char spec, String stringValue, long primitiveValue) {
+        switch (spec) {
+            case '+':
+                option.setValue(Boolean.TRUE);
+                break;
+            case '-':
+                option.setValue(Boolean.FALSE);
+                break;
+            case '?':
+                printFlags();
+                break;
+            case ' ':
+                printNoMatchMessage(name);
+                break;
+            case 'i':
+                option.setValue((int) primitiveValue);
+                break;
+            case 'f':
+                option.setValue((float) longBitsToDouble(primitiveValue));
+                break;
+            case 'd':
+                option.setValue(longBitsToDouble(primitiveValue));
+                break;
+            case 's':
+                option.setValue(stringValue);
+                break;
+        }
+    }
+
+    /**
      * Parses a given option value specification.
      *
      * @param option the specification of an option and its value
@@ -176,15 +147,7 @@
 
         OptionDescriptor desc = options.get(optionName);
         if (desc == null) {
-            Logger.info("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)");
-            List<OptionDescriptor> matches = fuzzyMatch(optionName);
-            if (!matches.isEmpty()) {
-                Logger.info("Did you mean one of the following?");
-                for (OptionDescriptor match : matches) {
-                    boolean isBoolean = match.getType() == boolean.class;
-                    Logger.info(String.format("    %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=<value>"));
-                }
-            }
+            printNoMatchMessage(optionName);
             return false;
         }
 
@@ -192,12 +155,12 @@
 
         if (value == null) {
             if (optionType == Boolean.TYPE || optionType == Boolean.class) {
-                Logger.info("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format");
+                System.err.println("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format");
                 return false;
             }
 
             if (valueString == null) {
-                Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
+                System.err.println("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
                 return false;
             }
 
@@ -212,7 +175,7 @@
             }
         } else {
             if (optionType != Boolean.class) {
-                Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
+                System.err.println("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
                 return false;
             }
         }
@@ -223,16 +186,28 @@
             } else {
                 OptionValue<?> optionValue = desc.getOptionValue();
                 optionValue.setValue(value);
-                // Logger.info("Set option " + desc.getName() + " to " + value);
+                // System.err.println("Set option " + desc.getName() + " to " + value);
             }
         } else {
-            Logger.info("Wrong value \"" + valueString + "\" for option " + optionName);
+            System.err.println("Wrong value \"" + valueString + "\" for option " + optionName);
             return false;
         }
 
         return true;
     }
 
+    protected static void printNoMatchMessage(String optionName) {
+        System.err.println("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)");
+        List<OptionDescriptor> matches = fuzzyMatch(optionName);
+        if (!matches.isEmpty()) {
+            System.err.println("Did you mean one of the following?");
+            for (OptionDescriptor match : matches) {
+                boolean isBoolean = match.getType() == boolean.class;
+                System.err.println(String.format("    %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=<value>"));
+            }
+        }
+    }
+
     /**
      * Sets the relevant system property such that a {@link DebugTimer} or {@link DebugMetric}
      * associated with a field in a class will be unconditionally enabled when it is created.
@@ -255,7 +230,7 @@
             }
             String previous = System.setProperty(propertyName, "true");
             if (previous != null) {
-                Logger.info("Overrode value \"" + previous + "\" of system property \"" + propertyName + "\" with \"true\"");
+                System.err.println("Overrode value \"" + previous + "\" of system property \"" + propertyName + "\" with \"true\"");
             }
         } catch (Exception e) {
             throw new GraalInternalError(e);
@@ -305,16 +280,16 @@
     }
 
     private static void printFlags() {
-        Logger.info("[Graal flags]");
-        SortedMap<String, OptionDescriptor> sortedOptions = new TreeMap<>(options);
+        System.out.println("[Graal flags]");
+        SortedMap<String, OptionDescriptor> sortedOptions = options;
         for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
             e.getKey();
             OptionDescriptor desc = e.getValue();
             Object value = desc.getOptionValue().getValue();
             List<String> helpLines = wrap(desc.getHelp(), 70);
-            Logger.info(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
+            System.out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
             for (int i = 1; i < helpLines.size(); i++) {
-                Logger.info(String.format("%67s %s", " ", helpLines.get(i)));
+                System.out.println(String.format("%67s %s", " ", helpLines.get(i)));
             }
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java	Sat May 24 10:48:18 2014 -0700
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.options.*;
+
+/**
+ * Helper class for separating loading of options from option initialization at runtime.
+ */
+class HotSpotOptionsLoader {
+    static final SortedMap<String, OptionDescriptor> options = new TreeMap<>();
+
+    /**
+     * Initializes {@link #options} from {@link Options} services.
+     */
+    static {
+        ServiceLoader<Options> sl = ServiceLoader.load(Options.class);
+        for (Options opts : sl) {
+            for (OptionDescriptor desc : opts) {
+                if (isHotSpotOption(desc)) {
+                    String name = desc.getName();
+                    OptionDescriptor existing = options.put(name, desc);
+                    assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
+                }
+            }
+        }
+    }
+
+    /**
+     * Determines if a given option is a HotSpot command line option.
+     */
+    private static boolean isHotSpotOption(OptionDescriptor desc) {
+        return desc.getClass().getName().startsWith("com.oracle.graal");
+    }
+
+    /**
+     * Command line utility for generating the source code of GraalRuntime::set_option() which is
+     * written {@link System#out}.
+     */
+    public static void main(String[] args) {
+        PrintStream out = System.out;
+        try {
+            Set<Integer> lengths = new TreeSet<>();
+            for (String s : options.keySet()) {
+                lengths.add(s.length());
+            }
+            lengths.add("PrintFlags".length());
+
+            out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS) {");
+            out.println("  if (value[0] == '+' || value[0] == '-') {");
+            out.println("    // boolean options");
+            genMatchers(out, lengths, true);
+            out.println("  } else {");
+            out.println("    // non-boolean options");
+            genMatchers(out, lengths, false);
+            out.println("  }");
+            out.println("  return false;");
+            out.println("}");
+        } catch (Throwable t) {
+            t.printStackTrace(out);
+        }
+        out.flush();
+    }
+
+    protected static void genMatchers(PrintStream out, Set<Integer> lengths, boolean isBoolean) throws Exception {
+        out.println("    switch (name_len) {");
+        for (int len : lengths) {
+            boolean printedCase = false;
+
+            // The use of strncmp is required (instead of strcmp) as the option name will not be
+            // null terminated for <name>=<value> style options.
+            if (len == "PrintFlags".length() && isBoolean) {
+                printedCase = true;
+                out.println("    case " + len + ":");
+                out.printf("      if (strncmp(name, \"PrintFlags\", %d) == 0) {\n", len);
+                out.println("        if (value[0] == '+') {");
+                out.println("          VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);");
+                out.println("        }");
+                out.println("        return true;");
+                out.println("      }");
+            }
+            for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
+                OptionDescriptor desc = e.getValue();
+                if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) {
+                    if (!printedCase) {
+                        printedCase = true;
+                        out.println("    case " + len + ":");
+                    }
+                    out.printf("      if (strncmp(name, \"%s\", %d) == 0) {\n", e.getKey(), len);
+                    Class<?> declaringClass = desc.getDeclaringClass();
+                    out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));\n", toInternalName(declaringClass), desc.getFieldName(),
+                                    toInternalName(getFieldType(desc)));
+                    if (isBoolean) {
+                        out.println("        VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);");
+                    } else if (desc.getType() == String.class) {
+                        out.println("        Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));");
+                        out.println("        VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);");
+                    } else {
+                        char spec = getPrimitiveSpecChar(desc);
+                        out.println("        jlong primitiveValue = parse_primitive_option_value('" + spec + "', name_handle, value, CHECK_(true));");
+                        out.println("        VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);");
+                    }
+                    out.println("        return true;");
+                    out.println("      }");
+                }
+            }
+        }
+        out.println("    }");
+    }
+
+    private static Class<?> getFieldType(OptionDescriptor desc) throws Exception {
+        return desc.getDeclaringClass().getDeclaredField(desc.getFieldName()).getType();
+    }
+
+    private static String toInternalName(Class<?> c) {
+        return c.getName().replace('.', '/');
+    }
+
+    /**
+     * @see HotSpotOptions#setOption(String, OptionValue, char, String, long)
+     */
+    private static char getPrimitiveSpecChar(OptionDescriptor desc) {
+        if (desc.getType() == Integer.class) {
+            return 'i';
+        }
+        if (desc.getType() == Float.class) {
+            return 'f';
+        }
+        if (desc.getType() == Double.class) {
+            return 'd';
+        }
+        throw GraalInternalError.shouldNotReachHere("Unexpected primitive option type: " + desc.getType().getName());
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Sat May 24 10:48:18 2014 -0700
@@ -40,7 +40,7 @@
      * @param metaspaceMethod the metaspace Method object
      * @return a new byte array containing the original bytecode
      */
-    byte[] initializeBytecode(long metaspaceMethod);
+    byte[] getBytecode(long metaspaceMethod);
 
     int exceptionTableLength(long metaspaceMethod);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Sat May 24 10:48:18 2014 -0700
@@ -43,7 +43,7 @@
     public native long getMetaspaceMethod(Class<?> holder, int slot);
 
     @Override
-    public native byte[] initializeBytecode(long metaspaceMethod);
+    public native byte[] getBytecode(long metaspaceMethod);
 
     @Override
     public native int exceptionTableLength(long metaspaceMethod);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Sat May 24 10:48:18 2014 -0700
@@ -22,22 +22,14 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.code.MemoryBarriers.*;
-import static com.oracle.graal.api.meta.DeoptimizationAction.*;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
-import static com.oracle.graal.nodes.java.ArrayLengthNode.*;
-
-import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
@@ -56,16 +48,14 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.replacements.*;
 
 /**
  * HotSpot implementation of {@link LoweringProvider}.
  */
-public class DefaultHotSpotLoweringProvider implements HotSpotLoweringProvider {
+public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider {
 
     protected final HotSpotGraalRuntime runtime;
-    protected final MetaAccessProvider metaAccess;
     protected final ForeignCallsProvider foreignCalls;
     protected final HotSpotRegistersProvider registers;
 
@@ -74,25 +64,25 @@
     protected NewObjectSnippets.Templates newObjectSnippets;
     protected MonitorSnippets.Templates monitorSnippets;
     protected WriteBarrierSnippets.Templates writeBarrierSnippets;
-    protected BoxingSnippets.Templates boxingSnippets;
     protected LoadExceptionObjectSnippets.Templates exceptionObjectSnippets;
     protected UnsafeLoadSnippets.Templates unsafeLoadSnippets;
 
-    public DefaultHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) {
+    public DefaultHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) {
+        super(metaAccess, target);
         this.runtime = runtime;
-        this.metaAccess = metaAccess;
         this.foreignCalls = foreignCalls;
         this.registers = registers;
     }
 
     public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
-        TargetDescription target = providers.getCodeCache().getTarget();
+        super.initialize(providers, providers.getSnippetReflection());
+
+        assert target == providers.getCodeCache().getTarget();
         checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, target);
         instanceofSnippets = new InstanceOfSnippets.Templates(providers, target);
         newObjectSnippets = new NewObjectSnippets.Templates(providers, target);
         monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking);
         writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null);
-        boxingSnippets = new BoxingSnippets.Templates(providers, providers.getSnippetReflection(), target);
         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target);
         unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target);
         providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target));
@@ -102,38 +92,12 @@
     public void lower(Node n, LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) n.graph();
 
-        if (n instanceof ArrayLengthNode) {
-            lowerArrayLengthNode((ArrayLengthNode) n, tool);
-        } else if (n instanceof Invoke) {
+        if (n instanceof Invoke) {
             lowerInvoke((Invoke) n, tool, graph);
-        } else if (n instanceof LoadFieldNode) {
-            lowerLoadFieldNode((LoadFieldNode) n, tool);
-        } else if (n instanceof StoreFieldNode) {
-            lowerStoreFieldNode((StoreFieldNode) n, tool);
-        } else if (n instanceof CompareAndSwapNode) {
-            lowerCompareAndSwapNode((CompareAndSwapNode) n);
-        } else if (n instanceof AtomicReadAndWriteNode) {
-            lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n);
-        } else if (n instanceof LoadIndexedNode) {
-            lowerLoadIndexedNode((LoadIndexedNode) n, tool);
-        } else if (n instanceof StoreIndexedNode) {
-            lowerStoreIndexedNode((StoreIndexedNode) n, tool);
-        } else if (n instanceof UnsafeLoadNode) {
-            lowerUnsafeLoadNode((UnsafeLoadNode) n, tool);
-        } else if (n instanceof UnsafeStoreNode) {
-            lowerUnsafeStoreNode((UnsafeStoreNode) n);
-        } else if (n instanceof JavaReadNode) {
-            lowerJavaReadNode((JavaReadNode) n);
-        } else if (n instanceof JavaWriteNode) {
-            lowerJavaWriteNode((JavaWriteNode) n);
-        } else if (n instanceof LoadHubNode) {
-            lowerLoadHubNode((LoadHubNode) n);
         } else if (n instanceof LoadMethodNode) {
             lowerLoadMethodNode((LoadMethodNode) n);
         } else if (n instanceof StoreHubNode) {
             lowerStoreHubNode((StoreHubNode) n, graph);
-        } else if (n instanceof CommitAllocationNode) {
-            lowerCommitAllocationNode((CommitAllocationNode) n, tool);
         } else if (n instanceof OSRStartNode) {
             lowerOSRStartNode((OSRStartNode) n);
         } else if (n instanceof DynamicCounterNode) {
@@ -197,26 +161,13 @@
         } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
             // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
             // zero and the MIN_VALUE / -1 cases.
-        } else if (n instanceof BoxNode) {
-            boxingSnippets.lower((BoxNode) n, tool);
-        } else if (n instanceof UnboxNode) {
-            boxingSnippets.lower((UnboxNode) n, tool);
         } else if (n instanceof DeoptimizeNode || n instanceof UnwindNode || n instanceof FloatRemNode) {
             /* No lowering, we generate LIR directly for these nodes. */
         } else {
-            throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n);
+            super.lower(n, tool);
         }
     }
 
-    private void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) {
-        StructuredGraph graph = arrayLengthNode.graph();
-        ValueNode array = arrayLengthNode.array();
-        ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, graph),
-                        StampFactory.positiveInt(), BarrierType.NONE, false));
-        arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool));
-        graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
-    }
-
     private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph) {
         if (invoke.callTarget() instanceof MethodCallTargetNode) {
             MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
@@ -236,7 +187,7 @@
                 ResolvedJavaType receiverType = invoke.getReceiverType();
                 if (hsMethod.isInVirtualMethodTable(receiverType)) {
                     Kind wordKind = runtime.getTarget().wordKind;
-                    ValueNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck);
+                    ValueNode hub = createReadHub(graph, receiver, receiverNullCheck);
 
                     ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod, receiverType);
                     // We use LocationNode.ANY_LOCATION for the reads that access the
@@ -261,291 +212,54 @@
         }
     }
 
-    private Stamp loadStamp(Stamp stamp, Kind kind) {
-        return loadStamp(stamp, kind, true);
-    }
-
-    private Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) {
-        switch (kind) {
-            case Boolean:
-            case Byte:
-                return StampTool.narrowingConversion(stamp, 8);
-
-            case Char:
-            case Short:
-                return StampTool.narrowingConversion(stamp, 16);
-
-            case Object:
-                if (compressible && runtime.getConfig().useCompressedOops) {
-                    return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getConfig().getOopEncoding());
-                }
+    @Override
+    protected Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) {
+        if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) {
+            return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getConfig().getOopEncoding());
         }
-        return stamp;
-    }
-
-    public ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value) {
-        return implicitLoadConvert(graph, kind, value, true);
-    }
-
-    private ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) {
-        switch (kind) {
-            case Byte:
-            case Short:
-                return graph.unique(new SignExtendNode(value, 32));
-
-            case Boolean:
-            case Char:
-                return graph.unique(new ZeroExtendNode(value, 32));
-
-            case Object:
-                if (compressible && runtime.getConfig().useCompressedOops) {
-                    return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding());
-                }
-        }
-        return value;
-    }
-
-    private void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) {
-        StructuredGraph graph = loadField.graph();
-        HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
-        ValueNode object = loadField.isStatic() ? ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph) : loadField.object();
-        assert loadField.getKind() != Kind.Illegal;
-        BarrierType barrierType = getFieldLoadBarrierType(field);
-
-        Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind());
-        ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadStamp, barrierType, false));
-        ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead);
-
-        loadField.replaceAtUsages(readValue);
-        graph.replaceFixed(loadField, memoryRead);
-
-        memoryRead.setGuard(createNullCheck(object, memoryRead, tool));
-
-        if (loadField.isVolatile()) {
-            MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ));
-            graph.addBeforeFixed(memoryRead, preMembar);
-            MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ));
-            graph.addAfterFixed(memoryRead, postMembar);
-        }
+        return super.loadStamp(stamp, kind, compressible);
     }
 
-    public ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value) {
-        return implicitStoreConvert(graph, kind, value, true);
-    }
-
-    private ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) {
-        switch (kind) {
-            case Boolean:
-            case Byte:
-                return graph.unique(new NarrowNode(value, 8));
-            case Char:
-            case Short:
-                return graph.unique(new NarrowNode(value, 16));
-            case Object:
-                if (compressible && runtime.getConfig().useCompressedOops) {
-                    return CompressionNode.compress(value, runtime.getConfig().getOopEncoding());
-                }
+    @Override
+    protected ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) {
+        if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) {
+            return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding());
         }
-        return value;
+        return super.implicitLoadConvert(graph, kind, value, compressible);
     }
 
-    private void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) {
-        StructuredGraph graph = storeField.graph();
-        HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
-        ValueNode object = storeField.isStatic() ? ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph) : storeField.object();
-        BarrierType barrierType = getFieldStoreBarrierType(storeField);
-
-        ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value());
-        WriteNode memoryWrite = graph.add(new WriteNode(object, value, createFieldLocation(graph, field, false), barrierType, false));
-        memoryWrite.setStateAfter(storeField.stateAfter());
-        graph.replaceFixedWithFixed(storeField, memoryWrite);
-        memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool));
-        FixedWithNextNode last = memoryWrite;
-        FixedWithNextNode first = memoryWrite;
-
-        if (storeField.isVolatile()) {
-            MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
-            graph.addBeforeFixed(first, preMembar);
-            MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
-            graph.addAfterFixed(last, postMembar);
-        }
-    }
-
-    private void lowerCompareAndSwapNode(CompareAndSwapNode cas) {
-        StructuredGraph graph = cas.graph();
-        Kind valueKind = cas.getValueKind();
-        LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), valueKind, cas.displacement(), cas.offset(), graph, 1);
-
-        ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected(), true);
-        ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue(), true);
-
-        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, getCompareAndSwapBarrierType(cas), false));
-        atomicNode.setStateAfter(cas.stateAfter());
-        graph.replaceFixedWithFixed(cas, atomicNode);
-    }
-
-    private void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) {
-        StructuredGraph graph = n.graph();
-        Kind valueKind = n.getValueKind();
-        LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1);
-
-        ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
-
-        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, getAtomicReadAndWriteBarrierType(n), false));
-        memoryRead.setStateAfter(n.stateAfter());
-
-        ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead);
-
-        n.replaceAtUsages(readValue);
-        graph.replaceFixedWithFixed(n, memoryRead);
+    @Override
+    protected ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField f) {
+        HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f;
+        return ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph);
     }
 
-    private void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) {
-        StructuredGraph graph = loadIndexed.graph();
-        Kind elementKind = loadIndexed.elementKind();
-        LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false);
-
-        Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind);
-        ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadStamp, BarrierType.NONE, false));
-        ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead);
-
-        memoryRead.setGuard(createBoundsCheck(loadIndexed, tool));
-
-        loadIndexed.replaceAtUsages(readValue);
-        graph.replaceFixed(loadIndexed, memoryRead);
-    }
-
-    private void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) {
-        StructuredGraph graph = storeIndexed.graph();
-        GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool);
-        Kind elementKind = storeIndexed.elementKind();
-        LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false);
-
-        ValueNode value = storeIndexed.value();
-        ValueNode array = storeIndexed.array();
-
-        CheckCastNode checkcastNode = null;
-        CheckCastDynamicNode checkcastDynamicNode = null;
-        if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) {
-            // Store check!
-            ResolvedJavaType arrayType = StampTool.typeOrNull(array);
-            if (arrayType != null && StampTool.isExactType(array)) {
-                ResolvedJavaType elementType = arrayType.getComponentType();
-                if (!MetaUtil.isJavaLangObject(elementType)) {
-                    checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true));
-                    graph.addBeforeFixed(storeIndexed, checkcastNode);
-                    value = checkcastNode;
-                }
-            } else {
-                Kind wordKind = runtime.getTarget().wordKind;
-                ValueNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck);
-                LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph);
-                /*
-                 * Anchor the read of the element klass to the cfg, because it is only valid when
-                 * arrayClass is an object class, which might not be the case in other parts of the
-                 * compiled method.
-                 */
-                FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed)));
-                checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true));
-                graph.addBeforeFixed(storeIndexed, checkcastDynamicNode);
-                value = checkcastDynamicNode;
-            }
+    @Override
+    protected ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) {
+        if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) {
+            return CompressionNode.compress(value, runtime.getConfig().getOopEncoding());
         }
-        BarrierType barrierType = getArrayStoreBarrierType(storeIndexed);
-        WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), arrayLocation, barrierType, false));
-        memoryWrite.setGuard(boundsCheck);
-        memoryWrite.setStateAfter(storeIndexed.stateAfter());
-        graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
-
-        // Lower the associated checkcast node.
-        if (checkcastNode != null) {
-            checkcastNode.lower(tool);
-        } else if (checkcastDynamicNode != null) {
-            checkcastDynamicSnippets.lower(checkcastDynamicNode, tool);
-        }
+        return super.implicitStoreConvert(graph, kind, value, compressible);
     }
 
-    private ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) {
-        boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
-        Kind readKind = load.accessKind();
-        LocationNode location = createLocation(load);
-        Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible);
-        ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE, false));
-        ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible);
-        load.replaceAtUsages(readValue);
-        return memoryRead;
-    }
-
-    private void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) {
-        StructuredGraph graph = load.graph();
-        if (load.getGuardingCondition() != null) {
-            ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition()));
-            ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode);
-            graph.replaceFixedWithFixed(load, valueAnchorNode);
-            graph.addAfterFixed(valueAnchorNode, memoryRead);
-        } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) {
-            assert load.getKind() != Kind.Illegal;
-            if (addReadBarrier(load)) {
-                unsafeLoadSnippets.lower(load, tool);
-            } else {
-                ReadNode memoryRead = createUnsafeRead(graph, load, null);
-                // An unsafe read must not float outside its block otherwise
-                // it may float above an explicit null check on its object.
-                memoryRead.setGuard(BeginNode.prevBegin(load));
-                graph.replaceFixedWithFixed(load, memoryRead);
-            }
-        }
+    @Override
+    protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor) {
+        Kind wordKind = runtime.getTarget().wordKind;
+        LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph);
+        /*
+         * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass
+         * is an object class, which might not be the case in other parts of the compiled method.
+         */
+        return graph.unique(new FloatingReadNode(arrayHub, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(anchor)));
     }
 
-    private void lowerUnsafeStoreNode(UnsafeStoreNode store) {
-        StructuredGraph graph = store.graph();
-        LocationNode location = createLocation(store);
-        ValueNode object = store.object();
-        BarrierType barrierType = getUnsafeStoreBarrierType(store);
-        boolean compressible = store.value().getKind() == Kind.Object;
-        Kind valueKind = store.accessKind();
-        ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible);
-        WriteNode write = graph.add(new WriteNode(object, value, location, barrierType, false));
-        write.setStateAfter(store.stateAfter());
-        graph.replaceFixedWithFixed(store, write);
-    }
-
-    private void lowerJavaReadNode(JavaReadNode read) {
-        StructuredGraph graph = read.graph();
-
-        Kind valueKind = read.location().getValueKind();
-        Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible());
-        ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType(), false));
-        ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible());
-
-        memoryRead.setGuard(read.getGuard());
-
-        read.replaceAtUsages(readValue);
-        graph.replaceFixed(read, memoryRead);
-    }
-
-    private void lowerJavaWriteNode(JavaWriteNode write) {
-        StructuredGraph graph = write.graph();
-
-        Kind valueKind = write.location().getValueKind();
-        ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible());
-
-        WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), false, write.isInitialization()));
-        memoryWrite.setStateAfter(write.stateAfter());
-        graph.replaceFixedWithFixed(write, memoryWrite);
-
-        memoryWrite.setGuard(write.getGuard());
-    }
-
-    private void lowerLoadHubNode(LoadHubNode loadHub) {
-        StructuredGraph graph = loadHub.graph();
-        if (graph.getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) {
-            Kind wordKind = runtime.getTarget().wordKind;
-            assert loadHub.getKind() == wordKind;
-            ValueNode object = loadHub.object();
-            GuardingNode guard = loadHub.getGuard();
-            ValueNode hub = createReadHub(graph, wordKind, object, guard);
-            graph.replaceFloating(loadHub, hub);
+    @Override
+    protected void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) {
+        StructuredGraph graph = load.graph();
+        if (load.getGuardingCondition() == null && graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal() && addReadBarrier(load)) {
+            unsafeLoadSnippets.lower(load, tool);
+        } else {
+            super.lowerUnsafeLoadNode(load, tool);
         }
     }
 
@@ -561,88 +275,14 @@
         graph.replaceFixed(storeHub, hub);
     }
 
-    private void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) {
-        StructuredGraph graph = commit.graph();
-        if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-            ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
-            BitSet omittedValues = new BitSet();
-            int valuePos = 0;
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
-                int entryCount = virtual.entryCount();
-                FixedWithNextNode newObject;
-                if (virtual instanceof VirtualInstanceNode) {
-                    newObject = graph.add(new NewInstanceNode(virtual.type(), true));
-                } else {
-                    newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true));
-                }
-                graph.addBeforeFixed(commit, newObject);
-                allocations[objIndex] = newObject;
-                for (int i = 0; i < entryCount; i++) {
-                    ValueNode value = commit.getValues().get(valuePos);
-                    if (value instanceof VirtualObjectNode) {
-                        value = allocations[commit.getVirtualObjects().indexOf(value)];
-                    }
-                    if (value == null) {
-                        omittedValues.set(valuePos);
-                    } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                        // Constant.illegal is always the defaultForKind, so it is skipped
-                        Kind valueKind = value.getKind();
-                        Kind entryKind = virtual.entryKind(i);
+    @Override
+    protected BarrierType fieldInitializationBarrier(Kind entryKind) {
+        return (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE;
+    }
 
-                        // Truffle requires some leniency in terms of what can be put where:
-                        Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind;
-                        assert valueKind.getStackKind() == entryKind.getStackKind() ||
-                                        (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode));
-                        ConstantLocationNode location;
-                        BarrierType barrierType;
-                        if (virtual instanceof VirtualInstanceNode) {
-                            ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i);
-                            location = ConstantLocationNode.create(INIT_LOCATION, accessKind, ((HotSpotResolvedJavaField) field).offset(), graph);
-                            barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE;
-                        } else {
-                            location = ConstantLocationNode.create(INIT_LOCATION, accessKind, getArrayBaseOffset(entryKind) + i * getScalingFactor(entryKind), graph);
-                            barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE;
-                        }
-                        WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType, false);
-                        graph.addAfterFixed(newObject, graph.add(write));
-                    }
-                    valuePos++;
-
-                }
-            }
-            valuePos = 0;
-
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
-                int entryCount = virtual.entryCount();
-                ValueNode newObject = allocations[objIndex];
-                for (int i = 0; i < entryCount; i++) {
-                    if (omittedValues.get(valuePos)) {
-                        ValueNode value = commit.getValues().get(valuePos);
-                        assert value instanceof VirtualObjectNode;
-                        ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)];
-                        if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) {
-                            assert virtual.entryKind(i) == Kind.Object && allocValue.getKind() == Kind.Object;
-                            WriteNode write;
-                            if (virtual instanceof VirtualInstanceNode) {
-                                VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
-                                write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i),
-                                                true), BarrierType.IMPRECISE, false);
-                            } else {
-                                write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph),
-                                                true), BarrierType.PRECISE, false);
-                            }
-                            graph.addBeforeFixed(commit, graph.add(write));
-                        }
-                    }
-                    valuePos++;
-                }
-            }
-
-            finishAllocatedObjects(tool, commit, allocations);
-            graph.removeFixed(commit);
-        }
+    @Override
+    protected BarrierType arrayInitializationBarrier(Kind entryKind) {
+        return (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE;
     }
 
     private void lowerOSRStartNode(OSRStartNode osrStart) {
@@ -729,79 +369,6 @@
         }
     }
 
-    public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) {
-        StructuredGraph graph = commit.graph();
-        for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-            FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
-            allocations[objIndex] = anchor;
-            graph.addBeforeFixed(commit, anchor);
-        }
-        for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-            for (MonitorIdNode monitorId : commit.getLocks(objIndex)) {
-                MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId));
-                graph.addBeforeFixed(commit, enter);
-                enter.lower(tool);
-            }
-        }
-        for (Node usage : commit.usages().snapshot()) {
-            AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
-            int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
-            graph.replaceFloating(addObject, allocations[index]);
-        }
-    }
-
-    private static LocationNode createLocation(UnsafeAccessNode access) {
-        return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind());
-    }
-
-    private static LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) {
-        ValueNode offset = offsetNode;
-        if (offset.isConstant()) {
-            long offsetValue = offset.asConstant().asLong();
-            return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph());
-        }
-
-        long displacement = 0;
-        int indexScaling = 1;
-        boolean signExtend = false;
-        if (offset instanceof SignExtendNode) {
-            SignExtendNode extend = (SignExtendNode) offset;
-            if (extend.getResultBits() == 64) {
-                signExtend = true;
-                offset = extend.getInput();
-            }
-        }
-        if (offset instanceof IntegerAddNode) {
-            IntegerAddNode integerAddNode = (IntegerAddNode) offset;
-            if (integerAddNode.y() instanceof ConstantNode) {
-                displacement = integerAddNode.y().asConstant().asLong();
-                offset = integerAddNode.x();
-            }
-        }
-
-        if (offset instanceof LeftShiftNode) {
-            LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
-            if (leftShiftNode.y() instanceof ConstantNode) {
-                long shift = leftShiftNode.y().asConstant().asLong();
-                if (shift >= 1 && shift <= 3) {
-                    if (shift == 1) {
-                        indexScaling = 2;
-                    } else if (shift == 2) {
-                        indexScaling = 4;
-                    } else {
-                        indexScaling = 8;
-                    }
-                    offset = leftShiftNode.x();
-                }
-            }
-        }
-        if (signExtend) {
-            // If we were using sign extended values before restore the sign extension.
-            offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64));
-        }
-        return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling);
-    }
-
     private static boolean addReadBarrier(UnsafeLoadNode load) {
         if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getKind() == Kind.Object && load.accessKind() == Kind.Object &&
                         !StampTool.isObjectAlwaysNull(load.object())) {
@@ -825,7 +392,9 @@
         return metaspaceMethod;
     }
 
-    private ValueNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) {
+    @Override
+    protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard) {
+        Kind wordKind = target.wordKind;
         HotSpotVMConfig config = runtime.getConfig();
         LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
@@ -858,7 +427,9 @@
         return graph.add(new WriteNode(object, writeValue, location, BarrierType.NONE, false));
     }
 
-    private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) {
+    @Override
+    protected BarrierType fieldLoadBarrierType(ResolvedJavaField f) {
+        HotSpotResolvedJavaField loadField = (HotSpotResolvedJavaField) f;
         BarrierType barrierType = BarrierType.NONE;
         if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) {
             barrierType = BarrierType.PRECISE;
@@ -866,144 +437,32 @@
         return barrierType;
     }
 
-    private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) {
-        if (storeField.field().getKind() == Kind.Object) {
-            return BarrierType.IMPRECISE;
-        }
-        return BarrierType.NONE;
-    }
-
-    private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) {
-        if (store.elementKind() == Kind.Object) {
-            return BarrierType.PRECISE;
-        }
-        return BarrierType.NONE;
-    }
-
-    private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) {
-        if (store.value().getKind() == Kind.Object) {
-            ResolvedJavaType type = StampTool.typeOrNull(store.object());
-            if (type != null && !type.isArray()) {
-                return BarrierType.IMPRECISE;
-            } else {
-                return BarrierType.PRECISE;
-            }
-        }
-        return BarrierType.NONE;
-    }
-
-    private static BarrierType getCompareAndSwapBarrierType(CompareAndSwapNode cas) {
-        if (cas.expected().getKind() == Kind.Object) {
-            ResolvedJavaType type = StampTool.typeOrNull(cas.object());
-            if (type != null && !type.isArray()) {
-                return BarrierType.IMPRECISE;
-            } else {
-                return BarrierType.PRECISE;
-            }
-        }
-        return BarrierType.NONE;
-    }
-
-    private static BarrierType getAtomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) {
-        if (n.newValue().getKind() == Kind.Object) {
-            ResolvedJavaType type = StampTool.typeOrNull(n.object());
-            if (type != null && !type.isArray()) {
-                return BarrierType.IMPRECISE;
-            } else {
-                return BarrierType.PRECISE;
-            }
-        }
-        return BarrierType.NONE;
-    }
-
-    protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) {
-        LocationIdentity loc = initialization ? INIT_LOCATION : field;
-        return ConstantLocationNode.create(loc, field.getKind(), field.offset(), graph);
-    }
-
-    public int getScalingFactor(Kind kind) {
-        if (useCompressedOops() && kind == Kind.Object) {
-            return this.runtime.getTarget().getSizeInBytes(Kind.Int);
-        } else {
-            return this.runtime.getTarget().getSizeInBytes(kind);
-        }
+    @Override
+    protected int fieldOffset(ResolvedJavaField f) {
+        HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f;
+        return field.offset();
     }
 
     @Override
-    public IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) {
-        LocationIdentity loc = initialization ? INIT_LOCATION : NamedLocationIdentity.getArrayLocation(elementKind);
-        int scale = getScalingFactor(elementKind);
-        return IndexedLocationNode.create(loc, elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
+    public int arrayScalingFactor(Kind kind) {
+        if (useCompressedOops() && kind == Kind.Object) {
+            return this.runtime.getTarget().getSizeInBytes(Kind.Int);
+        }
+        return super.arrayScalingFactor(kind);
     }
 
     @Override
-    public ValueNode reconstructArrayIndex(LocationNode location) {
-        Kind elementKind = location.getValueKind();
-        assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind));
-
-        long base;
-        ValueNode index;
-        int scale = getScalingFactor(elementKind);
-
-        if (location instanceof ConstantLocationNode) {
-            base = ((ConstantLocationNode) location).getDisplacement();
-            index = null;
-        } else if (location instanceof IndexedLocationNode) {
-            IndexedLocationNode indexedLocation = (IndexedLocationNode) location;
-            assert indexedLocation.getIndexScaling() == scale;
-            base = indexedLocation.getDisplacement();
-            index = indexedLocation.getIndex();
-        } else {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
-        base -= getArrayBaseOffset(elementKind);
-        assert base >= 0 && base % scale == 0;
-
-        base /= scale;
-        assert NumUtil.isInt(base);
-
-        StructuredGraph graph = location.graph();
-        if (index == null) {
-            return ConstantNode.forInt((int) base, graph);
-        } else {
-            if (base == 0) {
-                return index;
-            } else {
-                return IntegerArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index);
-            }
-        }
+    protected int arrayBaseOffset(Kind kind) {
+        return HotSpotGraalRuntime.getArrayBaseOffset(kind);
     }
 
-    private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
-        StructuredGraph g = n.graph();
-        ValueNode array = n.array();
-        ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection());
-        if (arrayLength == null) {
-            Stamp stamp = StampFactory.positiveInt();
-            ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false));
-            g.addBeforeFixed(n, readArrayLength);
-            readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool));
-            arrayLength = readArrayLength;
-        }
-
-        if (arrayLength.isConstant() && n.index().isConstant()) {
-            int l = arrayLength.asConstant().asInt();
-            int i = n.index().asConstant().asInt();
-            if (i >= 0 && i < l) {
-                // unneeded range check
-                return null;
-            }
-        }
-
-        return tool.createGuard(n, g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile);
+    @Override
+    protected int arrayLengthOffset() {
+        return config().arrayLengthOffset;
     }
 
-    private static GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) {
-        if (StampTool.isObjectNonNull(object)) {
-            return null;
-        }
-        return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
+    @Override
+    protected LocationIdentity initLocationIdentity() {
+        return INIT_LOCATION;
     }
-
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Sat May 24 10:48:18 2014 -0700
@@ -36,7 +36,7 @@
 
     void initialize(HotSpotProviders providers, HotSpotVMConfig config);
 
-    int getScalingFactor(Kind kind);
+    int arrayScalingFactor(Kind kind);
 
     IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Sat May 24 10:48:18 2014 -0700
@@ -196,7 +196,7 @@
             return null;
         }
         if (code == null && holder.isLinked()) {
-            code = runtime().getCompilerToVM().initializeBytecode(metaspaceMethod);
+            code = runtime().getCompilerToVM().getBytecode(metaspaceMethod);
             assert code.length == getCodeSize() : "expected: " + getCodeSize() + ", actual: " + code.length;
         }
         return code;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Sat May 24 10:48:18 2014 -0700
@@ -416,7 +416,7 @@
             ConstantNode hub = ConstantNode.forConstant(arrayType.klass(), providers.getMetaAccess(), graph);
             final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind);
             HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
-            int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind));
+            int log2ElementSize = CodeUtil.log2(lowerer.arrayScalingFactor(elementKind));
 
             Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("hub", hub);
--- a/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java	Sat May 24 10:48:18 2014 -0700
@@ -54,7 +54,7 @@
      */
     private static final boolean DEBUG = true;
 
-    private static final String LOGFILE = "/tmp/hotspotvmconfigprocessor.log";
+    private static final String LOGFILE = new File(System.getProperty("java.io.tmpdir"), "hotspotvmconfigprocessor.log").getPath();
 
     private static PrintWriter log;
 
@@ -109,7 +109,7 @@
 
     //@formatter:off
     String[] prologue = new String[]{
-        "// The normal wrappers boolAt and intxAt skip constant flags",
+        "// The normal wrappers CommandLineFlags::boolAt and CommandLineFlags::intxAt skip constant flags",
         "static bool boolAt(char* name, bool* value) {",
         "  Flag* result = Flag::find_flag(name, strlen(name), true, true);",
         "  if (result == NULL) return false;",
@@ -157,12 +157,12 @@
             out.println();
 
             Set<String> fieldTypes = new HashSet<>();
-            for (String key : annotations.keySet()) {
-                fieldTypes.add(annotations.get(key).getType());
+            for (VMConfigField key : annotations.values()) {
+                fieldTypes.add(key.getType());
             }
             // For each type of field, generate a switch on the length of the symbol and then do a
             // direct compare. In general this reduces each operation to 2 tests plus a string
-            // compare. Being more prefect than that is probably not worth it.
+            // compare. Being more perfect than that is probably not worth it.
             for (String type : fieldTypes) {
                 String sigtype = type.equals("boolean") ? "bool" : type;
                 out.println("    if (fs.signature() == vmSymbols::" + sigtype + "_signature()) {");
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Sat May 24 10:48:18 2014 -0700
@@ -141,13 +141,15 @@
         protected MetaAccessProvider metaAccessProvider;
         protected String emitName;
         protected int codeBufferPos = -1;
+        private final boolean emitInfopoint;
 
-        public DeoptimizeOp(Value actionAndReason, LIRFrameState frameState, String emitName, MetaAccessProvider metaAccessProvider) {
+        public DeoptimizeOp(Value actionAndReason, LIRFrameState frameState, String emitName, boolean emitInfopoint, MetaAccessProvider metaAccessProvider) {
             super(Value.ILLEGAL);   // return with no ret value
             this.actionAndReason = actionAndReason;
             this.frameState = frameState;
             this.emitName = emitName;
             this.metaAccessProvider = metaAccessProvider;
+            this.emitInfopoint = emitInfopoint;
         }
 
         @Override
@@ -181,8 +183,12 @@
             masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
             masm.emitJumpToLabelName(masm.getDeoptLabelName());
 
-            // now record the debuginfo
-            crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.IMPLICIT_EXCEPTION);
+            // Now record the debuginfo. If HSAIL deoptimization is off,
+            // no debuginfo is emitted and the kernel will return without
+            // a deoptimization.
+            if (emitInfopoint) {
+                crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.IMPLICIT_EXCEPTION);
+            }
         }
 
         public LIRFrameState getFrameState() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Sat May 24 10:48:18 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
@@ -481,30 +482,23 @@
             AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next();
             AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next();
             MergeNode merge = trueEnd.merge();
-            if (merge == falseEnd.merge() && merge.forwardEndCount() == 2 && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) {
+            if (merge == falseEnd.merge() && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) {
                 Iterator<PhiNode> phis = merge.phis().iterator();
                 if (!phis.hasNext()) {
-                    // empty if construct with no phis: remove it
-                    removeEmptyIf(tool);
+                    tool.addToWorkList(condition());
+                    removeThroughFalseBranch(tool);
                     return true;
                 } else {
                     PhiNode singlePhi = phis.next();
                     if (!phis.hasNext()) {
                         // one phi at the merge of an otherwise empty if construct: try to convert
                         // into a MaterializeNode
-                        boolean inverted = trueEnd == merge.forwardEndAt(1);
-                        ValueNode trueValue = singlePhi.valueAt(inverted ? 1 : 0);
-                        ValueNode falseValue = singlePhi.valueAt(inverted ? 0 : 1);
-                        if (trueValue.getKind() != falseValue.getKind()) {
-                            return false;
-                        }
-                        if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) {
-                            return false;
-                        }
+                        ValueNode trueValue = singlePhi.valueAt(trueEnd);
+                        ValueNode falseValue = singlePhi.valueAt(falseEnd);
                         ConditionalNode conditional = canonicalizeConditionalCascade(trueValue, falseValue);
                         if (conditional != null) {
-                            graph().replaceFloating(singlePhi, conditional);
-                            removeEmptyIf(tool);
+                            singlePhi.setValueAt(trueEnd, conditional);
+                            removeThroughFalseBranch(tool);
                             return true;
                         }
                     }
@@ -518,12 +512,6 @@
             ValueNode falseValue = falseEnd.result();
             ConditionalNode conditional = null;
             if (trueValue != null) {
-                if (trueValue.getKind() != falseValue.getKind()) {
-                    return false;
-                }
-                if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) {
-                    return false;
-                }
                 conditional = canonicalizeConditionalCascade(trueValue, falseValue);
                 if (conditional == null) {
                     return false;
@@ -537,7 +525,19 @@
         return false;
     }
 
+    protected void removeThroughFalseBranch(SimplifierTool tool) {
+        BeginNode trueBegin = trueSuccessor();
+        graph().removeSplitPropagate(this, trueBegin, tool);
+        tool.addToWorkList(trueBegin);
+    }
+
     private ConditionalNode canonicalizeConditionalCascade(ValueNode trueValue, ValueNode falseValue) {
+        if (trueValue.getKind() != falseValue.getKind()) {
+            return null;
+        }
+        if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) {
+            return null;
+        }
         if (trueValue.isConstant() && falseValue.isConstant()) {
             return graph().unique(new ConditionalNode(condition(), trueValue, falseValue));
         } else {
@@ -703,6 +703,18 @@
         connectEnds(falseEnds, phiValues, oldFalseSuccessor, merge, tool);
         connectEnds(trueEnds, phiValues, oldTrueSuccessor, merge, tool);
 
+        if (this.trueSuccessorProbability == 0.0) {
+            for (AbstractEndNode endNode : trueEnds) {
+                propagateZeroProbability(endNode);
+            }
+        }
+
+        if (this.trueSuccessorProbability == 1.0) {
+            for (AbstractEndNode endNode : falseEnds) {
+                propagateZeroProbability(endNode);
+            }
+        }
+
         /*
          * Remove obsolete ends only after processing all ends, otherwise oldTrueSuccessor or
          * oldFalseSuccessor might have been removed if it is a LoopExitNode.
@@ -724,6 +736,42 @@
         return true;
     }
 
+    private void propagateZeroProbability(FixedNode startNode) {
+        Node prev = null;
+        for (FixedNode node : GraphUtil.predecessorIterable(startNode)) {
+            if (node instanceof IfNode) {
+                IfNode ifNode = (IfNode) node;
+                if (ifNode.trueSuccessor() == prev) {
+                    if (ifNode.trueSuccessorProbability == 0.0) {
+                        return;
+                    } else if (ifNode.trueSuccessorProbability == 1.0) {
+                        continue;
+                    } else {
+                        ifNode.setTrueSuccessorProbability(0.0);
+                        return;
+                    }
+                } else if (ifNode.falseSuccessor() == prev) {
+                    if (ifNode.trueSuccessorProbability == 1.0) {
+                        return;
+                    } else if (ifNode.trueSuccessorProbability == 0.0) {
+                        continue;
+                    } else {
+                        ifNode.setTrueSuccessorProbability(1.0);
+                        return;
+                    }
+                } else {
+                    throw new GraalInternalError("Illegal state");
+                }
+            } else if (node instanceof MergeNode && !(node instanceof LoopBeginNode)) {
+                for (AbstractEndNode endNode : ((MergeNode) node).cfgPredecessors()) {
+                    propagateZeroProbability(endNode);
+                }
+                return;
+            }
+            prev = node;
+        }
+    }
+
     private static boolean checkFrameState(FixedNode start) {
         FixedNode node = start;
         while (true) {
@@ -835,38 +883,4 @@
 
         return null;
     }
-
-    private void removeEmptyIf(SimplifierTool tool) {
-        BeginNode originalTrueSuccessor = trueSuccessor();
-        BeginNode originalFalseSuccessor = falseSuccessor();
-        assert originalTrueSuccessor.next() instanceof AbstractEndNode && originalFalseSuccessor.next() instanceof AbstractEndNode;
-
-        AbstractEndNode trueEnd = (AbstractEndNode) originalTrueSuccessor.next();
-        AbstractEndNode falseEnd = (AbstractEndNode) originalFalseSuccessor.next();
-        assert trueEnd.merge() == falseEnd.merge();
-
-        FixedWithNextNode pred = (FixedWithNextNode) predecessor();
-        MergeNode merge = trueEnd.merge();
-        merge.prepareDelete(pred);
-        assert merge.usages().isEmpty();
-        originalTrueSuccessor.prepareDelete();
-        originalFalseSuccessor.prepareDelete();
-
-        FixedNode next = merge.next();
-        FrameState state = merge.stateAfter();
-        merge.setNext(null);
-        setTrueSuccessor(null);
-        setFalseSuccessor(null);
-        pred.setNext(next);
-        safeDelete();
-        originalTrueSuccessor.safeDelete();
-        originalFalseSuccessor.safeDelete();
-        merge.safeDelete();
-        trueEnd.safeDelete();
-        falseEnd.safeDelete();
-        if (state != null) {
-            tool.removeIfUnused(state);
-        }
-        tool.addToWorkList(next);
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Sat May 24 10:48:18 2014 -0700
@@ -82,6 +82,10 @@
         values().set(i, x);
     }
 
+    public void setValueAt(AbstractEndNode end, ValueNode x) {
+        setValueAt(merge().phiPredecessorIndex(end), x);
+    }
+
     public ValueNode valueAt(AbstractEndNode pred) {
         return valueAt(merge().phiPredecessorIndex(pred));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Sat May 24 10:48:18 2014 -0700
@@ -27,6 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
@@ -303,6 +304,10 @@
     }
 
     public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) {
+        removeSplitPropagate(node, survivingSuccessor, null);
+    }
+
+    public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor, SimplifierTool tool) {
         assert node != null;
         assert node.usages().isEmpty();
         assert survivingSuccessor != null;
@@ -313,7 +318,7 @@
         for (Node successor : snapshot) {
             if (successor != null && successor.isAlive()) {
                 if (successor != survivingSuccessor) {
-                    GraphUtil.killCFG(successor);
+                    GraphUtil.killCFG(successor, tool);
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Sat May 24 10:48:18 2014 -0700
@@ -61,7 +61,7 @@
 
     protected ControlFlowGraph(StructuredGraph graph) {
         this.graph = graph;
-        this.nodeToBlock = graph.createNodeMap(true);
+        this.nodeToBlock = graph.createNodeMap();
     }
 
     public List<Block> getBlocks() {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Sat May 24 10:48:18 2014 -0700
@@ -189,7 +189,9 @@
                                 GraphUtil.tryKillUnused(valueNode);
                             } else if (improvedStamp) {
                                 // the improved stamp may enable additional canonicalization
-                                tryCanonicalize(valueNode, nodeClass);
+                                if (!tryCanonicalize(valueNode, nodeClass)) {
+                                    valueNode.usages().forEach(workList::add);
+                                }
                             }
                         }
                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Sat May 24 10:48:18 2014 -0700
@@ -710,7 +710,9 @@
                     if (nonNull) {
                         replacementAnchor = searchAnchor(GraphUtil.unproxify(object), type);
                     }
-                    replacementAnchor = BeginNode.prevBegin(checkCast);
+                    if (replacementAnchor == null) {
+                        replacementAnchor = BeginNode.prevBegin(checkCast);
+                    }
                     PiNode piNode;
                     if (isNull) {
                         ConstantNode nullObject = ConstantNode.defaultForKind(Kind.Object, graph);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Sat May 24 10:34:43 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common;
-
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.phases.*;
-
-public class ReadEliminationPhase extends Phase {
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) {
-            if (isReadEliminable(n)) {
-                NodeMap<ValueNode> nodeMap = n.graph().createNodeMap();
-                ValueNode value = getValue(n, n.getLastLocationAccess(), nodeMap);
-                Debug.log("Eliminated memory read %1.1s and replaced with node %s", n, value);
-                graph.replaceFloating(n, value);
-            }
-        }
-    }
-
-    private static boolean isReadEliminable(FloatingReadNode n) {
-        return isWrites(n, n.getLastLocationAccess(), n.graph().createNodeBitMap());
-    }
-
-    private static boolean isWrites(FloatingReadNode n, MemoryNode lastLocationAccess, NodeBitMap visited) {
-        if (lastLocationAccess == null) {
-            return false;
-        }
-        if (visited.isMarked(ValueNodeUtil.asNode(lastLocationAccess))) {
-            return true; // dataflow loops must come from Phis assume them ok until proven wrong
-        }
-        if (lastLocationAccess instanceof ProxyNode) {
-            return isWrites(n, (MemoryNode) ((ProxyNode) lastLocationAccess).value(), visited);
-        }
-        if (lastLocationAccess instanceof WriteNode) {
-            WriteNode other = (WriteNode) lastLocationAccess;
-            return other.object() == n.object() && other.location() == n.location();
-        }
-        if (lastLocationAccess instanceof MemoryPhiNode) {
-            visited.mark(ValueNodeUtil.asNode(lastLocationAccess));
-            for (ValueNode value : ((MemoryPhiNode) lastLocationAccess).values()) {
-                if (!isWrites(n, (MemoryNode) value, visited)) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        return false;
-    }
-
-    private static ValueNode getValue(FloatingReadNode n, MemoryNode lastLocationAccess, NodeMap<ValueNode> nodeMap) {
-        ValueNode exisiting = nodeMap.get(ValueNodeUtil.asNode(lastLocationAccess));
-        if (exisiting != null) {
-            return exisiting;
-        }
-        if (lastLocationAccess instanceof MemoryProxyNode) {
-            MemoryProxyNode proxy = (MemoryProxyNode) lastLocationAccess;
-            ValueNode value = getValue(n, proxy.getOriginalMemoryNode(), nodeMap);
-            return ProxyNode.forValue(value, proxy.proxyPoint(), proxy.graph());
-        }
-        if (lastLocationAccess instanceof WriteNode) {
-            return ((WriteNode) lastLocationAccess).value();
-        }
-        if (lastLocationAccess instanceof MemoryPhiNode) {
-            MemoryPhiNode phi = (MemoryPhiNode) lastLocationAccess;
-            ValuePhiNode newPhi = phi.graph().addWithoutUnique(new ValuePhiNode(n.stamp().unrestricted(), phi.merge()));
-            nodeMap.set(phi, newPhi);
-            for (ValueNode value : phi.values()) {
-                newPhi.addInput(getValue(n, (MemoryNode) value, nodeMap));
-            }
-            return newPhi;
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Sat May 24 10:48:18 2014 -0700
@@ -332,13 +332,13 @@
             assert concretes.size() > 0;
             Debug.log("Method check cascade with %d methods", concretes.size());
 
-            ValueNode[] constantMethods = new ValueNode[concretes.size()];
+            ConstantNode[] constantMethods = new ConstantNode[concretes.size()];
             double[] probability = new double[concretes.size()];
             for (int i = 0; i < concretes.size(); ++i) {
                 ResolvedJavaMethod firstMethod = concretes.get(i);
                 Constant firstMethodConstant = firstMethod.getEncoding();
 
-                ValueNode firstMethodConstantNode = ConstantNode.forConstant(firstMethodConstant, metaAccess, graph);
+                ConstantNode firstMethodConstantNode = ConstantNode.forConstant(firstMethodConstant, metaAccess, graph);
                 constantMethods[i] = firstMethodConstantNode;
                 double concretesProbability = concretesProbabilities.get(i);
                 assert concretesProbability >= 0.0;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java	Sat May 24 10:48:18 2014 -0700
@@ -51,23 +51,23 @@
 
     public CallsiteHolder(StructuredGraph graph, double probability, double relevance) {
         this.graph = graph;
-        if (graph == null) {
-            this.remainingInvokes = new LinkedList<>();
-        } else {
-            LinkedList<Invoke> invokes = new InliningIterator(graph).apply();
-            assert invokes.size() == count(graph.getInvokes());
-            this.remainingInvokes = invokes;
-        }
         this.probability = probability;
         this.relevance = relevance;
-
-        if (graph != null && !remainingInvokes.isEmpty()) {
-            probabilities = new FixedNodeProbabilityCache();
-            computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities);
-            computeProbabilities();
-        } else {
+        if (graph == null) {
+            remainingInvokes = new LinkedList<>();
             probabilities = null;
             computeInliningRelevance = null;
+        } else {
+            remainingInvokes = new InliningIterator(graph).apply();
+            assert remainingInvokes.size() == count(graph.getInvokes());
+            if (remainingInvokes.isEmpty()) {
+                probabilities = null;
+                computeInliningRelevance = null;
+            } else {
+                probabilities = new FixedNodeProbabilityCache();
+                computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities);
+                computeProbabilities();
+            }
         }
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Sat May 24 10:48:18 2014 -0700
@@ -264,11 +264,6 @@
                 }
             }
 
-            if (concreteMethods.size() > maxMethodPerInlining) {
-                InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining);
-                return null;
-            }
-
             // Clear methods that fall below the threshold.
             if (notRecordedTypeProbability > 0) {
                 ArrayList<ResolvedJavaMethod> newConcreteMethods = new ArrayList<>();
@@ -280,7 +275,7 @@
                     }
                 }
 
-                if (newConcreteMethods.size() == 0) {
+                if (newConcreteMethods.isEmpty()) {
                     // No method left that is worth inlining.
                     InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "no methods remaining after filtering less frequent methods (%d methods previously)",
                                     concreteMethods.size());
@@ -291,6 +286,11 @@
                 concreteMethodsProbabilities = newConcreteMethodsProbabilities;
             }
 
+            if (concreteMethods.size() > maxMethodPerInlining) {
+                InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining);
+                return null;
+            }
+
             // Clean out types whose methods are no longer available.
             ArrayList<JavaTypeProfile.ProfiledType> usedTypes = new ArrayList<>();
             ArrayList<Integer> typesToConcretes = new ArrayList<>();
@@ -306,7 +306,7 @@
                 }
             }
 
-            if (usedTypes.size() == 0) {
+            if (usedTypes.isEmpty()) {
                 // No type left that is worth checking for.
                 InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "no types remaining after filtering less frequent types (%d types previously)", ptypes.length);
                 return null;
@@ -410,17 +410,7 @@
             double invokeProbability = callsiteHolder.invokeProbability(invoke);
             double invokeRelevance = callsiteHolder.invokeRelevance(invoke);
             MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance);
-            pushInvocation(methodInvocation);
-
-            for (int i = 0; i < info.numberOfMethods(); i++) {
-                Inlineable elem = info.inlineableElementAt(i);
-                if (elem instanceof InlineableGraph) {
-                    pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i));
-                } else {
-                    assert elem instanceof InlineableMacroNode;
-                    pushDummyGraph();
-                }
-            }
+            pushInvocationAndGraphs(methodInvocation);
         }
     }
 
@@ -449,6 +439,7 @@
 
     private void pushDummyGraph() {
         graphQueue.push(DUMMY_CALLSITE_HOLDER);
+        assert graphQueue.size() <= maxGraphs;
     }
 
     public boolean hasUnprocessedGraphs() {
@@ -492,10 +483,22 @@
         return invocationQueue.peekFirst();
     }
 
-    private void pushInvocation(MethodInvocation methodInvocation) {
+    private void pushInvocationAndGraphs(MethodInvocation methodInvocation) {
         invocationQueue.addFirst(methodInvocation);
-        maxGraphs += methodInvocation.callee().numberOfMethods();
+        InlineInfo info = methodInvocation.callee();
+        maxGraphs += info.numberOfMethods();
         assert graphQueue.size() <= maxGraphs;
+        double invokeProbability = methodInvocation.probability();
+        double invokeRelevance = methodInvocation.relevance();
+        for (int i = 0; i < info.numberOfMethods(); i++) {
+            Inlineable elem = info.inlineableElementAt(i);
+            if (elem instanceof InlineableGraph) {
+                pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i));
+            } else {
+                assert elem instanceof InlineableMacroNode;
+                pushDummyGraph();
+            }
+        }
     }
 
     private void popInvocation() {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Sat May 24 10:48:18 2014 -0700
@@ -42,10 +42,14 @@
     private final Map<FixedNode, Double> cache = newIdentityMap();
 
     public double applyAsDouble(FixedNode node) {
+        assert node != null;
         metricComputeNodeProbability.increment();
 
         FixedNode current = node;
         while (true) {
+            if (current == null) {
+                return 1D;
+            }
             Node predecessor = current.predecessor();
             if (current instanceof BeginNode) {
                 if (predecessor == null) {
@@ -54,6 +58,9 @@
                     assert predecessor instanceof ControlSplitNode : "a FixedNode with multiple successors needs to be a ControlSplitNode: " + current + " / " + predecessor;
                     break;
                 }
+            } else if (predecessor == null) {
+                // this should only appear for dead code
+                return 1D;
             }
             current = (FixedNode) predecessor;
         }
@@ -70,10 +77,8 @@
                 if (current instanceof LoopBeginNode) {
                     probability *= ((LoopBeginNode) current).loopFrequency();
                 }
-            } else if (current instanceof StartNode) {
-                probability = 1D;
             } else {
-                // this should only appear for dead code
+                assert current instanceof StartNode;
                 probability = 1D;
             }
         } else {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Sat May 24 10:48:18 2014 -0700
@@ -34,8 +34,13 @@
 
     public static class LoopInfo<StateT> {
 
-        public final List<StateT> endStates = new ArrayList<>();
-        public final List<StateT> exitStates = new ArrayList<>();
+        public final List<StateT> endStates;
+        public final List<StateT> exitStates;
+
+        public LoopInfo(int endCount, int exitCount) {
+            endStates = new ArrayList<>(endCount);
+            exitStates = new ArrayList<>(exitCount);
+        }
     }
 
     public abstract static class BlockIteratorClosure<StateT> {
@@ -58,8 +63,8 @@
     public static <StateT> LoopInfo<StateT> processLoop(BlockIteratorClosure<StateT> closure, Loop<Block> loop, StateT initialState) {
         Map<FixedNode, StateT> blockEndStates = apply(closure, loop.getHeader(), initialState, new HashSet<>(loop.getBlocks()));
 
-        LoopInfo<StateT> info = new LoopInfo<>();
         List<Block> predecessors = loop.getHeader().getPredecessors();
+        LoopInfo<StateT> info = new LoopInfo<>(predecessors.size() - 1, loop.getExits().size());
         for (int i = 1; i < predecessors.size(); i++) {
             StateT endState = blockEndStates.get(predecessors.get(i).getEndNode());
             // make sure all end states are unique objects
@@ -67,7 +72,7 @@
         }
         for (Block loopExit : loop.getExits()) {
             assert loopExit.getPredecessorCount() == 1;
-            assert blockEndStates.containsKey(loopExit.getBeginNode());
+            assert blockEndStates.containsKey(loopExit.getBeginNode()) : loopExit.getBeginNode() + " " + blockEndStates;
             StateT exitState = blockEndStates.get(loopExit.getBeginNode());
             // make sure all exit states are unique objects
             info.exitStates.add(closure.cloneState(exitState));
@@ -90,7 +95,9 @@
         Block current = start;
 
         while (true) {
-            if (boundary == null || boundary.contains(current)) {
+            if (boundary != null && !boundary.contains(current)) {
+                states.put(current.getBeginNode(), state);
+            } else {
                 state = closure.processBlock(current, state);
 
                 if (current.getSuccessors().isEmpty()) {
@@ -117,45 +124,47 @@
                                 blockQueue.addFirst(exit);
                             }
                         }
-                    } else {
-                        if (successor.getBeginNode() instanceof LoopExitNode) {
-                            assert successor.getPredecessors().size() == 1;
-                            states.put(successor.getBeginNode(), state);
+                    } else if (current.getEndNode() instanceof AbstractEndNode) {
+                        assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode();
+                        AbstractEndNode end = (AbstractEndNode) current.getEndNode();
+
+                        // add the end node and see if the merge is ready for processing
+                        MergeNode merge = end.merge();
+                        boolean endsVisited = true;
+                        for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
+                            if (forwardEnd != current.getEndNode() && !states.containsKey(forwardEnd)) {
+                                endsVisited = false;
+                                break;
+                            }
+                        }
+                        if (endsVisited) {
+                            ArrayList<StateT> mergedStates = new ArrayList<>(merge.forwardEndCount());
+                            for (Block predecessor : successor.getPredecessors()) {
+                                assert predecessor == current || states.containsKey(predecessor.getEndNode());
+                                StateT endState = predecessor == current ? state : states.remove(predecessor.getEndNode());
+                                mergedStates.add(endState);
+                            }
+                            state = closure.merge(successor, mergedStates);
                             current = successor;
                             continue;
                         } else {
-                            if (current.getEndNode() instanceof AbstractEndNode) {
-                                assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode();
-                                AbstractEndNode end = (AbstractEndNode) current.getEndNode();
-
-                                // add the end node and see if the merge is ready for processing
-                                assert !states.containsKey(end);
-                                states.put(end, state);
-                                MergeNode merge = end.merge();
-                                boolean endsVisited = true;
-                                for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
-                                    if (!states.containsKey(forwardEnd)) {
-                                        endsVisited = false;
-                                        break;
-                                    }
-                                }
-                                if (endsVisited) {
-                                    blockQueue.addFirst(successor);
-                                }
-                            } else {
-                                assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode();
-                                current = successor;
-                                continue;
-                            }
+                            assert !states.containsKey(end);
+                            states.put(end, state);
                         }
+                    } else {
+                        assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode();
+                        current = successor;
+                        continue;
                     }
                 } else {
                     assert current.getSuccessors().size() > 1;
-                    for (int i = 0; i < current.getSuccessors().size(); i++) {
+                    for (int i = 1; i < current.getSuccessors().size(); i++) {
                         Block successor = current.getSuccessors().get(i);
                         blockQueue.addFirst(successor);
-                        states.put(successor.getBeginNode(), i == 0 ? state : closure.cloneState(state));
+                        states.put(successor.getBeginNode(), closure.cloneState(state));
                     }
+                    current = current.getSuccessors().get(0);
+                    continue;
                 }
             }
 
@@ -164,20 +173,9 @@
                 return states;
             } else {
                 current = blockQueue.removeFirst();
-                if (current.getPredecessors().size() == 1) {
-                    assert states.containsKey(current.getBeginNode());
-                    state = states.get(current.getBeginNode());
-                } else {
-                    assert current.getPredecessors().size() > 1;
-                    MergeNode merge = (MergeNode) current.getBeginNode();
-                    ArrayList<StateT> mergedStates = new ArrayList<>(merge.forwardEndCount());
-                    for (Block predecessor : current.getPredecessors()) {
-                        AbstractEndNode end = (AbstractEndNode) predecessor.getEndNode();
-                        mergedStates.add(states.get(end));
-                    }
-                    state = closure.merge(current, mergedStates);
-                    states.put(merge, state);
-                }
+                assert current.getPredecessorCount() == 1;
+                assert states.containsKey(current.getBeginNode());
+                state = states.remove(current.getBeginNode());
             }
         }
     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Sat May 24 10:48:18 2014 -0700
@@ -33,8 +33,13 @@
 
     public static class LoopInfo<StateT> {
 
-        public final Map<LoopEndNode, StateT> endStates = newNodeIdentityMap(4);
-        public final Map<LoopExitNode, StateT> exitStates = newNodeIdentityMap(2);
+        public final Map<LoopEndNode, StateT> endStates;
+        public final Map<LoopExitNode, StateT> exitStates;
+
+        public LoopInfo(int endCount, int exitCount) {
+            endStates = newNodeIdentityMap(endCount);
+            exitStates = newNodeIdentityMap(exitCount);
+        }
     }
 
     public abstract static class NodeIteratorClosure<StateT> {
@@ -64,7 +69,7 @@
     public static <StateT> LoopInfo<StateT> processLoop(NodeIteratorClosure<StateT> closure, LoopBeginNode loop, StateT initialState) {
         Map<FixedNode, StateT> blockEndStates = apply(closure, loop, initialState, loop);
 
-        LoopInfo<StateT> info = new LoopInfo<>();
+        LoopInfo<StateT> info = new LoopInfo<>(loop.loopEnds().count(), loop.loopExits().count());
         for (LoopEndNode end : loop.loopEnds()) {
             if (blockEndStates.containsKey(end)) {
                 info.endStates.put(end, blockEndStates.get(end));
@@ -119,11 +124,9 @@
                                     nodeQueue.add(entry.getKey());
                                 }
                             } else {
-                                assert !blockEndStates.containsKey(current);
-                                blockEndStates.put(current, state);
                                 boolean endsVisited = true;
                                 for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
-                                    if (!blockEndStates.containsKey(forwardEnd)) {
+                                    if (forwardEnd != current && !blockEndStates.containsKey(forwardEnd)) {
                                         endsVisited = false;
                                         break;
                                     }
@@ -132,13 +135,16 @@
                                     ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount());
                                     for (int i = 0; i < merge.forwardEndCount(); i++) {
                                         AbstractEndNode forwardEnd = merge.forwardEndAt(i);
-                                        assert blockEndStates.containsKey(forwardEnd);
-                                        StateT other = blockEndStates.get(forwardEnd);
+                                        assert forwardEnd == current || blockEndStates.containsKey(forwardEnd);
+                                        StateT other = forwardEnd == current ? state : blockEndStates.remove(forwardEnd);
                                         states.add(other);
                                     }
                                     state = closure.merge(merge, states);
                                     current = closure.continueIteration(state) ? merge : null;
                                     continue;
+                                } else {
+                                    assert !blockEndStates.containsKey(current);
+                                    blockEndStates.put(current, state);
                                 }
                             }
                         }
@@ -148,14 +154,15 @@
                             current = firstSuccessor;
                             continue;
                         } else {
-                            while (successors.hasNext()) {
+                            do {
                                 BeginNode successor = (BeginNode) successors.next();
                                 StateT successorState = closure.afterSplit(successor, state);
                                 if (closure.continueIteration(successorState)) {
                                     blockEndStates.put(successor, successorState);
                                     nodeQueue.add(successor);
                                 }
-                            }
+                            } while (successors.hasNext());
+
                             state = closure.afterSplit((BeginNode) firstSuccessor, state);
                             current = closure.continueIteration(state) ? firstSuccessor : null;
                             continue;
@@ -169,7 +176,8 @@
                 return blockEndStates;
             } else {
                 current = nodeQueue.removeFirst();
-                state = blockEndStates.get(current);
+                assert blockEndStates.containsKey(current);
+                state = blockEndStates.remove(current);
                 assert !(current instanceof MergeNode) && current instanceof BeginNode;
             }
         } while (true);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Sat May 24 10:48:18 2014 -0700
@@ -0,0 +1,691 @@
+/*
+ * 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
+ * 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.replacements;
+
+import static com.oracle.graal.api.code.MemoryBarriers.*;
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.nodes.java.ArrayLengthNode.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
+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.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.util.*;
+
+/**
+ * VM-independent lowerings for standard Java nodes. VM-specific methods are abstract and must be
+ * implemented by VM-specific subclasses.
+ */
+public abstract class DefaultJavaLoweringProvider implements LoweringProvider {
+
+    protected final MetaAccessProvider metaAccess;
+    protected final TargetDescription target;
+
+    private BoxingSnippets.Templates boxingSnippets;
+
+    public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, TargetDescription target) {
+        this.metaAccess = metaAccess;
+        this.target = target;
+    }
+
+    public void initialize(Providers providers, SnippetReflectionProvider snippetReflection) {
+        boxingSnippets = new BoxingSnippets.Templates(providers, snippetReflection, target);
+    }
+
+    @Override
+    public void lower(Node n, LoweringTool tool) {
+        if (n instanceof LoadFieldNode) {
+            lowerLoadFieldNode((LoadFieldNode) n, tool);
+        } else if (n instanceof StoreFieldNode) {
+            lowerStoreFieldNode((StoreFieldNode) n, tool);
+        } else if (n instanceof LoadIndexedNode) {
+            lowerLoadIndexedNode((LoadIndexedNode) n, tool);
+        } else if (n instanceof StoreIndexedNode) {
+            lowerStoreIndexedNode((StoreIndexedNode) n, tool);
+        } else if (n instanceof ArrayLengthNode) {
+            lowerArrayLengthNode((ArrayLengthNode) n, tool);
+        } else if (n instanceof LoadHubNode) {
+            lowerLoadHubNode((LoadHubNode) n);
+        } else if (n instanceof CompareAndSwapNode) {
+            lowerCompareAndSwapNode((CompareAndSwapNode) n);
+        } else if (n instanceof AtomicReadAndWriteNode) {
+            lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n);
+        } else if (n instanceof UnsafeLoadNode) {
+            lowerUnsafeLoadNode((UnsafeLoadNode) n, tool);
+        } else if (n instanceof UnsafeStoreNode) {
+            lowerUnsafeStoreNode((UnsafeStoreNode) n);
+        } else if (n instanceof JavaReadNode) {
+            lowerJavaReadNode((JavaReadNode) n);
+        } else if (n instanceof JavaWriteNode) {
+            lowerJavaWriteNode((JavaWriteNode) n);
+        } else if (n instanceof CommitAllocationNode) {
+            lowerCommitAllocationNode((CommitAllocationNode) n, tool);
+        } else if (n instanceof BoxNode) {
+            boxingSnippets.lower((BoxNode) n, tool);
+        } else if (n instanceof UnboxNode) {
+            boxingSnippets.lower((UnboxNode) n, tool);
+        } else {
+            throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n);
+        }
+    }
+
+    protected void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) {
+        assert loadField.getKind() != Kind.Illegal;
+        StructuredGraph graph = loadField.graph();
+        ResolvedJavaField field = loadField.field();
+        ValueNode object = loadField.isStatic() ? staticFieldBase(graph, field) : loadField.object();
+        Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind(), true);
+        ConstantLocationNode location = createFieldLocation(graph, field, false);
+        assert location != null : "Field that is loaded must not be eliminated";
+
+        ReadNode memoryRead = graph.add(new ReadNode(object, location, loadStamp, fieldLoadBarrierType(field), false));
+        ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead);
+        loadField.replaceAtUsages(readValue);
+        graph.replaceFixed(loadField, memoryRead);
+
+        memoryRead.setGuard(createNullCheck(object, memoryRead, tool));
+
+        if (loadField.isVolatile()) {
+            MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ));
+            graph.addBeforeFixed(memoryRead, preMembar);
+            MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ));
+            graph.addAfterFixed(memoryRead, postMembar);
+        }
+    }
+
+    protected void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) {
+        StructuredGraph graph = storeField.graph();
+        ResolvedJavaField field = storeField.field();
+        ValueNode object = storeField.isStatic() ? staticFieldBase(graph, field) : storeField.object();
+        ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value());
+        ConstantLocationNode location = createFieldLocation(graph, field, false);
+
+        if (location == null) {
+            /* Field has been eliminated, so no write necessary. */
+            assert !storeField.isVolatile() : "missing memory barriers";
+            graph.removeFixed(storeField);
+            return;
+        }
+        WriteNode memoryWrite = graph.add(new WriteNode(object, value, location, fieldStoreBarrierType(storeField.field()), false));
+        memoryWrite.setStateAfter(storeField.stateAfter());
+        graph.replaceFixedWithFixed(storeField, memoryWrite);
+        memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool));
+
+        if (storeField.isVolatile()) {
+            MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
+            graph.addBeforeFixed(memoryWrite, preMembar);
+            MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
+            graph.addAfterFixed(memoryWrite, postMembar);
+        }
+    }
+
+    protected void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) {
+        StructuredGraph graph = loadIndexed.graph();
+        Kind elementKind = loadIndexed.elementKind();
+        LocationNode location = createArrayLocation(graph, elementKind, loadIndexed.index(), false);
+        Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind, true);
+
+        ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), location, loadStamp, BarrierType.NONE, false));
+        ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead);
+
+        memoryRead.setGuard(createBoundsCheck(loadIndexed, tool));
+
+        loadIndexed.replaceAtUsages(readValue);
+        graph.replaceFixed(loadIndexed, memoryRead);
+    }
+
+    protected void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) {
+        StructuredGraph graph = storeIndexed.graph();
+        GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool);
+        Kind elementKind = storeIndexed.elementKind();
+        LocationNode location = createArrayLocation(graph, elementKind, storeIndexed.index(), false);
+
+        ValueNode value = storeIndexed.value();
+        ValueNode array = storeIndexed.array();
+        FixedWithNextNode checkCastNode = null;
+        if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) {
+            /* Array store check. */
+            ResolvedJavaType arrayType = StampTool.typeOrNull(array);
+            if (arrayType != null && StampTool.isExactType(array)) {
+                ResolvedJavaType elementType = arrayType.getComponentType();
+                if (!MetaUtil.isJavaLangObject(elementType)) {
+                    checkCastNode = graph.add(new CheckCastNode(elementType, value, null, true));
+                    graph.addBeforeFixed(storeIndexed, checkCastNode);
+                    value = checkCastNode;
+                }
+            } else {
+                ValueNode arrayClass = createReadHub(graph, array, boundsCheck);
+                ValueNode componentHub = createReadArrayComponentHub(graph, arrayClass, storeIndexed);
+                checkCastNode = graph.add(new CheckCastDynamicNode(componentHub, value, true));
+                graph.addBeforeFixed(storeIndexed, checkCastNode);
+                value = checkCastNode;
+            }
+        }
+
+        WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), location, arrayStoreBarrierType(storeIndexed.elementKind()), false));
+        memoryWrite.setGuard(boundsCheck);
+        memoryWrite.setStateAfter(storeIndexed.stateAfter());
+        graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
+
+        if (checkCastNode instanceof Lowerable) {
+            /* Recursive lowering of the store check node. */
+            ((Lowerable) checkCastNode).lower(tool);
+        }
+    }
+
+    protected void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) {
+        StructuredGraph graph = arrayLengthNode.graph();
+        ValueNode array = arrayLengthNode.array();
+        ConstantLocationNode location = ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph);
+
+        ReadNode arrayLengthRead = graph.add(new ReadNode(array, location, StampFactory.positiveInt(), BarrierType.NONE, false));
+        arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool));
+        graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
+    }
+
+    protected void lowerLoadHubNode(LoadHubNode loadHub) {
+        StructuredGraph graph = loadHub.graph();
+        if (graph.getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) {
+            return;
+        }
+        ValueNode hub = createReadHub(graph, loadHub.object(), loadHub.getGuard());
+        graph.replaceFloating(loadHub, hub);
+    }
+
+    protected void lowerCompareAndSwapNode(CompareAndSwapNode cas) {
+        StructuredGraph graph = cas.graph();
+        Kind valueKind = cas.getValueKind();
+        LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), valueKind, cas.displacement(), cas.offset(), graph, 1);
+
+        ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected());
+        ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue());
+
+        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, compareAndSwapBarrierType(cas), false));
+        atomicNode.setStateAfter(cas.stateAfter());
+        graph.replaceFixedWithFixed(cas, atomicNode);
+    }
+
+    protected void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) {
+        StructuredGraph graph = n.graph();
+        Kind valueKind = n.getValueKind();
+        LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1);
+
+        ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
+
+        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, atomicReadAndWriteBarrierType(n), false));
+        memoryRead.setStateAfter(n.stateAfter());
+
+        ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead);
+        n.replaceAtUsages(readValue);
+        graph.replaceFixedWithFixed(n, memoryRead);
+    }
+
+    protected void lowerUnsafeLoadNode(UnsafeLoadNode load, @SuppressWarnings("unused") LoweringTool tool) {
+        StructuredGraph graph = load.graph();
+        if (load.getGuardingCondition() != null) {
+            ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition()));
+            ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode);
+            graph.replaceFixedWithFixed(load, valueAnchorNode);
+            graph.addAfterFixed(valueAnchorNode, memoryRead);
+        } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) {
+            assert load.getKind() != Kind.Illegal;
+            ReadNode memoryRead = createUnsafeRead(graph, load, null);
+            // An unsafe read must not float outside its block otherwise
+            // it may float above an explicit null check on its object.
+            memoryRead.setGuard(BeginNode.prevBegin(load));
+            graph.replaceFixedWithFixed(load, memoryRead);
+        }
+    }
+
+    protected ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) {
+        boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
+        Kind readKind = load.accessKind();
+        LocationNode location = createLocation(load);
+        Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible);
+        ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE, false));
+        ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible);
+        load.replaceAtUsages(readValue);
+        return memoryRead;
+    }
+
+    protected void lowerUnsafeStoreNode(UnsafeStoreNode store) {
+        StructuredGraph graph = store.graph();
+        LocationNode location = createLocation(store);
+        ValueNode object = store.object();
+        boolean compressible = store.value().getKind() == Kind.Object;
+        Kind valueKind = store.accessKind();
+        ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible);
+        WriteNode write = graph.add(new WriteNode(object, value, location, unsafeStoreBarrierType(store), false));
+        write.setStateAfter(store.stateAfter());
+        graph.replaceFixedWithFixed(store, write);
+    }
+
+    protected void lowerJavaReadNode(JavaReadNode read) {
+        StructuredGraph graph = read.graph();
+        Kind valueKind = read.location().getValueKind();
+        Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible());
+
+        ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType(), false));
+        ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible());
+        memoryRead.setGuard(read.getGuard());
+        read.replaceAtUsages(readValue);
+        graph.replaceFixed(read, memoryRead);
+    }
+
+    protected void lowerJavaWriteNode(JavaWriteNode write) {
+        StructuredGraph graph = write.graph();
+        Kind valueKind = write.location().getValueKind();
+        ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible());
+
+        WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), false, write.isInitialization()));
+        memoryWrite.setStateAfter(write.stateAfter());
+        graph.replaceFixedWithFixed(write, memoryWrite);
+        memoryWrite.setGuard(write.getGuard());
+    }
+
+    protected void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) {
+        StructuredGraph graph = commit.graph();
+        if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+            List<AbstractNewObjectNode> recursiveLowerings = new ArrayList<>();
+
+            ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
+            BitSet omittedValues = new BitSet();
+            int valuePos = 0;
+            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
+                int entryCount = virtual.entryCount();
+                AbstractNewObjectNode newObject;
+                if (virtual instanceof VirtualInstanceNode) {
+                    newObject = graph.add(new NewInstanceNode(virtual.type(), true));
+                } else {
+                    newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true));
+                }
+                recursiveLowerings.add(newObject);
+                graph.addBeforeFixed(commit, newObject);
+                allocations[objIndex] = newObject;
+                for (int i = 0; i < entryCount; i++) {
+                    ValueNode value = commit.getValues().get(valuePos);
+                    if (value instanceof VirtualObjectNode) {
+                        value = allocations[commit.getVirtualObjects().indexOf(value)];
+                    }
+                    if (value == null) {
+                        omittedValues.set(valuePos);
+                    } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
+                        // Constant.illegal is always the defaultForKind, so it is skipped
+                        Kind valueKind = value.getKind();
+                        Kind entryKind = virtual.entryKind(i);
+
+                        // Truffle requires some leniency in terms of what can be put where:
+                        Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind;
+                        assert valueKind.getStackKind() == entryKind.getStackKind() ||
+                                        (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode));
+                        ConstantLocationNode location = null;
+                        BarrierType barrierType = null;
+                        if (virtual instanceof VirtualInstanceNode) {
+                            ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i);
+                            long offset = fieldOffset(field);
+                            if (offset >= 0) {
+                                location = ConstantLocationNode.create(initLocationIdentity(), accessKind, offset, graph);
+                                barrierType = fieldInitializationBarrier(entryKind);
+                            }
+                        } else {
+                            location = ConstantLocationNode.create(initLocationIdentity(), accessKind, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind), graph);
+                            barrierType = arrayInitializationBarrier(entryKind);
+                        }
+                        if (location != null) {
+                            WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType, false);
+                            graph.addAfterFixed(newObject, graph.add(write));
+                        }
+                    }
+                    valuePos++;
+
+                }
+            }
+            valuePos = 0;
+
+            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
+                int entryCount = virtual.entryCount();
+                ValueNode newObject = allocations[objIndex];
+                for (int i = 0; i < entryCount; i++) {
+                    if (omittedValues.get(valuePos)) {
+                        ValueNode value = commit.getValues().get(valuePos);
+                        assert value instanceof VirtualObjectNode;
+                        ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)];
+                        if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) {
+                            assert virtual.entryKind(i) == Kind.Object && allocValue.getKind() == Kind.Object;
+                            LocationNode location;
+                            BarrierType barrierType;
+                            if (virtual instanceof VirtualInstanceNode) {
+                                VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
+                                location = createFieldLocation(graph, virtualInstance.field(i), true);
+                                barrierType = BarrierType.IMPRECISE;
+                            } else {
+                                location = createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), true);
+                                barrierType = BarrierType.PRECISE;
+                            }
+                            if (location != null) {
+                                WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), location, barrierType, false);
+                                graph.addBeforeFixed(commit, graph.add(write));
+                            }
+                        }
+                    }
+                    valuePos++;
+                }
+            }
+
+            finishAllocatedObjects(tool, commit, allocations);
+            graph.removeFixed(commit);
+
+            for (AbstractNewObjectNode recursiveLowering : recursiveLowerings) {
+                recursiveLowering.lower(tool);
+            }
+        }
+    }
+
+    public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) {
+        StructuredGraph graph = commit.graph();
+        for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+            FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
+            allocations[objIndex] = anchor;
+            graph.addBeforeFixed(commit, anchor);
+        }
+        for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+            for (MonitorIdNode monitorId : commit.getLocks(objIndex)) {
+                MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId));
+                graph.addBeforeFixed(commit, enter);
+                enter.lower(tool);
+            }
+        }
+        for (Node usage : commit.usages().snapshot()) {
+            AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
+            int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
+            graph.replaceFloating(addObject, allocations[index]);
+        }
+    }
+
+    protected BarrierType fieldLoadBarrierType(@SuppressWarnings("unused") ResolvedJavaField field) {
+        return BarrierType.NONE;
+    }
+
+    protected BarrierType fieldStoreBarrierType(ResolvedJavaField field) {
+        if (field.getKind() == Kind.Object) {
+            return BarrierType.IMPRECISE;
+        }
+        return BarrierType.NONE;
+    }
+
+    protected BarrierType arrayStoreBarrierType(Kind elementKind) {
+        if (elementKind == Kind.Object) {
+            return BarrierType.PRECISE;
+        }
+        return BarrierType.NONE;
+    }
+
+    protected BarrierType fieldInitializationBarrier(Kind entryKind) {
+        return entryKind == Kind.Object ? BarrierType.IMPRECISE : BarrierType.NONE;
+    }
+
+    protected BarrierType arrayInitializationBarrier(Kind entryKind) {
+        return entryKind == Kind.Object ? BarrierType.PRECISE : BarrierType.NONE;
+    }
+
+    protected BarrierType unsafeStoreBarrierType(UnsafeStoreNode store) {
+        return storeBarrierType(store.object(), store.value());
+    }
+
+    protected BarrierType compareAndSwapBarrierType(CompareAndSwapNode cas) {
+        return storeBarrierType(cas.object(), cas.expected());
+    }
+
+    protected BarrierType atomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) {
+        return storeBarrierType(n.object(), n.newValue());
+    }
+
+    protected BarrierType storeBarrierType(ValueNode object, ValueNode value) {
+        if (value.getKind() == Kind.Object) {
+            ResolvedJavaType type = StampTool.typeOrNull(object);
+            if (type != null && !type.isArray()) {
+                return BarrierType.IMPRECISE;
+            } else {
+                return BarrierType.PRECISE;
+            }
+        }
+        return BarrierType.NONE;
+    }
+
+    protected abstract int fieldOffset(ResolvedJavaField field);
+
+    protected abstract ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField field);
+
+    protected abstract int arrayLengthOffset();
+
+    protected abstract int arrayBaseOffset(Kind elementKind);
+
+    public int arrayScalingFactor(Kind elementKind) {
+        return target.getSizeInBytes(elementKind);
+    }
+
+    protected abstract LocationIdentity initLocationIdentity();
+
+    protected Stamp loadStamp(Stamp stamp, Kind kind, @SuppressWarnings("unused") boolean compressible) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+                return StampTool.narrowingConversion(stamp, 8);
+            case Char:
+            case Short:
+                return StampTool.narrowingConversion(stamp, 16);
+        }
+        return stamp;
+    }
+
+    public ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value) {
+        return implicitLoadConvert(graph, kind, value, true);
+
+    }
+
+    protected ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) {
+        switch (kind) {
+            case Byte:
+            case Short:
+                return graph.unique(new SignExtendNode(value, 32));
+            case Boolean:
+            case Char:
+                return graph.unique(new ZeroExtendNode(value, 32));
+        }
+        return value;
+    }
+
+    public ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value) {
+        return implicitStoreConvert(graph, kind, value, true);
+    }
+
+    protected ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+                return graph.unique(new NarrowNode(value, 8));
+            case Char:
+            case Short:
+                return graph.unique(new NarrowNode(value, 16));
+        }
+        return value;
+    }
+
+    protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard);
+
+    protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor);
+
+    protected ConstantLocationNode createFieldLocation(StructuredGraph graph, ResolvedJavaField field, boolean initialization) {
+        int offset = fieldOffset(field);
+        if (offset >= 0) {
+            LocationIdentity loc = initialization ? initLocationIdentity() : field;
+            return ConstantLocationNode.create(loc, field.getKind(), offset, graph);
+        } else {
+            return null;
+        }
+    }
+
+    protected LocationNode createLocation(UnsafeAccessNode access) {
+        return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind());
+    }
+
+    protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) {
+        ValueNode offset = offsetNode;
+        if (offset.isConstant()) {
+            long offsetValue = offset.asConstant().asLong();
+            return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph());
+        }
+
+        long displacement = 0;
+        int indexScaling = 1;
+        boolean signExtend = false;
+        if (offset instanceof SignExtendNode) {
+            SignExtendNode extend = (SignExtendNode) offset;
+            if (extend.getResultBits() == 64) {
+                signExtend = true;
+                offset = extend.getInput();
+            }
+        }
+        if (offset instanceof IntegerAddNode) {
+            IntegerAddNode integerAddNode = (IntegerAddNode) offset;
+            if (integerAddNode.y() instanceof ConstantNode) {
+                displacement = integerAddNode.y().asConstant().asLong();
+                offset = integerAddNode.x();
+            }
+        }
+
+        if (offset instanceof LeftShiftNode) {
+            LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
+            if (leftShiftNode.y() instanceof ConstantNode) {
+                long shift = leftShiftNode.y().asConstant().asLong();
+                if (shift >= 1 && shift <= 3) {
+                    if (shift == 1) {
+                        indexScaling = 2;
+                    } else if (shift == 2) {
+                        indexScaling = 4;
+                    } else {
+                        indexScaling = 8;
+                    }
+                    offset = leftShiftNode.x();
+                }
+            }
+        }
+        if (signExtend) {
+            // If we were using sign extended values before restore the sign extension.
+            offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64));
+        }
+        return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling);
+    }
+
+    public IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) {
+        LocationIdentity loc = initialization ? initLocationIdentity() : NamedLocationIdentity.getArrayLocation(elementKind);
+        return IndexedLocationNode.create(loc, elementKind, arrayBaseOffset(elementKind), index, graph, arrayScalingFactor(elementKind));
+    }
+
+    protected GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
+        StructuredGraph graph = n.graph();
+        ValueNode array = n.array();
+        ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection());
+        if (arrayLength == null) {
+            Stamp stamp = StampFactory.positiveInt();
+            ReadNode readArrayLength = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE, false));
+            graph.addBeforeFixed(n, readArrayLength);
+            readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool));
+            arrayLength = readArrayLength;
+        }
+
+        if (arrayLength.isConstant() && n.index().isConstant()) {
+            int l = arrayLength.asConstant().asInt();
+            int i = n.index().asConstant().asInt();
+            if (i >= 0 && i < l) {
+                // unneeded range check
+                return null;
+            }
+        }
+
+        return tool.createGuard(n, graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile);
+    }
+
+    protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) {
+        if (StampTool.isObjectNonNull(object)) {
+            return null;
+        }
+        return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
+    }
+
+    @Override
+    public ValueNode reconstructArrayIndex(LocationNode location) {
+        Kind elementKind = location.getValueKind();
+        assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind));
+
+        long base;
+        ValueNode index;
+        int scale = arrayScalingFactor(elementKind);
+
+        if (location instanceof ConstantLocationNode) {
+            base = ((ConstantLocationNode) location).getDisplacement();
+            index = null;
+        } else if (location instanceof IndexedLocationNode) {
+            IndexedLocationNode indexedLocation = (IndexedLocationNode) location;
+            assert indexedLocation.getIndexScaling() == scale;
+            base = indexedLocation.getDisplacement();
+            index = indexedLocation.getIndex();
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        base -= arrayBaseOffset(elementKind);
+        assert base >= 0 && base % scale == 0;
+
+        base /= scale;
+        assert NumUtil.isInt(base);
+
+        StructuredGraph graph = location.graph();
+        if (index == null) {
+            return ConstantNode.forInt((int) base, graph);
+        } else {
+            if (base == 0) {
+                return index;
+            } else {
+                return IntegerArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index);
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Sat May 24 10:48:18 2014 -0700
@@ -57,7 +57,7 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (object.isConstant() && !object.isNullConstant() && offset.isConstant()) {
+        if (object.isConstant() && !object.isNullConstant() && offset.isConstant() && condition.isConstant() && condition.asConstant().asInt() == 1) {
             Constant constant = tool.getConstantReflection().readUnsafeConstant(accessKind, object.asConstant(), offset.asConstant().asLong());
             return ConstantNode.forConstant(constant, tool.getMetaAccess(), graph());
         }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Sat May 24 10:48:18 2014 -0700
@@ -25,6 +25,7 @@
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
@@ -32,7 +33,7 @@
 public class EarlyReadEliminationPhase extends EffectsPhase<PhaseContext> {
 
     public EarlyReadEliminationPhase(CanonicalizerPhase canonicalizer) {
-        super(1, canonicalizer);
+        super(1, canonicalizer, true);
     }
 
     @Override
@@ -43,7 +44,8 @@
     }
 
     @Override
-    protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule) {
-        return new ReadEliminationClosure(schedule);
+    protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) {
+        assert schedule == null;
+        return new ReadEliminationClosure(cfg);
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Sat May 24 10:48:18 2014 -0700
@@ -42,6 +42,7 @@
 
 public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
 
+    private final ControlFlowGraph cfg;
     private final SchedulePhase schedule;
 
     protected final NodeMap<ValueNode> aliases;
@@ -51,11 +52,12 @@
 
     private boolean changed;
 
-    public EffectsClosure(SchedulePhase schedule) {
+    public EffectsClosure(SchedulePhase schedule, ControlFlowGraph cfg) {
         this.schedule = schedule;
-        this.aliases = schedule.getCFG().graph.createNodeMap();
-        this.blockEffects = new BlockMap<>(schedule.getCFG());
-        for (Block block : schedule.getCFG().getBlocks()) {
+        this.cfg = cfg;
+        this.aliases = cfg.graph.createNodeMap();
+        this.blockEffects = new BlockMap<>(cfg);
+        for (Block block : cfg.getBlocks()) {
             blockEffects.put(block, new GraphEffectList());
         }
     }
@@ -67,7 +69,7 @@
 
     @Override
     public void applyEffects() {
-        final StructuredGraph graph = schedule.getCFG().graph;
+        final StructuredGraph graph = cfg.graph;
         final ArrayList<Node> obsoleteNodes = new ArrayList<>(0);
         BlockIteratorClosure<Void> closure = new BlockIteratorClosure<Void>() {
 
@@ -114,7 +116,7 @@
                 return info.exitStates;
             }
         };
-        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
+        ReentrantBlockIterator.apply(closure, cfg.getStartBlock());
         assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
     }
 
@@ -124,7 +126,8 @@
 
         GraphEffectList effects = blockEffects.get(block);
         FixedWithNextNode lastFixedNode = null;
-        for (Node node : schedule.getBlockToNodesMap().get(block)) {
+        Iterable<? extends Node> nodes = schedule != null ? schedule.getBlockToNodesMap().get(block) : block.getNodes();
+        for (Node node : nodes) {
             aliases.set(node, null);
             if (node instanceof LoopExitNode) {
                 LoopExitNode loopExit = (LoopExitNode) node;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Sat May 24 10:48:18 2014 -0700
@@ -31,6 +31,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.common.util.*;
@@ -49,10 +50,16 @@
 
     private final int maxIterations;
     protected final CanonicalizerPhase canonicalizer;
+    private final boolean unscheduled;
 
-    public EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) {
+    protected EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) {
+        this(maxIterations, canonicalizer, false);
+    }
+
+    protected EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer, boolean unscheduled) {
         this.maxIterations = maxIterations;
         this.canonicalizer = canonicalizer;
+        this.unscheduled = unscheduled;
     }
 
     @Override
@@ -64,10 +71,19 @@
         boolean changed = false;
         for (int iteration = 0; iteration < maxIterations; iteration++) {
             try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) {
-                SchedulePhase schedule = new SchedulePhase();
-                schedule.apply(graph, false);
-                Closure<?> closure = createEffectsClosure(context, schedule);
-                ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
+                SchedulePhase schedule;
+                ControlFlowGraph cfg;
+                if (unscheduled) {
+                    schedule = null;
+                    cfg = ControlFlowGraph.compute(graph, true, true, false, false);
+                } else {
+                    schedule = new SchedulePhase();
+                    schedule.apply(graph, false);
+                    cfg = schedule.getCFG();
+                }
+
+                Closure<?> closure = createEffectsClosure(context, schedule, cfg);
+                ReentrantBlockIterator.apply(closure, cfg.getStartBlock());
 
                 if (!closure.hasChanged()) {
                     break;
@@ -106,5 +122,5 @@
         }
     }
 
-    protected abstract Closure<?> createEffectsClosure(PhaseContextT context, SchedulePhase schedule);
+    protected abstract Closure<?> createEffectsClosure(PhaseContextT context, SchedulePhase schedule, ControlFlowGraph cfg);
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Sat May 24 10:48:18 2014 -0700
@@ -79,7 +79,7 @@
     }
 
     public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) {
-        super(schedule);
+        super(schedule, schedule.getCFG());
         this.usages = schedule.getCFG().graph.createNodeBitMap();
         this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, assumptions, this);
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Sat May 24 10:48:18 2014 -0700
@@ -30,6 +30,7 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
@@ -84,7 +85,8 @@
     }
 
     @Override
-    protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule) {
+    protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) {
+        assert schedule != null;
         if (readElimination) {
             return new PEReadEliminationClosure(schedule, context.getMetaAccess(), context.getConstantReflection(), context.getAssumptions());
         } else {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Sat May 24 10:48:18 2014 -0700
@@ -132,13 +132,7 @@
     }
 
     public void killReadCache(LocationIdentity identity) {
-        Iterator<Map.Entry<CacheEntry<?>, ValueNode>> iter = readCache.entrySet().iterator();
-        while (iter.hasNext()) {
-            Map.Entry<CacheEntry<?>, ValueNode> entry = iter.next();
-            if (entry.getKey().conflicts(identity)) {
-                iter.remove();
-            }
-        }
+        readCache.entrySet().removeIf(entry -> entry.getKey().conflicts(identity));
     }
 
     public Map<CacheEntry<?>, ValueNode> getReadCache() {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Sat May 24 10:34:43 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Sat May 24 10:48:18 2014 -0700
@@ -34,15 +34,14 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry;
 
 public class ReadEliminationClosure extends EffectsClosure<ReadEliminationBlockState> {
 
-    public ReadEliminationClosure(SchedulePhase schedule) {
-        super(schedule);
+    public ReadEliminationClosure(ControlFlowGraph cfg) {
+        super(null, cfg);
     }
 
     @Override
@@ -53,104 +52,104 @@
     @Override
     protected boolean processNode(Node node, ReadEliminationBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
         boolean deleted = false;
-        if (node instanceof LoadFieldNode) {
-            LoadFieldNode load = (LoadFieldNode) node;
-            if (!load.isVolatile()) {
-                ValueNode object = GraphUtil.unproxify(load.object());
-                LoadCacheEntry identifier = new LoadCacheEntry(object, load.field());
+        if (node instanceof AccessFieldNode) {
+            AccessFieldNode access = (AccessFieldNode) node;
+            if (access.isVolatile()) {
+                processIdentity(state, ANY_LOCATION);
+            } else {
+                ValueNode object = GraphUtil.unproxify(access.object());
+                LoadCacheEntry identifier = new LoadCacheEntry(object, access.field());
                 ValueNode cachedValue = state.getCacheEntry(identifier);
-                if (cachedValue != null) {
-                    effects.replaceAtUsages(load, cachedValue);
-                    addScalarAlias(load, cachedValue);
-                    deleted = true;
+                if (node instanceof LoadFieldNode) {
+                    if (cachedValue != null) {
+                        effects.replaceAtUsages(access, cachedValue);
+                        addScalarAlias(access, cachedValue);
+                        deleted = true;
+                    } else {
+                        state.addCacheEntry(identifier, access);
+                    }
                 } else {
-                    state.addCacheEntry(identifier, load);
+                    assert node instanceof StoreFieldNode;
+                    StoreFieldNode store = (StoreFieldNode) node;
+                    ValueNode value = getScalarAlias(store.value());
+                    if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
+                        effects.deleteFixedNode(store);
+                        deleted = true;
+                    }
+                    state.killReadCache(store.field());
+                    state.addCacheEntry(identifier, value);
+                }
+            }
+        } else if (node instanceof FixedAccessNode) {
+            if (node instanceof ReadNode) {
+                ReadNode read = (ReadNode) node;
+                if (read.location() instanceof ConstantLocationNode) {
+                    ValueNode object = GraphUtil.unproxify(read.object());
+                    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;
+                    } else {
+                        state.addCacheEntry(identifier, read);
+                    }
+                }
+            } else if (node instanceof WriteNode) {
+                WriteNode write = (WriteNode) node;
+                if (write.location() instanceof ConstantLocationNode) {
+                    ValueNode object = GraphUtil.unproxify(write.object());
+                    ReadCacheEntry identifier = new ReadCacheEntry(object, write.location());
+                    ValueNode cachedValue = state.getCacheEntry(identifier);
+
+                    ValueNode value = getScalarAlias(write.value());
+                    if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
+                        effects.deleteFixedNode(write);
+                        deleted = true;
+                    }
+                    processIdentity(state, write.location().getLocationIdentity());
+                    state.addCacheEntry(identifier, value);
+                } else {
+                    processIdentity(state, write.location().getLocationIdentity());
+                }
+            }
+        } else if (node instanceof UnsafeAccessNode) {
+            if (node instanceof UnsafeLoadNode) {
+                UnsafeLoadNode load = (UnsafeLoadNode) node;
+                if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
+                    ValueNode object = GraphUtil.unproxify(load.object());
+                    LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity());
+                    ValueNode cachedValue = state.getCacheEntry(identifier);
+                    if (cachedValue != null) {
+                        effects.replaceAtUsages(load, cachedValue);
+                        addScalarAlias(load, cachedValue);
+                        deleted = true;
+                    } else {
+                        state.addCacheEntry(identifier, load);
+                    }
                 }
             } else {
-                processIdentity(state, ANY_LOCATION);
-            }
-        } else if (node instanceof StoreFieldNode) {
-            StoreFieldNode store = (StoreFieldNode) node;
-            if (!store.isVolatile()) {
-                ValueNode object = GraphUtil.unproxify(store.object());
-                LoadCacheEntry identifier = new LoadCacheEntry(object, store.field());
-                ValueNode cachedValue = state.getCacheEntry(identifier);
+                assert node instanceof UnsafeStoreNode;
+                UnsafeStoreNode write = (UnsafeStoreNode) node;
+                if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
+                    ValueNode object = GraphUtil.unproxify(write.object());
+                    LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity());
+                    ValueNode cachedValue = state.getCacheEntry(identifier);
 
-                ValueNode value = getScalarAlias(store.value());
-                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                    effects.deleteFixedNode(store);
-                    deleted = true;
-                }
-                state.killReadCache(store.field());
-                state.addCacheEntry(identifier, value);
-            } else {
-                processIdentity(state, ANY_LOCATION);
-            }
-        } else if (node instanceof ReadNode) {
-            ReadNode read = (ReadNode) node;
-            if (read.location() instanceof ConstantLocationNode) {
-                ValueNode object = GraphUtil.unproxify(read.object());
-                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);
+                    ValueNode value = getScalarAlias(write.value());
+                    if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
+                        effects.deleteFixedNode(write);
+                        deleted = true;
                     }
-                    effects.replaceAtUsages(read, cachedValue);
-                    addScalarAlias(read, cachedValue);
-                    deleted = true;
+                    processIdentity(state, write.getLocationIdentity());
+                    state.addCacheEntry(identifier, value);
                 } else {
-                    state.addCacheEntry(identifier, read);
+                    processIdentity(state, write.getLocationIdentity());
                 }
             }
-        } else if (node instanceof UnsafeLoadNode) {
-            UnsafeLoadNode load = (UnsafeLoadNode) node;
-            if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
-                ValueNode object = GraphUtil.unproxify(load.object());
-                LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity());
-                ValueNode cachedValue = state.getCacheEntry(identifier);
-                if (cachedValue != null) {
-                    effects.replaceAtUsages(load, cachedValue);
-                    addScalarAlias(load, cachedValue);
-                    deleted = true;
-                } else {
-                    state.addCacheEntry(identifier, load);
-                }
-            }
-        } else if (node instanceof WriteNode) {
-            WriteNode write = (WriteNode) node;
-            if (write.location() instanceof ConstantLocationNode) {
-                ValueNode object = GraphUtil.unproxify(write.object());
-                ReadCacheEntry identifier = new ReadCacheEntry(object, write.location());
-                ValueNode cachedValue = state.getCacheEntry(identifier);
-
-                ValueNode value = getScalarAlias(write.value());
-                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                    effects.deleteFixedNode(write);
-                    deleted = true;
-                }
-                processIdentity(state, write.location().getLocationIdentity());
-                state.addCacheEntry(identifier, value);
-            } else {
-                processIdentity(state, write.location().getLocationIdentity());
-            }
-        } else if (node instanceof UnsafeStoreNode) {
-            UnsafeStoreNode write = (UnsafeStoreNode) node;
-            if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
-                ValueNode object = GraphUtil.unproxify(write.object());
-                LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity());
-                ValueNode cachedValue = state.getCacheEntry(identifier);
-
-                ValueNode value = getScalarAlias(write.value());
-                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                    effects.deleteFixedNode(write);
-                    deleted = true;
-                }
-                processIdentity(state, write.getLocationIdentity());
-                state.addCacheEntry(identifier, value);
-            } else {
-                processIdentity(state, write.getLocationIdentity());
-            }
         } else if (node instanceof MemoryCheckpoint.Single) {
             LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
             processIdentity(state, identity);
--- a/mx/mx_graal.py	Sat May 24 10:34:43 2014 -0700
+++ b/mx/mx_graal.py	Sat May 24 10:48:18 2014 -0700
@@ -46,8 +46,8 @@
 """ The VMs that can be built and run along with an optional description. Only VMs with a
     description are listed in the dialogue for setting the default VM (see _get_vm()). """
 _vmChoices = {
-    'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.',
-    'server' : 'Normal compilation is performed with the tiered system (i.e., client + server), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.',
+    'graal' : 'Normal compilation is performed with a tiered system (C1 + Graal), Truffle compilation is performed with Graal.',
+    'server' : 'Normal compilation is performed with a tiered system (C1 + C2), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.',
     'client' : None,  # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal
     'server-nograal' : None,  # all compilation with tiered system (i.e., client + server), Graal omitted
     'client-nograal' : None,  # all compilation with client compiler, Graal omitted
@@ -154,7 +154,7 @@
         def handleRemoveReadonly(func, path, exc):
             excvalue = exc[1]
             if mx.get_os() == 'windows' and func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
-                os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777
+                os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)  # 0777
                 func(path)
             else:
                 raise
@@ -212,7 +212,7 @@
     def _genFileName(archivtype, middle):
         idPrefix = infos['revision'] + '_'
         idSuffix = '.tar.gz'
-        return join(_graal_home, "graalvm_" + archivtype + "_"  + idPrefix + middle + idSuffix)
+        return join(_graal_home, "graalvm_" + archivtype + "_" + idPrefix + middle + idSuffix)
 
     def _genFileArchPlatformName(archivtype, middle):
         return _genFileName(archivtype, infos['platform'] + '_' + infos['architecture'] + '_' + middle)
@@ -484,8 +484,27 @@
         if exists(toDelete):
             os.unlink(toDelete)
 
+def _update_HotSpotOptions_inline_hpp(graalJar):
+    p = mx.project('com.oracle.graal.hotspot')
+    mainClass = 'com.oracle.graal.hotspot.HotSpotOptionsLoader'
+    assert exists(join(p.source_dirs()[0], mainClass.replace('.', os.sep) + '.java'))
+    hsSrcGenDir = join(p.source_gen_dir(), 'hotspot')
+    if not exists(hsSrcGenDir):
+        os.makedirs(hsSrcGenDir)
+    tmp = StringIO.StringIO()
+    retcode = mx.run_java(['-cp', graalJar, mainClass], out=tmp.write, nonZeroIsFatal=False)
+    if retcode != 0:
+        # Suppress the error if it's because the utility class isn't compiled yet
+        with zipfile.ZipFile(graalJar, 'r') as zf:
+            mainClassFile = mainClass.replace('.', '/') + '.class'
+            if mainClassFile not in zf.namelist():
+                return
+        mx.abort(retcode)
+    mx.update_file(join(hsSrcGenDir, 'HotSpotOptions.inline.hpp'), tmp.getvalue())
+
 def _installGraalJarInJdks(graalDist):
     graalJar = graalDist.path
+    _update_HotSpotOptions_inline_hpp(graalJar)
     jdks = _jdksDir()
 
     if exists(jdks):
@@ -690,7 +709,7 @@
             mustBuild = False
             timestamp = os.path.getmtime(timestampFile)
             sources = []
-            for d in ['src', 'make', 'graal/com.oracle.graal.hotspot/src_gen/hotspot']:
+            for d in ['src', 'make', join('graal', 'com.oracle.graal.hotspot', 'src_gen', 'hotspot')]:
                 for root, dirnames, files in os.walk(join(_graal_home, d)):
                     # ignore <graal>/src/share/tools
                     if root == join(_graal_home, 'src', 'share'):
--- a/mxtool/mx.py	Sat May 24 10:34:43 2014 -0700
+++ b/mxtool/mx.py	Sat May 24 10:48:18 2014 -0700
@@ -1514,14 +1514,19 @@
         stderr = err if not callable(err) else subprocess.PIPE
         p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env)
         sub = _addSubprocess(p, args)
+        joiners = []
         if callable(out):
             t = Thread(target=redirect, args=(p.stdout, out))
             # Don't make the reader thread a daemon otherwise output can be droppped
             t.start()
+            joiners.append(t)
         if callable(err):
             t = Thread(target=redirect, args=(p.stderr, err))
             # Don't make the reader thread a daemon otherwise output can be droppped
             t.start()
+            joiners.append(t)
+        for t in joiners:
+            t.join()
         if timeout is None or timeout == 0:
             retcode = waitOn(p)
         else:
@@ -1673,6 +1678,7 @@
         self.javac = exe_suffix(join(self.jdk, 'bin', 'javac'))
         self.javap = exe_suffix(join(self.jdk, 'bin', 'javap'))
         self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc'))
+        self.pack200 = exe_suffix(join(self.jdk, 'bin', 'pack200'))
         self.toolsjar = join(self.jdk, 'lib', 'tools.jar')
         self._bootclasspath = None
         self._extdirs = None
@@ -1847,7 +1853,7 @@
 
     def is_alive(p):
         if isinstance(p, subprocess.Popen):
-            return p.poll() is not None
+            return p.poll() is None
         assert isinstance(p, multiprocessing.Process), p
         return p.is_alive()
 
@@ -3398,13 +3404,12 @@
             for ap in p.annotation_processors():
                 for dep in dependency(ap).all_deps([], True):
                     if dep.isLibrary():
-                        if not hasattr(dep, 'eclipse.container') and not hasattr(dep, 'eclipse.project'):
-                            # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
-                            # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
-                            # safest to simply use absolute paths.
-                            path = _make_absolute(dep.get_path(resolve=True), p.suite.dir)
-                            out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'})
-                            files.append(path)
+                        # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
+                        # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
+                        # safest to simply use absolute paths.
+                        path = _make_absolute(dep.get_path(resolve=True), p.suite.dir)
+                        out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'})
+                        files.append(path)
                     elif dep.isProject():
                         out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
             out.close('factorypath')
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Sat May 24 10:34:43 2014 -0700
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Sat May 24 10:48:18 2014 -0700
@@ -89,12 +89,12 @@
   VMStructs::initHotSpotVMConfig(JNIHandles::resolve(config));
 C2V_END
 
-C2V_VMENTRY(jbyteArray, initializeBytecode, (JNIEnv *, jobject, jlong metaspace_method))
+C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jlong metaspace_method))
   methodHandle method = asMethod(metaspace_method);
   ResourceMark rm;
 
   int code_size = method->code_size();
-  jbyte* reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size);
+  typeArrayOop reconstituted_code = oopFactory::new_byteArray(code_size, CHECK_NULL);
 
   guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten");
   // iterate over all bytecodes and replace non-Java bytecodes
@@ -106,9 +106,9 @@
     int len = s.instruction_size();
 
     // Restore original byte code.
-    reconstituted_code[bci] = (jbyte) (s.is_wide()? Bytecodes::_wide : code);
+    reconstituted_code->byte_at_put(bci, (jbyte) (s.is_wide()? Bytecodes::_wide : code));
     if (len > 1) {
-      memcpy(&reconstituted_code[bci+1], s.bcp()+1, len-1);
+      memcpy(reconstituted_code->byte_at_addr(bci + 1), s.bcp()+1, len-1);
     }
 
     if (len > 1) {
@@ -124,41 +124,39 @@
         case Bytecodes::_invokestatic:
         case Bytecodes::_invokeinterface:
         case Bytecodes::_invokehandle: {
-          int cp_index = Bytes::get_native_u2((address) &reconstituted_code[bci + 1]);
-          Bytes::put_Java_u2((address) &reconstituted_code[bci + 1], (u2) cp_index);
+          int cp_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
+          Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
           break;
         }
 
         case Bytecodes::_invokedynamic:
-          int cp_index = Bytes::get_native_u4((address) &reconstituted_code[bci + 1]);
-          Bytes::put_Java_u4((address) &reconstituted_code[bci + 1], (u4) cp_index);
+          int cp_index = Bytes::get_native_u4((address) reconstituted_code->byte_at_addr(bci + 1));
+          Bytes::put_Java_u4((address) reconstituted_code->byte_at_addr(bci + 1), (u4) cp_index);
           break;
       }
 
       // Not all ldc byte code are rewritten.
       switch (raw_code) {
         case Bytecodes::_fast_aldc: {
-          int cpc_index = reconstituted_code[bci + 1] & 0xff;
+          int cpc_index = reconstituted_code->byte_at(bci + 1) & 0xff;
           int cp_index = method->constants()->object_to_cp_index(cpc_index);
           assert(cp_index < method->constants()->length(), "sanity check");
-          reconstituted_code[bci + 1] = (jbyte) cp_index;
+          reconstituted_code->byte_at_put(bci + 1, (jbyte) cp_index);
           break;
         }
 
         case Bytecodes::_fast_aldc_w: {
-          int cpc_index = Bytes::get_native_u2((address) &reconstituted_code[bci + 1]);
+          int cpc_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
           int cp_index = method->constants()->object_to_cp_index(cpc_index);
           assert(cp_index < method->constants()->length(), "sanity check");
-          Bytes::put_Java_u2((address) &reconstituted_code[bci + 1], (u2) cp_index);
+          Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
           break;
         }
       }
     }
   }
 
-  typeArrayOop result_array = oopFactory::new_byteArray(code_size, CHECK_NULL);
-  memcpy(result_array->byte_at_addr(0), reconstituted_code, code_size);
-  return (jbyteArray) JNIHandles::make_local(result_array);
+  return (jbyteArray) JNIHandles::make_local(reconstituted_code);
 C2V_END
 
 C2V_VMENTRY(jint, exceptionTableLength, (JNIEnv *, jobject, jlong metaspace_method))
@@ -1004,7 +1002,7 @@
 #define METASPACE_SYMBOL      "J"
 
 JNINativeMethod CompilerToVM_methods[] = {
-  {CC"initializeBytecode",                           CC"("METASPACE_METHOD")[B",                                               FN_PTR(initializeBytecode)},
+  {CC"getBytecode",                                  CC"("METASPACE_METHOD")[B",                                               FN_PTR(getBytecode)},
   {CC"exceptionTableStart",                          CC"("METASPACE_METHOD")J",                                                FN_PTR(exceptionTableStart)},
   {CC"exceptionTableLength",                         CC"("METASPACE_METHOD")I",                                                FN_PTR(exceptionTableLength)},
   {CC"hasBalancedMonitors",                          CC"("METASPACE_METHOD")Z",                                                FN_PTR(hasBalancedMonitors)},
--- a/src/share/vm/graal/graalRuntime.cpp	Sat May 24 10:34:43 2014 -0700
+++ b/src/share/vm/graal/graalRuntime.cpp	Sat May 24 10:48:18 2014 -0700
@@ -651,17 +651,166 @@
   GraalRuntime::initialize_natives(env, c2vmClass);
 JVM_END
 
-// private static String[] HotSpotOptions.getVMOptions(boolean[] timeCompilations)
-JVM_ENTRY(jobject, JVM_GetGraalOptions(JNIEnv *env, jclass c, jobject timeCompilations))
+// private static boolean HotSpotOptions.parseVMOptions()
+JVM_ENTRY(jboolean, JVM_ParseGraalOptions(JNIEnv *env, jclass c))
   HandleMark hm;
+  KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c)));
+  return GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false);
+JVM_END
+
+bool GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  // Process option overrides from graal.options first
+  parse_graal_options_file(hotSpotOptionsClass, CHECK_false);
+
+  // Now process options on the command line
   int numOptions = Arguments::num_graal_args();
-  objArrayOop options = oopFactory::new_objArray(SystemDictionary::String_klass(),
-      numOptions, CHECK_NULL);
-  objArrayHandle optionsHandle(THREAD, options);
   for (int i = 0; i < numOptions; i++) {
-    Handle option = java_lang_String::create_from_str(Arguments::graal_args_array()[i], CHECK_NULL);
-    optionsHandle->obj_at_put(i, option());
+    char* arg = Arguments::graal_args_array()[i];
+    parse_argument(hotSpotOptionsClass, arg, CHECK_false);
+  }
+  return CITime || CITimeEach;
+}
+
+void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) {
+  char first = arg[0];
+  char* name;
+  size_t name_len;
+  Handle name_handle;
+  bool valid = true;
+  if (first == '+' || first == '-') {
+    name = arg + 1;
+    name_len = strlen(name);
+    name_handle = java_lang_String::create_from_str(name, CHECK);
+    valid = set_option(hotSpotOptionsClass, name, name_len, name_handle, arg, CHECK);
+  } else {
+    char* sep = strchr(arg, '=');
+    if (sep != NULL) {
+      name = arg;
+      name_len = sep - name;
+      // Temporarily replace '=' with NULL to create the Java string for the option name
+      *sep = '\0';
+      name_handle = java_lang_String::create_from_str(arg, THREAD);
+      *sep = '=';
+      if (HAS_PENDING_EXCEPTION) {
+        return;
+      }
+      valid = set_option(hotSpotOptionsClass, name, name_len, name_handle, sep + 1, CHECK);
+    } else {
+      char buf[200];
+      jio_snprintf(buf, sizeof(buf), "Value for option %s must use '-G:%s=<value>' format", arg, arg);
+      THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
+    }
+  }
+
+  if (!valid) {
+    VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), ' ', Handle(), 0L);
+    char buf[200];
+    jio_snprintf(buf, sizeof(buf), "Invalid Graal option %s", arg);
+    THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
   }
-  ((typeArrayOop) JNIHandles::resolve(timeCompilations))->bool_at_put(0, CITime || CITimeEach);
-  return JNIHandles::make_local(THREAD, optionsHandle());
-JVM_END
+}
+
+void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) {
+  const char* home = Arguments::get_java_home();
+  int path_len = strlen(home) + strlen("/lib/graal.options") + 1;
+  char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
+  char sep = os::file_separator()[0];
+  sprintf(path, "%s%clib%cgraal.options", home, sep, sep);
+
+  struct stat st;
+  if (os::stat(path, &st) == 0) {
+    int file_handle = os::open(path, 0, 0);
+    if (file_handle != -1) {
+      char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size);
+      int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size);
+      if (num_read == -1) {
+        warning("Error reading file %s due to %s", path, strerror(errno));
+      } else if (num_read != st.st_size) {
+        warning("Only read %d of %d bytes from %s", num_read, st.st_size, path);
+      }
+      os::close(file_handle);
+      if (num_read == st.st_size) {
+        char* line = buffer;
+        int lineNo = 1;
+        while (line - buffer < num_read) {
+          char* nl = strchr(line, '\n');
+          if (nl != NULL) {
+            *nl = '\0';
+          }
+          parse_argument(hotSpotOptionsClass, line, THREAD);
+          if (HAS_PENDING_EXCEPTION) {
+            warning("Error in %s:%d", path, lineNo);
+            return;
+          }
+          if (nl != NULL) {
+            line = nl + 1;
+            lineNo++;
+          } else {
+            // File without newline at the end
+            break;
+          }
+        }
+      }
+    } else {
+      warning("Error opening file %s due to %s", path, strerror(errno));
+    }
+  }
+}
+
+jlong GraalRuntime::parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS) {
+  union {
+    jint i;
+    jlong l;
+    double d;
+  } uu;
+  uu.l = 0L;
+  char dummy;
+  switch (spec) {
+    case 'd':
+    case 'f': {
+      if (sscanf(value, "%lf%c", &uu.d, &dummy) == 1) {
+        return uu.l;
+      }
+      break;
+    }
+    case 'i': {
+      if (sscanf(value, "%d%c", &uu.i, &dummy) == 1) {
+        return uu.l;
+      }
+      break;
+    }
+    default:
+      ShouldNotReachHere();
+  }
+  ResourceMark rm(THREAD);
+  char buf[200];
+  jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %s: %s", (spec == 'i' ? "numeric" : "float/double"), java_lang_String::as_utf8_string(name()), value);
+  THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L);
+}
+
+Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) {
+  TempNewSymbol name = SymbolTable::new_symbol(declaringClass, THREAD);
+  Klass* klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NH);
+
+  // The class has been loaded so the field and signature should already be in the symbol
+  // table.  If they're not there, the field doesn't exist.
+  TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName));
+  TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)strlen(fieldSig));
+  if (fieldname == NULL || signame == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle());
+  }
+  // Make sure class is initialized before handing id's out to fields
+  klass->initialize(CHECK_NH);
+
+  fieldDescriptor fd;
+  if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) {
+    THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle());
+  }
+
+  Handle ret = klass->java_mirror()->obj_field(fd.offset());
+  return ret;
+}
+
+#include "HotSpotOptions.inline.hpp"
--- a/src/share/vm/graal/graalRuntime.hpp	Sat May 24 10:34:43 2014 -0700
+++ b/src/share/vm/graal/graalRuntime.hpp	Sat May 24 10:48:18 2014 -0700
@@ -31,12 +31,55 @@
 class GraalRuntime: public CHeapObj<mtCompiler> {
  private:
 
-  static address   _external_deopt_i2c_entry;
+  static address _external_deopt_i2c_entry;
+
+  /**
+   * Reads the OptionValue object from a specified static field.
+   *
+   * @throws LinkageError if the field could not be resolved
+   */
+  static Handle get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS);
+
+  /**
+   * Parses the string form of a numeric, float or double option into a jlong (using raw bits for floats/doubles).
+   *
+   * @param spec 'i', 'f' or 'd' (see HotSpotOptions.setOption())
+   * @param name name option option
+   * @param value string value to parse
+   * @throws InternalError if value could not be parsed according to spec
+   */
+  static jlong parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS);
+
+  /**
+   * Loads default option value overrides from a <jre_home>/lib/graal.options if it exists. Each
+   * line in this file must have the format of a Graal command line option without the
+   * leading "-G:" prefix. These option values are set prior to processing of any Graal
+   * options present on the command line.
+   */
+  static void parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS);
+
+  /**
+   * Parses a given argument and sets the denoted Graal option.
+   *
+   * @throws InternalError if there was a problem parsing or setting the option
+   */
+  static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS);
+
+  /**
+   * Searches for a Graal option denoted by a given name and sets it value.
+   *
+   * @returns true if the option was found
+   * @throws InternalError if there was a problem setting the option's value
+   */
+  static bool set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS);
 
  public:
 
   static void initialize_natives(JNIEnv *env, jclass c2vmClass);
   static BufferBlob* initialize_buffer_blob();
+
+  static bool parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS);
+
   static BasicType kindToBasicType(jchar ch);
   static address create_external_deopt_i2c();
   static address get_external_deopt_i2c_entry() {return _external_deopt_i2c_entry;}
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Sat May 24 10:34:43 2014 -0700
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Sat May 24 10:48:18 2014 -0700
@@ -94,48 +94,20 @@
   return Handle(JNIHandles::resolve_non_null(_VMToCompiler_instance));
 }
 
-void VMToCompiler::initOptions() {
+void VMToCompiler::setOption(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) {
+  assert(!option.is_null(), "npe");
   Thread* THREAD = Thread::current();
-  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD);
-  KlassHandle optionsKlass = loadClass(name);
-  optionsKlass->initialize(THREAD);
-  check_pending_exception("Error while calling initOptions");
-}
-
-jboolean VMToCompiler::setOption(Handle option) {
-  assert(!option.is_null(), "");
-  Thread* THREAD = Thread::current();
-  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD);
   TempNewSymbol setOption = SymbolTable::new_symbol("setOption", THREAD);
-  TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;)Z", THREAD);
-  KlassHandle optionsKlass = loadClass(name);
-  JavaValue result(T_BOOLEAN);
-  JavaCalls::call_static(&result, optionsKlass, setOption, sig, option, THREAD);
-  check_pending_exception("Error while calling setOption");
-  return result.get_jboolean();
-}
-
-void VMToCompiler::finalizeOptions(jboolean ciTime) {
-  Thread* THREAD = Thread::current();
-  TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD);
-  TempNewSymbol finalizeOptions = SymbolTable::new_symbol("finalizeOptions", THREAD);
-  TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;)Z", THREAD);
-  KlassHandle optionsKlass = loadClass(name);
+  TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", THREAD);
   JavaValue result(T_VOID);
   JavaCallArguments args;
-  args.push_int(ciTime);
-  JavaCalls::call_static(&result, optionsKlass, finalizeOptions, vmSymbols::bool_void_signature(), &args, THREAD);
-  check_pending_exception("Error while calling finalizeOptions");
-}
-
-void VMToCompiler::startRuntime() {
-  JavaThread* THREAD = JavaThread::current();
-  JavaValue result(T_VOID);
-  JavaCallArguments args;
-  TempNewSymbol startRuntime = SymbolTable::new_symbol("startRuntime", THREAD);
-  args.push_oop(VMToCompiler_instance());
-  JavaCalls::call_interface(&result, VMToCompiler_klass(), startRuntime, vmSymbols::void_method_signature(), &args, THREAD);
-  check_pending_exception("Error while calling startRuntime");
+  args.push_oop(name());
+  args.push_oop(option());
+  args.push_int(spec);
+  args.push_oop(stringValue());
+  args.push_long(primitiveValue);
+  JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, THREAD);
+  check_pending_exception("Error while calling setOption");
 }
 
 #ifdef COMPILERGRAAL
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Sat May 24 10:34:43 2014 -0700
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Sat May 24 10:48:18 2014 -0700
@@ -55,17 +55,8 @@
     return _HotSpotGraalRuntime_instance;
   }
 
-  // public static boolean HotSpotOptions.<clinit>();
-  static void initOptions();
-
-  // public static boolean HotSpotOptions.setOption(String option);
-  static jboolean setOption(Handle option);
-
-  // public static void HotSpotOptions.finalizeOptions(boolean ciTime);
-  static void finalizeOptions(jboolean ciTime);
-
-  // public abstract void startRuntime();
-  static void startRuntime();
+  // public static void HotSpotOptions.setOption(String name, OptionValue<?> option, char spec, String stringValue, long primitiveValue);
+  static void setOption(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue);
 
 #ifdef COMPILERGRAAL
   // public abstract void startCompiler(boolean bootstrapEnabled);
--- a/src/share/vm/prims/nativeLookup.cpp	Sat May 24 10:34:43 2014 -0700
+++ b/src/share/vm/prims/nativeLookup.cpp	Sat May 24 10:48:18 2014 -0700
@@ -124,10 +124,10 @@
   void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
   void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
 #ifdef GRAAL
-  void    JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass);
-  jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c);
-  jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c);
-  jobject JNICALL JVM_GetGraalOptions(JNIEnv *env, jclass hotspotOptionsClass, jobject timeCompilations);
+  void     JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass);
+  jobject  JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c);
+  jobject  JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c);
+  jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass);
 #endif
 }
 
@@ -140,10 +140,10 @@
   { CC"Java_sun_misc_Perf_registerNatives",                        NULL, FN_PTR(JVM_RegisterPerfMethods)         },
   { CC"Java_sun_hotspot_WhiteBox_registerNatives",                 NULL, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
 #ifdef GRAAL
-  { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime)             },
-  { CC"Java_com_oracle_truffle_api_Truffle_createRuntime",         NULL, FN_PTR(JVM_CreateTruffleRuntime)        },
-  { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init",    NULL, FN_PTR(JVM_InitializeGraalNatives)      },
-  { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_getVMOptions", NULL, FN_PTR(JVM_GetGraalOptions)             },
+  { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime",   NULL, FN_PTR(JVM_GetGraalRuntime)             },
+  { CC"Java_com_oracle_truffle_api_Truffle_createRuntime",           NULL, FN_PTR(JVM_CreateTruffleRuntime)        },
+  { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init",      NULL, FN_PTR(JVM_InitializeGraalNatives)      },
+  { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions)           },
 #endif
 };