changeset 17087:4faf9bdb9973

Merge
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Tue, 09 Sep 2014 14:31:36 -0700
parents 82b5a7250a0d (current diff) 2476180699f6 (diff)
children 6e27f9d92dc5
files src/cpu/sparc/vm/sharedRuntime_sparc.cpp
diffstat 90 files changed, 2379 insertions(+), 489 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Tue Sep 09 12:22:48 2014 -0700
+++ b/CHANGELOG.md	Tue Sep 09 14:31:36 2014 -0700
@@ -6,6 +6,9 @@
 
 ### Truffle
 * Added TruffleRuntime#getCallTargets() to get all call targets that were created and are still referenced.
+* Added `NeverValidAssumption` to complement `AlwaysValidAssumption`.
+* Fixed a bug in `AssumedValue` that may not invalidate correctly.
+* New option, TruffleCompilationExceptionsAreThrown, that will throw a OptimizationFailedException for compiler errors.
 
 ## Version 0.4
 19-Aug-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.4)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MoreThanEightArgsOOBTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+import org.junit.*;
+
+public class MoreThanEightArgsOOBTest extends GraalKernelTester {
+
+    int[] makeIntArray(int size) {
+        int[] out = new int[size];
+
+        for (int i = 0; i < size; i++) {
+            out[i] = 1;
+        }
+        return out;
+    }
+
+    final int rows = 4096;
+    final int cols = 4096;
+    final int loops = 1;
+
+    @Result int[] result;
+
+    void innerTest(int[] res, int[] a, int[] b, int[] c, int[] d, int base, int stride) {
+        final int resCols = a.length;
+        final int resRows = res.length;
+        final int limit = resCols - stride;
+
+        dispatchLambdaKernel(resRows, (row) -> {
+            res[row] = 0;
+            if (a != null) {
+                for (int col = base; col < limit; col += 4) {
+                    int p0 = 0;
+                    int p1 = 0;
+                    int p2 = 0;
+                    int p3 = 0;
+                    p0 = a[col] + b[col] + c[col] + d[col] + stride;
+                    p1 = a[col + 1] + b[col + 1] + c[col + 1] + d[col + 1];
+                    p2 = a[col + 2] + b[col + 2] + c[col + 2] + d[col + 2];
+                    p3 = a[col + 3] + b[col + 3] + c[col + 3] + d[col + 5000];
+                    res[row] += p0 + p1 + p2 + p3;
+                }
+            }
+        });
+    }
+
+    @Override
+    public void runTest() {
+        int[] a;
+        int[] b;
+        int[] c;
+        int[] d;
+
+        result = makeIntArray(rows);
+        a = makeIntArray(cols);
+        b = makeIntArray(cols);
+        c = makeIntArray(cols);
+        d = makeIntArray(cols);
+        for (int i = 0; i < loops; i++) {
+            innerTest(result, a, b, c, d, 0, 4);
+        }
+    }
+
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -269,7 +269,7 @@
             }
             result.append("\n");
             for (Node node : schedule.getBlockToNodesMap().get(block)) {
-                if (node.isAlive() && node.recordsUsages()) {
+                if (node.isAlive()) {
                     if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) {
                         int id;
                         if (canonicalId.get(node) != null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodeRefIteratorTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+
+public class NodeRefIteratorTest extends GraalCompilerTest {
+
+    @NodeInfo
+    static class TestNode extends Node {
+        @Successor Node s1;
+        @Successor Node s2;
+        @Successor NodeSuccessorList<Node> stail;
+
+        @Input NodeInputList<ValueNode> itail;
+        @Input ValueNode i1;
+        @Input ValueNode i2;
+
+        public static TestNode create() {
+            return USE_GENERATED_NODES ? new NodeRefIteratorTest_TestNodeGen() : new TestNode();
+        }
+    }
+
+    @Test
+    public void testInputs() {
+        TestNode n = TestNode.create();
+
+        ConstantNode i1 = ConstantNode.forInt(1);
+        ConstantNode i2 = ConstantNode.forDouble(1.0d);
+        ConstantNode i3 = ConstantNode.forInt(4);
+        ConstantNode i4 = ConstantNode.forInt(14);
+        n.itail = new NodeInputList<>(n, new ValueNode[]{i3, i4});
+        n.i1 = i1;
+        n.i2 = i2;
+
+        NodeClassIterable inputs = n.inputs();
+
+        NodePosIterator iterator = inputs.iterator();
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i1);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i2);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i3);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i4);
+        Assert.assertFalse(iterator.hasNext());
+        Assert.assertFalse(iterator.hasNext());
+
+        iterator = inputs.iterator();
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.nextPosition().toString(), "input 0/-1");
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.nextPosition().toString(), "input 1/-1");
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.nextPosition().toString(), "input 2/0");
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.nextPosition().toString(), "input 2/1");
+        Assert.assertFalse(iterator.hasNext());
+        Assert.assertFalse(iterator.hasNext());
+
+        iterator = inputs.iterator();
+        n.i1 = i4;
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i4);
+        n.i2 = i1;
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i1);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i3);
+        n.itail.initialize(1, i4);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i4);
+        Assert.assertFalse(iterator.hasNext());
+
+        iterator = inputs.iterator();
+        n.i1 = null;
+        n.i2 = i2;
+        n.itail.initialize(0, null);
+        n.itail.initialize(1, i4);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i2);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i4);
+        Assert.assertFalse(iterator.hasNext());
+
+        iterator = inputs.withNullIterator();
+        n.i1 = null;
+        n.i2 = null;
+        n.itail.initialize(0, i3);
+        n.itail.initialize(1, null);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertNull(iterator.next());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertNull(iterator.next());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), i3);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertNull(iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void testSuccessors() {
+        TestNode n = TestNode.create();
+        EndNode s1 = EndNode.create();
+        EndNode s2 = EndNode.create();
+        EndNode s3 = EndNode.create();
+        EndNode s4 = EndNode.create();
+        n.s1 = s1;
+        n.s2 = s2;
+        n.stail = new NodeSuccessorList<>(n, new Node[]{s3, s4});
+
+        NodeClassIterable successors = n.successors();
+        NodePosIterator iterator = successors.iterator();
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s1);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s2);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s3);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s4);
+        Assert.assertFalse(iterator.hasNext());
+        Assert.assertFalse(iterator.hasNext());
+
+        iterator = successors.iterator();
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.nextPosition().toString(), "successor 0/-1");
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.nextPosition().toString(), "successor 1/-1");
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.nextPosition().toString(), "successor 2/0");
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.nextPosition().toString(), "successor 2/1");
+        Assert.assertFalse(iterator.hasNext());
+        Assert.assertFalse(iterator.hasNext());
+
+        iterator = successors.iterator();
+        n.s1 = s4;
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s4);
+        n.s2 = s1;
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s1);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s3);
+        n.stail.initialize(1, s4);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s4);
+        Assert.assertFalse(iterator.hasNext());
+
+        iterator = successors.iterator();
+        n.s1 = null;
+        n.s2 = s2;
+        n.stail.initialize(0, null);
+        n.stail.initialize(1, s4);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s2);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s4);
+        Assert.assertFalse(iterator.hasNext());
+
+        iterator = successors.withNullIterator();
+        n.s1 = null;
+        n.s2 = null;
+        n.stail.initialize(0, s3);
+        n.stail.initialize(1, null);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertNull(iterator.next());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertNull(iterator.next());
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), s3);
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertNull(iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -242,7 +242,7 @@
     }
 
     private static void outputNode(Node node) {
-        TTY.print("  " + node + "    (usage count: " + (node.recordsUsages() ? node.usages().count() : "?") + ") (inputs:");
+        TTY.print("  " + node + "    (usage count: " + node.usages().count() + ") (inputs:");
         for (Node input : node.inputs()) {
             TTY.print(" " + input.toString(Verbosity.Id));
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Sep 09 14:31:36 2014 -0700
@@ -25,6 +25,7 @@
 import static com.oracle.graal.compiler.GraalCompiler.Options.*;
 import static com.oracle.graal.compiler.MethodFilter.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
 
 import java.util.*;
 
@@ -167,7 +168,7 @@
             HighTierContext highTierContext = new HighTierContext(providers, assumptions, cache, graphBuilderSuite, optimisticOpts);
             if (graph.start().next() == null) {
                 graphBuilderSuite.apply(graph, highTierContext);
-                new DeadCodeEliminationPhase().apply(graph);
+                new DeadCodeEliminationPhase(OPTIONAL).apply(graph);
             } else {
                 Debug.dump(graph, "initial state");
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Sep 09 14:31:36 2014 -0700
@@ -894,15 +894,26 @@
                 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 = intervalFor(operandNum).operand;
-                        Debug.log("var %d; operand=%s; node=%s", operandNum, operand, getValueForOperandFromDebugContext(operand));
+                        Interval interval = intervalFor(operandNum);
+                        if (interval != null) {
+                            Value operand = interval.operand;
+                            Debug.log("var %d; operand=%s; node=%s", operandNum, operand, getValueForOperandFromDebugContext(operand));
+                        } else {
+                            Debug.log("var %d; missing operand", operandNum);
+                        }
                     }
                 }
 
                 // print some additional information to simplify debugging
                 for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) {
-                    Value operand = intervalFor(operandNum).operand;
-                    try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, getValueForOperandFromDebugContext(operand))) {
+                    Interval interval = intervalFor(operandNum);
+                    Value operand = null;
+                    ValueNode valueForOperandFromDebugContext = null;
+                    if (interval != null) {
+                        operand = interval.operand;
+                        valueForOperandFromDebugContext = getValueForOperandFromDebugContext(operand);
+                    }
+                    try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) {
 
                         Deque<AbstractBlock<?>> definedIn = new ArrayDeque<>();
                         HashSet<AbstractBlock<?>> usedIn = new HashSet<>();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/OptimizingLinearScanWalker.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/OptimizingLinearScanWalker.java	Tue Sep 09 14:31:36 2014 -0700
@@ -74,34 +74,39 @@
     void walk() {
         try (Scope s = Debug.scope("OptimizingLinearScanWalker")) {
             for (AbstractBlock<?> block : allocator.sortedBlocks) {
-                if (block.getPredecessorCount() == 1) {
-                    int nextBlock = allocator.getFirstLirInstructionId(block);
-                    try (Scope s1 = Debug.scope("LSRAOptimization")) {
-                        Debug.log("next block: %s (%d)", block, nextBlock);
-                    }
-                    try (Indent indent0 = Debug.indent()) {
-                        walkTo(nextBlock);
+                optimizeBlock(block);
+            }
+        }
+        super.walk();
+    }
+
+    private void optimizeBlock(AbstractBlock<?> block) {
+        if (block.getPredecessorCount() == 1) {
+            int nextBlock = allocator.getFirstLirInstructionId(block);
+            try (Scope s1 = Debug.scope("LSRAOptimization")) {
+                Debug.log("next block: %s (%d)", block, nextBlock);
+            }
+            try (Indent indent0 = Debug.indent()) {
+                walkTo(nextBlock);
 
-                        try (Scope s1 = Debug.scope("LSRAOptimization")) {
-                            boolean changed = true;
-                            // we need to do this because the active lists might change
-                            loop: while (changed) {
-                                changed = false;
-                                try (Indent indent1 = Debug.logAndIndent("Active intervals: (block %s [%d])", block, nextBlock)) {
-                                    for (Interval active = activeLists.get(RegisterBinding.Any); active != Interval.EndMarker; active = active.next) {
-                                        Debug.log("active   (any): %s", active);
-                                        if (optimize(nextBlock, block, active, RegisterBinding.Any)) {
-                                            changed = true;
-                                            break loop;
-                                        }
-                                    }
-                                    for (Interval active = activeLists.get(RegisterBinding.Stack); active != Interval.EndMarker; active = active.next) {
-                                        Debug.log("active (stack): %s", active);
-                                        if (optimize(nextBlock, block, active, RegisterBinding.Stack)) {
-                                            changed = true;
-                                            break loop;
-                                        }
-                                    }
+                try (Scope s1 = Debug.scope("LSRAOptimization")) {
+                    boolean changed = true;
+                    // we need to do this because the active lists might change
+                    loop: while (changed) {
+                        changed = false;
+                        try (Indent indent1 = Debug.logAndIndent("Active intervals: (block %s [%d])", block, nextBlock)) {
+                            for (Interval active = activeLists.get(RegisterBinding.Any); active != Interval.EndMarker; active = active.next) {
+                                Debug.log("active   (any): %s", active);
+                                if (optimize(nextBlock, block, active, RegisterBinding.Any)) {
+                                    changed = true;
+                                    break loop;
+                                }
+                            }
+                            for (Interval active = activeLists.get(RegisterBinding.Stack); active != Interval.EndMarker; active = active.next) {
+                                Debug.log("active (stack): %s", active);
+                                if (optimize(nextBlock, block, active, RegisterBinding.Stack)) {
+                                    changed = true;
+                                    break loop;
                                 }
                             }
                         }
@@ -109,7 +114,6 @@
                 }
             }
         }
-        super.walk();
     }
 
     private boolean optimize(int currentPos, AbstractBlock<?> currentBlock, Interval currentInterval, RegisterBinding binding) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Tue Sep 09 14:31:36 2014 -0700
@@ -34,6 +34,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.virtual.nodes.*;
 
@@ -203,20 +204,24 @@
                     STATE_VIRTUAL_OBJECTS.increment();
                     return vobject;
                 }
-            } else if (value instanceof ConstantNode) {
-                STATE_CONSTANTS.increment();
-                return ((ConstantNode) value).getValue();
+            } else {
+                // Remove proxies from constants so the constant can be directly embedded.
+                ValueNode unproxied = GraphUtil.unproxify(value);
+                if (unproxied instanceof ConstantNode) {
+                    STATE_CONSTANTS.increment();
+                    return ((ConstantNode) unproxied).getValue();
 
-            } else if (value != null) {
-                STATE_VARIABLES.increment();
-                Value operand = nodeOperands.get(value);
-                assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value;
-                return operand;
+                } else if (value != null) {
+                    STATE_VARIABLES.increment();
+                    Value operand = nodeOperands.get(value);
+                    assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value;
+                    return operand;
 
-            } else {
-                // return a dummy value because real value not needed
-                STATE_ILLEGALS.increment();
-                return Value.ILLEGAL;
+                } else {
+                    // return a dummy value because real value not needed
+                    STATE_ILLEGALS.increment();
+                    return Value.ILLEGAL;
+                }
             }
         } catch (GraalInternalError e) {
             throw e.addContext("toValue: ", value);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Tue Sep 09 14:31:36 2014 -0700
@@ -24,12 +24,14 @@
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.compiler.phases.HighTier.Options.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
+
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.cfs.IterativeFlowSensitiveReductionPhase;
+import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.common.inlining.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
@@ -56,7 +58,7 @@
                 appendPhase(new IterativeInliningPhase(canonicalizer));
             } else {
                 appendPhase(new InliningPhase(canonicalizer));
-                appendPhase(new DeadCodeEliminationPhase());
+                appendPhase(new DeadCodeEliminationPhase(OPTIONAL));
 
                 boolean reduceOrEliminate = FlowSensitiveReduction.getValue() || ConditionalElimination.getValue();
                 if (reduceOrEliminate && OptCanonicalizer.getValue()) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Tue Sep 09 14:31:36 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.phases;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
 
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.options.*;
@@ -63,6 +64,6 @@
 
         appendPhase(new UseTrappingNullChecksPhase());
 
-        appendPhase(new DeadCodeEliminationPhase());
+        appendPhase(new DeadCodeEliminationPhase(REQUIRED));
     }
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Sep 09 14:31:36 2014 -0700
@@ -30,6 +30,7 @@
 import java.util.*;
 import java.util.concurrent.*;
 
+import com.oracle.graal.debug.DelegatingDebugConfig.Level;
 import com.oracle.graal.debug.internal.*;
 
 /**
@@ -318,7 +319,7 @@
         for (Object obj : context()) {
             context.add(obj);
         }
-        return Debug.sandbox("forceLog", new DelegatingDebugConfig().enable(LOG).enable(LOG_METHOD), context.toArray());
+        return Debug.sandbox("forceLog", new DelegatingDebugConfig().override(Level.LOG, Integer.MAX_VALUE).enable(LOG_METHOD), context.toArray());
     }
 
     /**
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Tue Sep 09 14:31:36 2014 -0700
@@ -39,18 +39,10 @@
      */
     public enum Feature {
         /**
-         * @see Debug#isLogEnabled()
-         */
-        LOG,
-        /**
          * @see Debug#isLogEnabledForMethod()
          */
         LOG_METHOD,
         /**
-         * @see Debug#isDumpEnabled()
-         */
-        DUMP,
-        /**
          * @see Debug#isDumpEnabledForMethod()
          */
         DUMP_METHOD,
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -26,6 +26,7 @@
 
 import org.junit.*;
 
+import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 
@@ -47,6 +48,9 @@
 
     @Before
     public void before() {
+        // Need to initialize HotSpotGraalRuntime before any Node class is initialized.
+        Graal.getRuntime();
+
         graph = new Graph();
         for (int i = 0; i < nodes.length; i++) {
             nodes[i] = graph.add(TestNode.create());
@@ -97,24 +101,45 @@
         }
     }
 
-    @Test(expected = AssertionError.class)
+    @SuppressWarnings("all")
+    private static boolean assertionsEnabled() {
+        boolean assertionsEnabled = false;
+        assert assertionsEnabled = true;
+        return assertionsEnabled;
+    }
+
+    @Test
     public void testNewGet() {
         /*
          * Failing here is not required, but if this behavior changes, usages of get need to be
          * checked for compatibility.
          */
         TestNode newNode = graph.add(TestNode.create());
-        map.get(newNode);
+        try {
+            map.get(newNode);
+            fail("expected " + (assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName()));
+        } catch (AssertionError ae) {
+            // thrown when assertions are enabled
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // thrown when assertions are disabled
+        }
     }
 
-    @Test(expected = AssertionError.class)
+    @Test
     public void testNewSet() {
         /*
          * Failing here is not required, but if this behavior changes, usages of set need to be
          * checked for compatibility.
          */
         TestNode newNode = graph.add(TestNode.create());
-        map.set(newNode, 1);
+        try {
+            map.set(newNode, 1);
+            fail("expected " + (assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName()));
+        } catch (AssertionError ae) {
+            // thrown when assertions are enabled
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // thrown when assertions are disabled
+        }
     }
 
     @Test
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Sep 09 14:31:36 2014 -0700
@@ -479,7 +479,7 @@
             int minCount = Integer.MAX_VALUE;
             Node minCountNode = null;
             for (Node input : node.inputs()) {
-                if (input != null && input.recordsUsages()) {
+                if (input != null) {
                     int estimate = input.getUsageCountUpperBound();
                     if (estimate == 0) {
                         return null;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Sep 09 14:31:36 2014 -0700
@@ -189,6 +189,8 @@
         return graph;
     }
 
+    private static final boolean USE_GENERATED_NODE_ITERATORS = Boolean.getBoolean("graal.useGeneratedNodeIterators");
+
     /**
      * Returns an {@link NodeClassIterable iterable} which can be used to traverse all non-null
      * input edges of this node.
@@ -197,6 +199,9 @@
      */
     public NodeClassIterable inputs() {
         if (USE_GENERATED_NODES) {
+            if (!USE_GENERATED_NODE_ITERATORS) {
+                return new NodeRefIterable(this, true);
+            }
             return inputsV2();
         }
         return getNodeClass().getInputIterable(this);
@@ -210,13 +215,18 @@
      */
     public NodeClassIterable successors() {
         if (USE_GENERATED_NODES) {
+            if (!USE_GENERATED_NODE_ITERATORS) {
+                return new NodeRefIterable(this, false);
+            }
             return successorsV2();
         }
         return getNodeClass().getSuccessorIterable(this);
     }
 
+    /**
+     * Gets the maximum number of usages this node has had at any point in time.
+     */
     int getUsageCountUpperBound() {
-        assert recordsUsages();
         if (usage0 == null) {
             return 0;
         }
@@ -230,20 +240,10 @@
      * Gets the list of nodes that use this node (i.e., as an input).
      */
     public final NodeIterable<Node> usages() {
-        assert recordsUsages() : this;
         return new NodeUsageIterable(this);
     }
 
     /**
-     * Determines if this node records its usages (i.e. the nodes for which it is an input). All
-     * methods in {@link Node} that pertain to querying or updating usage information must not be
-     * called for a {@link Node} instance that returns false for this method.
-     */
-    public boolean recordsUsages() {
-        return true;
-    }
-
-    /**
      * Finds the index of the last non-null entry in a node array. The search assumes that all
      * non-null entries precede the first null entry in the array.
      *
@@ -283,7 +283,6 @@
      * @param node the node to add
      */
     private void addUsage(Node node) {
-        assert recordsUsages();
         incUsageModCount();
         if (usage0 == null) {
             usage0 = node;
@@ -390,7 +389,6 @@
      * @return whether or not {@code usage} was in the usage list
      */
     private boolean removeUsage(Node node) {
-        assert recordsUsages();
         assert node != null;
         // It is critical that this method maintains the invariant that
         // the usage list has no null element preceding a non-null element
@@ -441,7 +439,6 @@
     }
 
     private void clearUsages() {
-        assert recordsUsages();
         incUsageModCount();
         usage0 = null;
         usage1 = null;
@@ -494,18 +491,14 @@
         assert isAlive() && (newInput == null || newInput.isAlive()) : "adding " + newInput + " to " + this + " instead of " + oldInput;
         if (oldInput != newInput) {
             if (oldInput != null) {
-                if (oldInput.recordsUsages()) {
-                    boolean result = removeThisFromUsages(oldInput);
-                    assert assertTrue(result, "not found in usages, old input: %s", oldInput);
-                }
+                boolean result = removeThisFromUsages(oldInput);
+                assert assertTrue(result, "not found in usages, old input: %s", oldInput);
             }
             maybeNotifyInputChanged(this);
             if (newInput != null) {
-                if (newInput.recordsUsages()) {
-                    newInput.addUsage(this);
-                }
+                newInput.addUsage(this);
             }
-            if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) {
+            if (oldInput != null && oldInput.usages().isEmpty()) {
                 maybeNotifyZeroUsages(oldInput);
             }
         }
@@ -570,9 +563,7 @@
             assert assertTrue(result, "not found in inputs, usage: %s", usage);
             if (other != null) {
                 maybeNotifyInputChanged(usage);
-                if (other.recordsUsages()) {
-                    other.addUsage(usage);
-                }
+                other.addUsage(usage);
             }
         }
         clearUsages();
@@ -592,9 +583,7 @@
                 assert assertTrue(result, "not found in inputs, usage: %s", usage);
                 if (other != null) {
                     maybeNotifyInputChanged(usage);
-                    if (other.recordsUsages()) {
-                        other.addUsage(usage);
-                    }
+                    other.addUsage(usage);
                 }
             } else {
                 if (removeStart >= 0) {
@@ -678,11 +667,9 @@
 
     private void unregisterInputs() {
         for (Node input : inputs()) {
-            if (input.recordsUsages()) {
-                removeThisFromUsages(input);
-                if (input.usages().isEmpty()) {
-                    maybeNotifyZeroUsages(input);
-                }
+            removeThisFromUsages(input);
+            if (input.usages().isEmpty()) {
+                maybeNotifyZeroUsages(input);
             }
         }
     }
@@ -713,9 +700,7 @@
     }
 
     private boolean checkDeletion() {
-        if (recordsUsages()) {
-            assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages());
-        }
+        assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages());
         assertTrue(predecessor == null, "cannot delete node %s because of predecessor: %s", this, predecessor);
         return true;
     }
@@ -743,9 +728,7 @@
         clazz.copyInputs(this, newNode);
         if (addToGraph) {
             for (Node input : inputs()) {
-                if (input.recordsUsages()) {
-                    input.addUsage(newNode);
-                }
+                input.addUsage(newNode);
             }
         }
         return newNode;
@@ -817,23 +800,20 @@
         assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id);
         assertTrue(graph() != null, "null graph");
         for (Node input : inputs()) {
-            assertTrue(!input.recordsUsages() || input.usages().contains(this), "missing usage in input %s", input);
+            assertTrue(input.usages().contains(this), "missing usage in input %s", input);
         }
         for (Node successor : successors()) {
             assertTrue(successor.predecessor() == this, "missing predecessor in %s (actual: %s)", successor, successor.predecessor());
             assertTrue(successor.graph() == graph(), "mismatching graph in successor %s", successor);
         }
-        if (recordsUsages()) {
-            for (Node usage : usages()) {
-                assertFalse(usage.isDeleted(), "usage %s must never be deleted", usage);
-                assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage);
-                NodePosIterator iterator = usage.inputs().iterator();
-                while (iterator.hasNext()) {
-                    Position pos = iterator.nextPosition();
-                    if (pos.get(usage) == this && pos.getInputType(usage) != InputType.Unchecked) {
-                        assert isAllowedUsageType(pos.getInputType(usage)) : "invalid input of type " + pos.getInputType(usage) + " from " + usage + " to " + this + " (" + pos.getInputName(usage) +
-                                        ")";
-                    }
+        for (Node usage : usages()) {
+            assertFalse(usage.isDeleted(), "usage %s must never be deleted", usage);
+            assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage);
+            NodePosIterator iterator = usage.inputs().iterator();
+            while (iterator.hasNext()) {
+                Position pos = iterator.nextPosition();
+                if (pos.get(usage) == this && pos.getInputType(usage) != InputType.Unchecked) {
+                    assert isAllowedUsageType(pos.getInputType(usage)) : "invalid input of type " + pos.getInputType(usage) + " from " + usage + " to " + this + " (" + pos.getInputName(usage) + ")";
                 }
             }
         }
@@ -1034,6 +1014,24 @@
         return NodeClassIterable.Empty;
     }
 
+    /**
+     * Determines if this node's inputs contain a given node.
+     *
+     * @param other
+     */
+    public boolean inputsContains(Node other) {
+        return false;
+    }
+
+    /**
+     * Determines if this node's successors contain a given node.
+     *
+     * @param other
+     */
+    public boolean successorsContains(Node other) {
+        return false;
+    }
+
     public NodeClassIterable successorsV2() {
         return NodeClassIterable.Empty;
     }
@@ -1056,6 +1054,68 @@
     }
 
     /**
+     * Gets the number of {@link Node} and {@link NodeList} fields in this node that are
+     * {@link Input}s or {@link OptionalInput}s.
+     *
+     * @return {@code L << 16 | N} where {@code N} is the number of {@link Node} fields and
+     *         {@code L} is the number of {@link NodeList} fields
+     */
+    public int getInputsCount() {
+        return 0;
+    }
+
+    /**
+     * Gets the number of {@link Node} and {@link NodeList} fields in this node that are
+     * {@link Successor}s.
+     *
+     * @return {@code L << 16 | N} where {@code N} is the number of {@link Node} fields and
+     *         {@code L} is the number of {@link NodeList} fields
+     */
+    public int getSuccessorsCount() {
+        return 0;
+    }
+
+    /**
+     * Gets an input of this node at a given index.
+     *
+     * @param index index of an input {@link Node} field. This value must be in the range of the
+     *            number of {@link Node} fields returned by {@link #getInputsCount()}.
+     */
+    public Node getInputNodeAt(int index) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Gets a successor of this node at a given index.
+     *
+     * @param index index of a successor {@link Node} field. This value must be in the range of the
+     *            number of {@link Node} fields returned by {@link #getSuccessorsCount()}.
+     */
+    public Node getSuccessorNodeAt(int index) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Gets an input list at a given index.
+     *
+     * @param index index of an input {@link NodeList} field. This value must be in the range of the
+     *            number of {@link NodeList} fields returned by {@link #getInputsCount()}.
+     */
+    public NodeList<? extends Node> getInputNodeListAt(int index) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Gets a successor list at a given index.
+     *
+     * @param index index of a successor {@link NodeList} field. This value must be in the range of
+     *            the number of {@link NodeList} fields returned by {@link #getSuccessorsCount()}.
+     */
+    public NodeList<? extends Node> getSuccessorNodeListAt(int index) {
+        throw new NoSuchElementException();
+    }
+
+    /**
      * Gets an input or successor list at a given position.
      *
      * @param position
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeAllRefsIterator.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,64 @@
+/*
+ * 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.graph;
+
+import com.oracle.graal.graph.Node.Input;
+
+/**
+ * An iterator over the references to a given {@link Node}'s {@linkplain Input inputs}.
+ *
+ * An iterator of this type will return null values.
+ */
+public final class NodeAllRefsIterator extends NodeRefIterator {
+
+    public NodeAllRefsIterator(Node node, int nodeFields, int nodeListFields, boolean isInputs) {
+        super(node, nodeFields, nodeListFields, isInputs);
+    }
+
+    @Override
+    protected void forward() {
+        assert needsForward;
+        needsForward = false;
+        if (index < nodeFields) {
+            index++;
+            if (index < nodeFields) {
+                nextElement = getNode(index);
+                return;
+            }
+        } else {
+            subIndex++;
+        }
+
+        while (index < allNodeRefFields) {
+            if (subIndex == 0) {
+                list = getNodeList(index - nodeFields);
+            }
+            if (subIndex < list.size()) {
+                nextElement = list.get(subIndex);
+                return;
+            }
+            subIndex = 0;
+            index++;
+        }
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Sep 09 14:31:36 2014 -0700
@@ -340,7 +340,17 @@
     }
 
     /**
-     * Determines if a given {@link Node} class is described by the {@link NodeClass} object.
+     * Determines if a given {@link Node} class is described by this {@link NodeClass} object. This
+     * is useful for doing an exact type test (as opposed to an instanceof test) on a node. For
+     * example:
+     *
+     * <pre>
+     *     if (node.getNodeClass().is(BeginNode.class)) { ... }
+     *
+     *     // Due to generated Node classes, the test below
+     *     // is *not* the same as the test above:
+     *     if (node.getClass() == BeginNode.class) { ... }
+     * </pre>
      *
      * @param nodeClass a {@linkplain GeneratedNode non-generated} {@link Node} class
      */
@@ -496,6 +506,9 @@
         protected final Node node;
         protected int index;
         protected int subIndex;
+        NodeList<Node> list;
+        protected boolean needsForward;
+        protected Node nextElement;
 
         /**
          * Creates an iterator that will iterate over fields in the given node.
@@ -506,14 +519,16 @@
             this.node = node;
             index = NOT_ITERABLE;
             subIndex = 0;
+            needsForward = true;
         }
 
         void forward() {
+            needsForward = false;
             if (index < getDirectCount()) {
                 index++;
                 while (index < getDirectCount()) {
-                    Node element = getNode(node, getOffsets()[index]);
-                    if (element != null) {
+                    nextElement = getNode(node, getOffsets()[index]);
+                    if (nextElement != null) {
                         return;
                     }
                     index++;
@@ -522,9 +537,12 @@
                 subIndex++;
             }
             while (index < getOffsets().length) {
-                NodeList<Node> list = getNodeList(node, getOffsets()[index]);
+                if (subIndex == 0) {
+                    list = getNodeList(node, getOffsets()[index]);
+                }
                 while (subIndex < list.size()) {
-                    if (list.get(subIndex) != null) {
+                    nextElement = list.get(subIndex);
+                    if (nextElement != null) {
                         return;
                     }
                     subIndex++;
@@ -535,39 +553,39 @@
         }
 
         private Node nextElement() {
-            if (index < getDirectCount()) {
-                return getNode(node, getOffsets()[index]);
-            } else if (index < getOffsets().length) {
-                NodeList<Node> list = getNodeList(node, getOffsets()[index]);
-                return list.get(subIndex);
+            if (needsForward) {
+                forward();
+            }
+            needsForward = true;
+            if (index < getOffsets().length) {
+                return nextElement;
             }
             throw new NoSuchElementException();
         }
 
         @Override
         public boolean hasNext() {
+            if (needsForward) {
+                forward();
+            }
             return index < getOffsets().length;
         }
 
         @Override
         public Node next() {
-            try {
-                return nextElement();
-            } finally {
-                forward();
-            }
+            return nextElement();
         }
 
         public Position nextPosition() {
-            try {
-                if (index < getDirectCount()) {
-                    return new Position(getOffsets() == getNodeClass().inputOffsets, index, NOT_ITERABLE);
-                } else {
-                    return new Position(getOffsets() == getNodeClass().inputOffsets, index, subIndex);
-                }
-            } finally {
+            if (needsForward) {
                 forward();
             }
+            needsForward = true;
+            if (index < getDirectCount()) {
+                return new Position(getOffsets() == getNodeClass().inputOffsets, index, NOT_ITERABLE);
+            } else {
+                return new Position(getOffsets() == getNodeClass().inputOffsets, index, subIndex);
+            }
         }
 
         @Override
@@ -583,16 +601,10 @@
     }
 
     private class NodeClassInputsIterator extends NodeClassIterator {
+
         NodeClassInputsIterator(Node node) {
-            this(node, true);
-        }
-
-        NodeClassInputsIterator(Node node, boolean forward) {
             super(node);
             assert NodeClass.this == node.getNodeClass();
-            if (forward) {
-                forward();
-            }
         }
 
         @Override
@@ -613,22 +625,27 @@
 
     private class NodeClassAllInputsIterator extends NodeClassInputsIterator {
         NodeClassAllInputsIterator(Node node) {
-            super(node, true);
+            super(node);
         }
 
         @Override
         void forward() {
+            needsForward = false;
             if (index < getDirectCount()) {
                 index++;
                 if (index < getDirectCount()) {
+                    nextElement = getNode(node, getOffsets()[index]);
                     return;
                 }
             } else {
                 subIndex++;
             }
             while (index < getOffsets().length) {
-                NodeList<Node> list = getNodeList(node, getOffsets()[index]);
+                if (subIndex == 0) {
+                    list = getNodeList(node, getOffsets()[index]);
+                }
                 if (subIndex < list.size()) {
+                    nextElement = list.get(subIndex);
                     return;
                 }
                 subIndex = 0;
@@ -639,22 +656,27 @@
 
     private class NodeClassAllSuccessorsIterator extends NodeClassSuccessorsIterator {
         NodeClassAllSuccessorsIterator(Node node) {
-            super(node, true);
+            super(node);
         }
 
         @Override
         void forward() {
+            needsForward = false;
             if (index < getDirectCount()) {
                 index++;
                 if (index < getDirectCount()) {
+                    nextElement = getNode(node, getOffsets()[index]);
                     return;
                 }
             } else {
                 subIndex++;
             }
             while (index < getOffsets().length) {
-                NodeList<Node> list = getNodeList(node, getOffsets()[index]);
+                if (subIndex == 0) {
+                    list = getNodeList(node, getOffsets()[index]);
+                }
                 if (subIndex < list.size()) {
+                    nextElement = list.get(subIndex);
                     return;
                 }
                 subIndex = 0;
@@ -667,10 +689,9 @@
         private final int modCount;
 
         private NodeClassInputsWithModCountIterator(Node node) {
-            super(node, false);
+            super(node);
             assert MODIFICATION_COUNTS_ENABLED;
             this.modCount = node.modCount();
-            forward();
         }
 
         @Override
@@ -702,16 +723,10 @@
     }
 
     private class NodeClassSuccessorsIterator extends NodeClassIterator {
+
         NodeClassSuccessorsIterator(Node node) {
-            this(node, true);
-        }
-
-        NodeClassSuccessorsIterator(Node node, boolean forward) {
             super(node);
             assert NodeClass.this == node.getNodeClass();
-            if (forward) {
-                forward();
-            }
         }
 
         @Override
@@ -734,10 +749,9 @@
         private final int modCount;
 
         private NodeClassSuccessorsWithModCountIterator(Node node) {
-            super(node, false);
+            super(node);
             assert MODIFICATION_COUNTS_ENABLED;
             this.modCount = node.modCount();
-            forward();
         }
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,77 @@
+/*
+ * 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.graph;
+
+import static com.oracle.graal.graph.Graph.*;
+
+import com.oracle.graal.graph.Node.*;
+
+/**
+ * An iterator over the references to a given {@link Node}'s {@linkplain Input inputs} or
+ * {@linkplain Successor successors}.
+ */
+public final class NodeRefIterable implements NodeClassIterable {
+
+    protected final Node node;
+
+    /**
+     * Specifies if {@link #iterator()} and {@link #withNullIterator()} iterate over
+     * {@linkplain Input inputs} or {@linkplain Successor successors}.
+     */
+    protected final boolean isInputs;
+
+    public NodeRefIterable(Node node, boolean isInputs) {
+        this.isInputs = isInputs;
+        this.node = node;
+    }
+
+    @Override
+    public NodePosIterator iterator() {
+        int count = isInputs ? node.getInputsCount() : node.getSuccessorsCount();
+        if (count == 0) {
+            return NodeRefIterator.Empty;
+        }
+        int nodeFields = count & 0xFFFF;
+        int nodeListFields = (count >> 16) & 0xFFFF;
+        if (MODIFICATION_COUNTS_ENABLED) {
+            return new NodeRefWithModCountIterator(node, nodeFields, nodeListFields, isInputs);
+        } else {
+            return new NodeRefIterator(node, nodeFields, nodeListFields, isInputs);
+        }
+    }
+
+    public NodePosIterator withNullIterator() {
+        int count = isInputs ? node.getInputsCount() : node.getSuccessorsCount();
+        if (count == 0) {
+            return NodeRefIterator.Empty;
+        }
+        int nodeFields = count & 0xFFFF;
+        int nodeListFields = (count >> 16) & 0xFFFF;
+        return new NodeAllRefsIterator(node, nodeFields, nodeListFields, isInputs);
+    }
+
+    @Override
+    public boolean contains(Node other) {
+        return isInputs ? node.inputsContains(other) : node.successorsContains(other);
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java	Tue Sep 09 14:31:36 2014 -0700
@@ -36,7 +36,9 @@
  */
 public class NodeRefIterator implements NodePosIterator {
 
-    public static final NodeRefIterator Empty = new NodeRefIterator(0, 0, false);
+    public static final NodeRefIterator Empty = new NodeRefIterator();
+
+    protected final Node node;
 
     /**
      * The total number of {@link Node} and {@link NodeList} fields.
@@ -52,7 +54,7 @@
      * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor
      * successors}.
      */
-    private final boolean isInputs;
+    protected final boolean isInputs;
 
     /**
      * Current field iteration index.
@@ -65,6 +67,10 @@
      */
     protected int subIndex;
 
+    protected Node nextElement;
+    protected boolean needsForward;
+    protected NodeList<? extends Node> list;
+
     /**
      * Creates an iterator over a node's references (i.e., {@linkplain Input inputs} or
      * {@linkplain Successor successors}) to other nodes. The {@link Node} fields are iterated
@@ -76,22 +82,38 @@
      * @param nodeListFields the number of {@link NodeList} fields in the class hierarchy of the
      *            node being iterated
      */
-    protected NodeRefIterator(int nodeFields, int nodeListFields, boolean isInputs) {
+    protected NodeRefIterator(Node node, int nodeFields, int nodeListFields, boolean isInputs) {
+        this.node = node;
         this.allNodeRefFields = nodeListFields + nodeFields;
         this.nodeFields = nodeFields;
         this.isInputs = isInputs;
-        index = Node.NOT_ITERABLE;
+        this.needsForward = true;
+        index = -1;
         subIndex = 0;
     }
 
     /**
+     * Constructor for {@link #Empty}.
+     */
+    private NodeRefIterator() {
+        this(null, 0, 0, false);
+        // This constructor must only be used to construct Empty
+        assert Empty == null;
+        // This must be set here to prevent multiple threads racing to
+        // call forward() which never needs to be done for Empty.
+        this.needsForward = false;
+        // Ensure hasNext() will always return false.
+        this.index = 0;
+    }
+
+    /**
      * Gets the value of a {@link Node} field in the node.
      *
      * @param at the index of the Node field whose value is being requested. This is guaranteed to
      *            be between 0 and the {@code nodeFields} value this iterator was constructed with
      */
     protected Node getNode(int at) {
-        throw new NoSuchElementException();
+        return isInputs ? node.getInputNodeAt(at) : node.getSuccessorNodeAt(at);
     }
 
     /**
@@ -102,15 +124,16 @@
      *            constructed with
      */
     protected NodeList<? extends Node> getNodeList(int at) {
-        throw new NoSuchElementException();
+        return isInputs ? node.getInputNodeListAt(at) : node.getSuccessorNodeListAt(at);
     }
 
     protected void forward() {
+        needsForward = false;
         if (index < nodeFields) {
             index++;
             while (index < nodeFields) {
-                Node element = getNode(index);
-                if (element != null) {
+                nextElement = getNode(index);
+                if (nextElement != null) {
                     return;
                 }
                 index++;
@@ -119,9 +142,13 @@
             subIndex++;
         }
         while (index < allNodeRefFields) {
-            NodeList<? extends Node> list = getNodeList(index - nodeFields);
+            if (subIndex == 0) {
+                list = getNodeList(index - nodeFields);
+            }
+            assert list == getNodeList(index - nodeFields);
             while (subIndex < list.size()) {
-                if (list.get(subIndex) != null) {
+                nextElement = list.get(subIndex);
+                if (nextElement != null) {
                     return;
                 }
                 subIndex++;
@@ -133,39 +160,39 @@
     }
 
     private Node nextElement() {
-        if (index < nodeFields) {
-            return getNode(index);
-        } else if (index < allNodeRefFields) {
-            NodeList<? extends Node> list = getNodeList(index - nodeFields);
-            return list.get(subIndex);
+        if (needsForward) {
+            forward();
+        }
+        needsForward = true;
+        if (index < allNodeRefFields) {
+            return nextElement;
         }
         throw new NoSuchElementException();
     }
 
     @Override
     public boolean hasNext() {
-        return index >= 0 && index < allNodeRefFields;
+        if (needsForward) {
+            forward();
+        }
+        return index < allNodeRefFields;
     }
 
     @Override
     public Node next() {
-        try {
-            return nextElement();
-        } finally {
-            forward();
-        }
+        return nextElement();
     }
 
     public Position nextPosition() {
-        try {
-            if (index < nodeFields) {
-                return new Position(isInputs, index, Node.NOT_ITERABLE);
-            } else {
-                return new Position(isInputs, index, subIndex);
-            }
-        } finally {
+        if (needsForward) {
             forward();
         }
+        needsForward = true;
+        if (index < nodeFields) {
+            return new Position(isInputs, index, Node.NOT_ITERABLE);
+        } else {
+            return new Position(isInputs, index, subIndex);
+        }
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefWithModCountIterator.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import static com.oracle.graal.graph.Graph.*;
+
+import com.oracle.graal.graph.Node.Input;
+
+/**
+ * An iterator over the references to a given {@link Node}'s {@linkplain Input inputs}.
+ *
+ * An iterator of this type will not return null values, unless the field values are modified
+ * concurrently. Concurrent modifications are detected by an assertion on a best-effort basis.
+ */
+public final class NodeRefWithModCountIterator extends NodeRefIterator {
+
+    private final int modCount;
+
+    public NodeRefWithModCountIterator(Node node, int nodeFields, int nodeListFields, boolean isInputs) {
+        super(node, nodeFields, nodeListFields, isInputs);
+        assert MODIFICATION_COUNTS_ENABLED;
+        this.modCount = node.modCount();
+    }
+
+    @Override
+    public boolean hasNext() {
+        try {
+            return super.hasNext();
+        } finally {
+            assert modCount == node.modCount() : "must not be modified";
+        }
+    }
+
+    @Override
+    public Node next() {
+        try {
+            return super.next();
+        } finally {
+            assert modCount == node.modCount() : "must not be modified";
+        }
+    }
+
+    @Override
+    public Position nextPosition() {
+        try {
+            return super.nextPosition();
+        } finally {
+            assert modCount == node.modCount();
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -692,7 +692,7 @@
             };
 
             DebugConfig debugConfig = DebugScope.getConfig();
-            DebugConfig fixedConfig = Debug.fixedConfig(0, 0, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
+            DebugConfig fixedConfig = debugConfig == null ? null : Debug.fixedConfig(0, 0, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
             try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
                 ReentrantNodeIterator.apply(closure, graph.start(), false);
                 new WriteBarrierVerificationPhase().apply(graph);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -45,10 +45,8 @@
     @Override
     protected boolean verify(StructuredGraph graph, PhaseContext context) {
         for (ConstantNode node : getConstantNodes(graph)) {
-            if (node.recordsUsages()) {
-                if (isObject(node) && !isNullReference(node) && !isInternedString(node) && !isDirectMethodHandle(node) && !isBoundMethodHandle(node)) {
-                    throw new VerificationError("illegal object constant: " + node);
-                }
+            if (isObject(node) && !isNullReference(node) && !isInternedString(node) && !isDirectMethodHandle(node) && !isBoundMethodHandle(node)) {
+                throw new VerificationError("illegal object constant: " + node);
             }
         }
         return true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.phases;
 
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
@@ -109,6 +111,6 @@
         GraphUtil.killCFG(start);
 
         Debug.dump(graph, "OnStackReplacement result");
-        new DeadCodeEliminationPhase().apply(graph);
+        new DeadCodeEliminationPhase(OPTIONAL).apply(graph);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -71,7 +71,9 @@
         Iterator<Node> iterator = frontier.iterator();
         while (iterator.hasNext()) {
             Node currentNode = iterator.next();
-            assert !isSafepoint(currentNode) : "Write barrier must be present " + write;
+            if (isSafepoint(currentNode)) {
+                throw new AssertionError("Write barrier must be present " + write);
+            }
             if (useG1GC()) {
                 if (!(currentNode instanceof G1PostWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode))) {
                     expandFrontier(frontier, currentNode);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Tue Sep 09 14:31:36 2014 -0700
@@ -107,12 +107,36 @@
 
                 // insert moves, delete null instructions and reset instruction ids
                 lir.getControlFlowGraph().getBlocks().forEach(this::rewriteBlock);
+
+                assert verifyStates();
             } catch (Throwable e) {
                 throw Debug.handle(e);
             }
         }
     }
 
+    private boolean verifyStates() {
+        map.forEach(this::verifyStateUsage);
+        return true;
+    }
+
+    private void verifyStateUsage(DefUseTree tree) {
+        Variable var = tree.getVariable();
+        ValueConsumer stateConsumer = new ValueConsumer() {
+
+            @Override
+            public void visitValue(Value operand) {
+                assert !operand.equals(var) : "constant usage through variable in frame state " + var;
+            }
+        };
+        for (AbstractBlock<?> block : lir.getControlFlowGraph().getBlocks()) {
+            for (LIRInstruction inst : lir.getLIRforBlock(block)) {
+                // set instruction id to the index in the lir instruction list
+                inst.visitEachState(stateConsumer);
+            }
+        }
+    }
+
     private static boolean isConstantLoad(LIRInstruction inst) {
         if (!(inst instanceof MoveOp)) {
             return false;
--- a/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java	Tue Sep 09 14:31:36 2014 -0700
@@ -47,6 +47,8 @@
  */
 public class GraphNodeGenerator {
 
+    private static final boolean GENERATE_ASSERTIONS = false;
+
     private final GraphNodeProcessor env;
     private final Types types;
     private final Elements elements;
@@ -283,6 +285,10 @@
     enum NodeRefsType {
         Inputs,
         Successors;
+
+        String singular() {
+            return name().substring(0, name().length() - 1);
+        }
     }
 
     CodeCompilationUnit process(TypeElement node, boolean constructorsOnly) {
@@ -336,7 +342,7 @@
                 createPositionAccessibleFieldOrderClass(packageElement);
 
                 if (!inputListFields.isEmpty() || !successorListFields.isEmpty()) {
-                    createGetNodeListAtMethod();
+                    createGetNodeListAtPositionMethod();
                     createSetNodeListAtMethod();
                 }
             }
@@ -352,6 +358,11 @@
                 createAllIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement, inputFields, inputListFields);
                 createWithModCountIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement);
                 createIterableClass(Inputs, packageElement);
+                createGetNodeAtMethod(NodeRefsType.Inputs, inputFields);
+                createCountMethod(NodeRefsType.Inputs, inputFields.size(), inputListFields.size());
+                if (!inputListFields.isEmpty()) {
+                    createGetNodeListAtIndexMethod(NodeRefsType.Inputs, inputListFields);
+                }
             }
 
             if (hasSuccessors) {
@@ -364,6 +375,11 @@
                 createAllIteratorClass(Successors, successorsIteratorClass.asType(), packageElement, successorFields, successorListFields);
                 createWithModCountIteratorClass(Successors, successorsIteratorClass.asType(), packageElement);
                 createIterableClass(Successors, packageElement);
+                createGetNodeAtMethod(NodeRefsType.Successors, successorFields);
+                createCountMethod(NodeRefsType.Successors, successorFields.size(), successorListFields.size());
+                if (!successorListFields.isEmpty()) {
+                    createGetNodeListAtIndexMethod(NodeRefsType.Successors, successorListFields);
+                }
             }
         }
         compilationUnit.add(genClass);
@@ -426,6 +442,22 @@
         genClassName = null;
     }
 
+    private CodeVariableElement addParameter(CodeExecutableElement method, TypeMirror type, String name) {
+        return addParameter(method, type, name, true);
+    }
+
+    private CodeVariableElement addParameter(CodeExecutableElement method, TypeMirror type, String name, boolean checkHiding) {
+        CodeVariableElement parameter = new CodeVariableElement(type, name);
+        if (checkHiding && hidesField(parameter.getSimpleName().toString())) {
+            DeclaredType suppress = (DeclaredType) getType(SuppressWarnings.class);
+            CodeAnnotationMirror suppressMirror = new CodeAnnotationMirror(suppress);
+            suppressMirror.setElementValue(suppressMirror.findExecutableElement("value"), new CodeAnnotationValue("hiding"));
+            parameter.getAnnotationMirrors().add(suppressMirror);
+        }
+        method.addParameter(parameter);
+        return parameter;
+    }
+
     /**
      * Checks that a generated method overrides exactly one method in a super type and that the
      * super type is Node.
@@ -448,9 +480,11 @@
 
     private ExecutableElement createIsOptionalInputAtMethod() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isOptionalInputAt");
-        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        addParameter(method, Position.asType(), "pos");
         CodeTreeBuilder b = method.createBuilder();
-        b.startAssert().string("pos.isInput()").end();
+        if (GENERATE_ASSERTIONS) {
+            b.startAssert().string("pos.isInput()").end();
+        }
         if (!optionalInputs.isEmpty()) {
             b.startSwitch().string("pos.getIndex()").end().startBlock();
             int index = 0;
@@ -490,16 +524,13 @@
 
         // Constructor
         CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name);
-        ctor.addParameter(new CodeVariableElement(getType(boolean.class), "callForward"));
         CodeTreeBuilder b = ctor.createBuilder();
         b.startStatement().startSuperCall();
+        b.string(genClassName, ".this");
         b.string(String.valueOf(nodeFields.size()));
         b.string(String.valueOf(nodeListFields.size()));
         b.string(String.valueOf(nodeRefsType == NodeRefsType.Inputs));
         b.end().end();
-        b.startIf().string("callForward").end().startBlock();
-        b.startStatement().string("forward()").end();
-        b.end();
         cls.add(ctor);
 
         // Methods overriding those in NodeRefIterator
@@ -512,7 +543,7 @@
     private void createGetFieldMethod(CodeTypeElement cls, List<VariableElement> fields, TypeMirror returnType, String name) {
         if (!fields.isEmpty()) {
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), returnType, name);
-            method.addParameter(new CodeVariableElement(getType(int.class), "at"));
+            addParameter(method, getType(int.class), "at");
             CodeTreeBuilder b = method.createBuilder();
             createGetFieldCases(b, fields, returnType, null);
             cls.add(method);
@@ -623,7 +654,7 @@
 
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(String[].class), "getOrderedFieldNames");
 
-        method.addParameter(new CodeVariableElement(getType(boolean.class), "input"));
+        addParameter(method, getType(boolean.class), "input", false);
 
         CodeTreeBuilder b = method.createBuilder();
         b.startIf().string("input").end().startBlock();
@@ -646,34 +677,33 @@
         CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE, FINAL), ElementKind.CLASS, packageElement, name);
         cls.setSuperClass(inputsIteratorType);
 
-        // Constructor
-        CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name);
-        CodeTreeBuilder b = ctor.createBuilder();
-        b.startStatement().startSuperCall();
-        b.string("true");
-        b.end().end();
-        cls.add(ctor);
-
         // forward() method
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getType(void.class), "forward");
-        b = method.createBuilder();
+        CodeTreeBuilder b = method.createBuilder();
         int nodeFieldsSize = nodeFields.size();
         int nodeListFieldsSize = nodeListFields.size();
         String cond = "index < " + nodeFieldsSize;
+        if (GENERATE_ASSERTIONS) {
+            b.startAssert().string("needsForward").end();
+        }
+        b.startStatement().string("needsForward = false").end();
         b.startIf().string(cond).end().startBlock();
         b.startStatement().string("index++").end();
         b.startIf().string(cond).end().startBlock();
+        b.startStatement().string("nextElement = getNode(index)").end();
         b.startStatement().string("return").end();
         b.end();
         b.end();
         b.startElseBlock();
         b.startStatement().string("subIndex++").end();
         b.end();
-        DeclaredType nodeListOfNode = types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null));
         int count = nodeFieldsSize + nodeListFieldsSize;
         b.startWhile().string("index < " + count).end().startBlock();
-        b.declaration(nodeListOfNode, "list", "getNodeList(index - " + nodeFieldsSize + ")");
+        b.startIf().string("subIndex == 0").end().startBlock();
+        b.startStatement().string("list = getNodeList(index - " + nodeFieldsSize + ")").end();
+        b.end();
         b.startIf().string("subIndex < list.size()").end().startBlock();
+        b.startStatement().string("nextElement = list.get(subIndex)").end();
         b.startStatement().string("return").end();
         b.end();
         b.startStatement().string("subIndex = 0").end();
@@ -697,12 +727,8 @@
         // Constructor
         CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name);
         CodeTreeBuilder b = ctor.createBuilder();
-        b.startStatement().startSuperCall();
-        b.string("false");
-        b.end().end();
         b.startAssert().staticReference(getType("com.oracle.graal.graph.Graph"), "MODIFICATION_COUNTS_ENABLED").end();
         b.startStatement().string("this.modCount = modCount()").end();
-        b.startStatement().string("forward()").end();
         cls.add(ctor);
 
         // hasNext, next and nextPosition methods
@@ -737,7 +763,7 @@
         b.startStatement().string("return new " + nodeRefsType + "WithModCountIterator()").end();
         b.end();
         b.startElseBlock();
-        b.startStatement().string("return new " + nodeRefsType + "Iterator(true)").end();
+        b.startStatement().string("return new " + nodeRefsType + "Iterator()").end();
         b.end();
         cls.add(method);
 
@@ -749,16 +775,16 @@
 
         // contains(Node) method
         method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(boolean.class), "contains");
-        method.addParameter(new CodeVariableElement(Node.asType(), "n"));
+        addParameter(method, Node.asType(), "n");
         b = method.createBuilder();
-        b.startStatement().string("return " + nodeRefsType.name().toLowerCase() + "Contain(n)").end();
+        b.startStatement().string("return " + nodeRefsType.name().toLowerCase() + "Contains(n)").end();
         cls.add(method);
         genClass.add(cls);
     }
 
     private void createContainsMethod(NodeRefsType nodeRefsType, List<VariableElement> nodeFields, List<VariableElement> nodeListFields) {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, FINAL), getType(boolean.class), nodeRefsType.name().toLowerCase() + "Contain");
-        method.addParameter(new CodeVariableElement(Node.asType(), "n"));
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(boolean.class), nodeRefsType.name().toLowerCase() + "Contains");
+        addParameter(method, Node.asType(), "n");
         CodeTreeBuilder b = method.createBuilder();
         for (VariableElement f : nodeFields) {
             b.startIf().string("n == " + f).end().startBlock();
@@ -788,7 +814,7 @@
 
     private void createGetNodeAtMethod() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), Node.asType(), "getNodeAt");
-        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        addParameter(method, Position.asType(), "pos");
         CodeTreeBuilder b = method.createBuilder();
         b.startIf().string("pos.isInput()").end().startBlock();
         createGetNodeAt(b, inputFields, inputListFields);
@@ -800,9 +826,79 @@
         checkOnlyInGenNode(method);
     }
 
-    private void createGetNodeListAtMethod() {
+    private void createCountMethod(NodeRefsType nodeRefsType, int nodesCount, int nodeListsCount) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(int.class), "get" + nodeRefsType + "Count");
+        CodeTreeBuilder b = method.createBuilder();
+
+        b.startStatement().string("return " + (nodeListsCount << 16 | nodesCount), " /* (" + nodeListsCount + " << 16 | " + nodesCount + ") */").end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createGetNodeAtMethod(NodeRefsType nodeRefsType, List<VariableElement> nodes) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), Node.asType(), "get" + nodeRefsType.singular() + "NodeAt");
+        addParameter(method, getType(int.class), "index");
+        CodeTreeBuilder b = method.createBuilder();
+        boolean justOne = nodes.size() == 1;
+        if (!justOne) {
+            b.startSwitch().string("index").end().startBlock();
+        } else if (GENERATE_ASSERTIONS) {
+            b.startAssert().string("index == 0").end();
+        }
+        int index = 0;
+        for (VariableElement f : nodes) {
+            if (!justOne) {
+                b.startCase().string(String.valueOf(index)).end();
+            }
+            b.startReturn();
+            if (!isAssignableWithErasure(f, Node)) {
+                b.cast(((DeclaredType) Node.asType()).asElement().getSimpleName().toString());
+            }
+            b.string(genClassName + ".this." + f.getSimpleName());
+            b.end();
+            index++;
+        }
+        if (!justOne) {
+            b.end();
+            b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+        }
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createGetNodeListAtIndexMethod(NodeRefsType nodeRefsType, List<VariableElement> nodeLists) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "get" +
+                        nodeRefsType.singular() + "NodeListAt");
+        addParameter(method, getType(int.class), "index");
+        CodeTreeBuilder b = method.createBuilder();
+
+        boolean justOne = nodeLists.size() == 1;
+        if (!justOne) {
+            b.startSwitch().string("index").end().startBlock();
+        } else if (GENERATE_ASSERTIONS) {
+            b.startAssert().string("index == 0").end();
+        }
+        int index = 0;
+        for (VariableElement f : nodeLists) {
+            if (!justOne) {
+                b.startCase().string(String.valueOf(index)).end();
+            }
+            b.startReturn();
+            b.string(genClassName + ".this." + f.getSimpleName());
+            b.end();
+            index++;
+        }
+        if (!justOne) {
+            b.end();
+            b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+        }
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createGetNodeListAtPositionMethod() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "getNodeListAt");
-        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        addParameter(method, Position.asType(), "pos");
         CodeTreeBuilder b = method.createBuilder();
         b.startIf().string("pos.isInput()").end().startBlock();
         createGetNodeListAt(b, inputFields, inputListFields);
@@ -822,8 +918,8 @@
         suppressMirror.setElementValue(suppressMirror.findExecutableElement("value"), new CodeAnnotationValue("unchecked"));
         method.getAnnotationMirrors().add(suppressMirror);
 
-        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
-        method.addParameter(new CodeVariableElement(types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "list"));
+        addParameter(method, Position.asType(), "pos");
+        addParameter(method, types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "list");
         CodeTreeBuilder b = method.createBuilder();
         b.startIf().string("pos.isInput()").end().startBlock();
         createSetNodeListAt(b, inputFields, inputListFields);
@@ -837,7 +933,7 @@
 
     private void createGetNameOfMethod() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(String.class), "getNameOf");
-        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        addParameter(method, Position.asType(), "pos");
         CodeTreeBuilder b = method.createBuilder();
 
         b.startIf().string("pos.isInput()").end().startBlock();
@@ -852,9 +948,11 @@
 
     private void createGetInputTypeAtMethod() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(InputType.class), "getInputTypeAt");
-        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        addParameter(method, Position.asType(), "pos");
         CodeTreeBuilder b = method.createBuilder();
-        b.startAssert().string("pos.isInput()").end();
+        if (GENERATE_ASSERTIONS) {
+            b.startAssert().string("pos.isInput()").end();
+        }
         boolean hasNodes = !inputFields.isEmpty();
         boolean hasNodeLists = !inputListFields.isEmpty();
         if (hasNodeLists || hasNodes) {
@@ -882,15 +980,8 @@
 
     private void createUpdateOrInitializeNodeAtMethod(boolean isInitialization) {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), (isInitialization ? "initialize" : "update") + "NodeAt");
-        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
-        CodeVariableElement newValue = new CodeVariableElement(Node.asType(), "newValue");
-        if (hidesField(newValue.getSimpleName().toString())) {
-            DeclaredType suppress = (DeclaredType) getType(SuppressWarnings.class);
-            CodeAnnotationMirror suppressMirror = new CodeAnnotationMirror(suppress);
-            suppressMirror.setElementValue(suppressMirror.findExecutableElement("value"), new CodeAnnotationValue("hiding"));
-            newValue.getAnnotationMirrors().add(suppressMirror);
-        }
-        method.addParameter(newValue);
+        addParameter(method, Position.asType(), "pos");
+        addParameter(method, Node.asType(), "newValue");
         CodeTreeBuilder b = method.createBuilder();
         b.startIf().string("pos.isInput()").end().startBlock();
         createUpdateOrInitializeNodeAt(b, inputFields, inputListFields, isInitialization);
@@ -910,7 +1001,9 @@
         } else {
             if (hasNodes) {
                 if (!hasNodeLists) {
-                    b.startAssert().string("pos.getSubIndex() == NOT_ITERABLE").end();
+                    if (GENERATE_ASSERTIONS) {
+                        b.startAssert().string("pos.getSubIndex() == NOT_ITERABLE").end();
+                    }
                 } else {
                     b.startIf().string("pos.getSubIndex() == NOT_ITERABLE").end().startBlock();
                 }
@@ -923,7 +1016,9 @@
 
             if (hasNodeLists) {
                 if (!hasNodes) {
-                    b.startAssert().string("pos.getSubIndex() != NOT_ITERABLE").end();
+                    if (GENERATE_ASSERTIONS) {
+                        b.startAssert().string("pos.getSubIndex() != NOT_ITERABLE").end();
+                    }
                 } else {
                     b.startElseBlock();
                 }
@@ -941,7 +1036,9 @@
         if (!hasNodeLists) {
             b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
         } else {
-            b.startAssert().string("pos.getSubIndex() == NODE_LIST").end();
+            if (GENERATE_ASSERTIONS) {
+                b.startAssert().string("pos.getSubIndex() == NODE_LIST").end();
+            }
             b.declaration("int", "at", "pos.getIndex() - " + nodes.size());
             createGetFieldCases(b, nodeLists, Node.asType(), "");
         }
@@ -952,7 +1049,9 @@
         if (!hasNodeLists) {
             b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
         } else {
-            b.startAssert().string("pos.getSubIndex() == NODE_LIST").end();
+            if (GENERATE_ASSERTIONS) {
+                b.startAssert().string("pos.getSubIndex() == NODE_LIST").end();
+            }
             b.declaration("int", "at", "pos.getIndex() - " + nodes.size());
             createSetNodeListAtCases(b, nodeLists, Node.asType(), "");
         }
@@ -987,7 +1086,9 @@
         } else {
             if (hasNodes) {
                 if (!hasNodeLists) {
-                    b.startAssert().string("pos.getSubIndex() == NOT_ITERABLE").end();
+                    if (GENERATE_ASSERTIONS) {
+                        b.startAssert().string("pos.getSubIndex() == NOT_ITERABLE").end();
+                    }
                 } else {
                     b.startIf().string("pos.getSubIndex() == NOT_ITERABLE").end().startBlock();
                 }
@@ -1000,7 +1101,9 @@
 
             if (hasNodeLists) {
                 if (!hasNodes) {
-                    b.startAssert().string("pos.getSubIndex() != NOT_ITERABLE").end();
+                    if (GENERATE_ASSERTIONS) {
+                        b.startAssert().string("pos.getSubIndex() != NOT_ITERABLE").end();
+                    }
                 } else {
                     b.startElseBlock();
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Tue Sep 09 14:31:36 2014 -0700
@@ -46,6 +46,11 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        //
+        Node prev = this.predecessor();
+        while (prev.getNodeClass().is(BeginNode.class) && prev.usages().isEmpty()) {
+            BeginNode begin = (BeginNode) prev;
+            prev = prev.predecessor();
+            graph().removeFixed(begin);
+        }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Tue Sep 09 14:31:36 2014 -0700
@@ -100,7 +100,7 @@
             }
             ValueNode removedValue = phi.valueAt(predIndex);
             phi.removeInput(predIndex);
-            if (removedValue != null && removedValue.isAlive() && removedValue.recordsUsages() && removedValue.usages().isEmpty() && GraphUtil.isFloatingNode().apply(removedValue)) {
+            if (removedValue != null && removedValue.isAlive() && removedValue.usages().isEmpty() && GraphUtil.isFloatingNode().apply(removedValue)) {
                 GraphUtil.killWithUnusedFloatingInputs(removedValue);
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Sep 09 14:31:36 2014 -0700
@@ -193,7 +193,13 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        ValueNode singleValue = singleValue();
+        ValueNode singleValue;
+
+        if (isLoopPhi() && singleBackValue() == this) {
+            singleValue = firstValue();
+        } else {
+            singleValue = singleValue();
+        }
 
         if (singleValue != MULTIPLE_VALUES) {
             for (Node node : usages().snapshot()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Sep 09 14:31:36 2014 -0700
@@ -64,32 +64,42 @@
     }
 
     /**
+     * Replicate the {@link ValueProxyNode}s from {@code originalValue} onto {@code value}.
+     *
+     * @param originalValue a possibly proxied value
+     * @param value a value needing proxies
+     * @return proxies wrapping {@code value}
+     */
+    private static ValueNode reproxyValue(ValueNode originalValue, ValueNode value) {
+        if (value.isConstant()) {
+            // No proxy needed
+            return value;
+        }
+        if (originalValue instanceof ValueProxyNode) {
+            ValueProxyNode proxy = (ValueProxyNode) originalValue;
+            return ValueProxyNode.create(reproxyValue(proxy.getOriginalNode(), value), proxy.proxyPoint());
+        } else if (originalValue instanceof ValueProxy) {
+            ValueProxy proxy = (ValueProxy) originalValue;
+            return reproxyValue(proxy.getOriginalNode(), value);
+        } else {
+            return value;
+        }
+    }
+
+    /**
      * Gets the length of an array if possible.
      *
      * @return a node representing the length of {@code array} or null if it is not available
      */
     public static ValueNode readArrayLength(ValueNode originalArray, ConstantReflectionProvider constantReflection) {
-        ArrayLengthProvider foundArrayLengthProvider = null;
-        ValueNode result = originalArray;
-        while (true) {
-            if (result instanceof ArrayLengthProvider) {
-                foundArrayLengthProvider = (ArrayLengthProvider) result;
-                break;
-            }
-            if (result instanceof ValueProxy) {
-                result = ((ValueProxy) result).getOriginalNode();
-            } else {
-                break;
+        ValueNode array = GraphUtil.unproxify(originalArray);
+        if (array instanceof ArrayLengthProvider) {
+            ValueNode length = ((ArrayLengthProvider) array).length();
+            if (length != null) {
+                // Ensure that any proxies on the original value end up on the length value
+                return reproxyValue(originalArray, length);
             }
         }
-
-        if (foundArrayLengthProvider != null) {
-            ValueNode length = foundArrayLengthProvider.length();
-            if (length != null) {
-                return length;
-            }
-        }
-        ValueNode array = GraphUtil.unproxify(originalArray);
         if (constantReflection != null && array.isConstant() && !array.isNullConstant()) {
             Constant constantValue = array.asConstant();
             if (constantValue != null && constantValue.isNonNull()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Sep 09 14:31:36 2014 -0700
@@ -135,17 +135,13 @@
     }
 
     public static void killWithUnusedFloatingInputs(Node node) {
-        if (node.recordsUsages()) {
-            List<Node> floatingInputs = node.inputs().filter(isFloatingNode()).snapshot();
-            node.safeDelete();
+        List<Node> floatingInputs = node.inputs().filter(isFloatingNode()).snapshot();
+        node.safeDelete();
 
-            for (Node in : floatingInputs) {
-                if (in.isAlive() && (!in.recordsUsages() || in.usages().isEmpty())) {
-                    killWithUnusedFloatingInputs(in);
-                }
+        for (Node in : floatingInputs) {
+            if (in.isAlive() && in.usages().isEmpty()) {
+                killWithUnusedFloatingInputs(in);
             }
-        } else {
-            assert node.inputs().isEmpty();
         }
     }
 
@@ -358,7 +354,7 @@
     }
 
     public static boolean tryKillUnused(Node node) {
-        if (node.isAlive() && isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) {
+        if (node.isAlive() && isFloatingNode().apply(node) && node.usages().isEmpty()) {
             killWithUnusedFloatingInputs(node);
             return true;
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -832,9 +832,6 @@
         }
 
         private GuardingNode searchAnchor(ValueNode value, ResolvedJavaType type) {
-            if (!value.recordsUsages()) {
-                return null;
-            }
             for (Node n : value.usages()) {
                 if (n instanceof InstanceOfNode) {
                     InstanceOfNode instanceOfNode = (InstanceOfNode) n;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -101,7 +103,7 @@
             }
         }
 
-        new DeadCodeEliminationPhase().apply(graph);
+        new DeadCodeEliminationPhase(OPTIONAL).apply(graph);
     }
 
     private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
@@ -147,11 +149,11 @@
                     }
                 }
             }
-            survivingSuccessor.simplify(simplifierTool);
             Debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin);
             FixedNode next = pred.next();
             pred.setNext(guard);
             guard.setNext(next);
+            survivingSuccessor.simplify(simplifierTool);
             return;
         }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -22,18 +22,54 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Options.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 
 public class DeadCodeEliminationPhase extends Phase {
 
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Disable optional dead code eliminations")
+        public static final OptionValue<Boolean> ReduceDCE = new OptionValue<>(true);
+        // @formatter:on
+    }
+
     // Metrics
     private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved");
 
+    public enum Optionality {
+        OPTIONAL,
+        REQUIRED;
+    }
+
+    /**
+     * Creates a dead code elimination phase that will be run irrespective of
+     * {@link Options#ReduceDCE}.
+     */
+    public DeadCodeEliminationPhase() {
+        this(Optionality.REQUIRED);
+    }
+
+    /**
+     * Creates a dead code elimination phase that will be run only if it is
+     * {@linkplain Optionality#REQUIRED non-optional} or {@link Options#ReduceDCE} is false.
+     */
+    public DeadCodeEliminationPhase(Optionality optionality) {
+        this.optional = optionality == Optionality.OPTIONAL;
+    }
+
+    private final boolean optional;
+
     @Override
     public void run(StructuredGraph graph) {
+        if (optional && ReduceDCE.getValue()) {
+            return;
+        }
         NodeFlood flood = graph.createNodeFlood();
 
         flood.add(graph.start());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -172,10 +172,14 @@
          * then remove the Begin from the graph.
          */
         nonTrappingContinuation.replaceAtUsages(InputType.Guard, trappingNullCheck);
-        FixedNode next = nonTrappingContinuation.next();
-        nonTrappingContinuation.clearSuccessors();
-        trappingNullCheck.setNext(next);
-        nonTrappingContinuation.safeDelete();
+        if (nonTrappingContinuation.getNodeClass().is(BeginNode.class)) {
+            FixedNode next = nonTrappingContinuation.next();
+            nonTrappingContinuation.clearSuccessors();
+            trappingNullCheck.setNext(next);
+            nonTrappingContinuation.safeDelete();
+        } else {
+            trappingNullCheck.setNext(nonTrappingContinuation);
+        }
 
         GraphUtil.killCFG(trappingContinuation);
         if (isNullNode.usages().isEmpty()) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Tue Sep 09 14:31:36 2014 -0700
@@ -22,24 +22,23 @@
  */
 package com.oracle.graal.phases.common.cfs;
 
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
+
+import java.lang.reflect.*;
+
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.Node;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.FloatingNode;
-import com.oracle.graal.nodes.calc.IsNullNode;
-import com.oracle.graal.nodes.extended.LoadHubNode;
-import com.oracle.graal.nodes.extended.NullCheckNode;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.compiler.common.type.IllegalStamp;
-import com.oracle.graal.nodes.type.StampTool;
-import com.oracle.graal.nodes.util.GraphUtil;
-import com.oracle.graal.phases.common.DeadCodeEliminationPhase;
-import com.oracle.graal.phases.tiers.PhaseContext;
-
-import java.lang.reflect.Modifier;
-
-import static com.oracle.graal.api.meta.DeoptimizationAction.InvalidateReprofile;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * <p>
@@ -152,7 +151,7 @@
             for (PostponedDeopt postponed : postponedDeopts) {
                 postponed.doRewrite(falseConstant);
             }
-            new DeadCodeEliminationPhase().apply(graph);
+            new DeadCodeEliminationPhase(OPTIONAL).apply(graph);
         }
         for (MethodCallTargetNode mcn : graph.getNodes().filter(MethodCallTargetNode.class)) {
             if (mcn.isAlive() && FlowUtil.lacksUsages(mcn)) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Tue Sep 09 14:31:36 2014 -0700
@@ -37,7 +37,7 @@
     }
 
     public static boolean lacksUsages(Node n) {
-        return n.recordsUsages() && n.usages().isEmpty();
+        return n.usages().isEmpty();
     }
 
     public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) {
@@ -95,11 +95,11 @@
         } else {
             /*
              * Not comparable, two cases:
-             *
+             * 
              * Example 1: 'a' standing for j.l.Number and 'b' for j.l.String We return null for lack
              * of a value representing NullType, the right answer. Same goes when both arguments are
              * non-comparable interfaces.
-             *
+             * 
              * Example 2: 'a' standing for sun/nio/ch/DirectBuffer (an interface) and b for
              * java/nio/Buffer (an abstract class). The class always takes precedence.
              */
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java	Tue Sep 09 14:31:36 2014 -0700
@@ -45,4 +45,6 @@
     int getNodeCount();
 
     Iterable<Invoke> getInvokes();
+
+    double getProbability(Invoke invoke);
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java	Tue Sep 09 14:31:36 2014 -0700
@@ -22,21 +22,21 @@
  */
 package com.oracle.graal.phases.common.inlining.info.elem;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
+
 import java.util.*;
 
-import com.oracle.graal.api.meta.Constant;
-import com.oracle.graal.api.meta.ResolvedJavaMethod;
-import com.oracle.graal.compiler.common.type.Stamp;
-import com.oracle.graal.debug.Debug;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.common.CanonicalizerPhase;
-import com.oracle.graal.phases.common.DeadCodeEliminationPhase;
-import com.oracle.graal.phases.common.cfs.FlowUtil;
-import com.oracle.graal.phases.common.inlining.InliningUtil;
-import com.oracle.graal.phases.tiers.HighTierContext;
-
-import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.cfs.*;
+import com.oracle.graal.phases.common.inlining.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * <p>
@@ -56,6 +56,8 @@
 
     private final StructuredGraph graph;
 
+    private FixedNodeProbabilityCache probabilites = new FixedNodeProbabilityCache();
+
     public InlineableGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer) {
         StructuredGraph original = getOriginalGraph(method, context, canonicalizer);
         // TODO copying the graph is only necessary if it is modified or if it contains any invokes
@@ -245,7 +247,7 @@
             }
             assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite";
 
-            new DeadCodeEliminationPhase().apply(newGraph);
+            new DeadCodeEliminationPhase(OPTIONAL).apply(newGraph);
 
             if (OptCanonicalizer.getValue()) {
                 canonicalizer.apply(newGraph, context);
@@ -270,6 +272,11 @@
         return graph.getInvokes();
     }
 
+    @Override
+    public double getProbability(Invoke invoke) {
+        return probabilites.applyAsDouble(invoke.asNode());
+    }
+
     public StructuredGraph getGraph() {
         return graph;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableMacroNode.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableMacroNode.java	Tue Sep 09 14:31:36 2014 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.phases.common.inlining.info.elem;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.nodes.FixedWithNextNode;
 import com.oracle.graal.nodes.Invoke;
 
@@ -48,4 +49,8 @@
     public Class<? extends FixedWithNextNode> getMacroNodeClass() {
         return macroNodeClass;
     }
+
+    public double getProbability(Invoke invoke) {
+        throw GraalInternalError.shouldNotReachHere("No invokes in inlineable");
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java	Tue Sep 09 14:31:36 2014 -0700
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.ProfilingInfo;
 import com.oracle.graal.api.meta.ResolvedJavaMethod;
-import com.oracle.graal.nodes.FixedNode;
 import com.oracle.graal.nodes.Invoke;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.spi.Replacements;
@@ -33,7 +32,6 @@
 import com.oracle.graal.phases.common.inlining.info.elem.Inlineable;
 
 import java.util.Map;
-import java.util.function.ToDoubleFunction;
 
 import static com.oracle.graal.compiler.common.GraalOptions.RelevanceCapForInlining;
 import static com.oracle.graal.phases.common.inlining.InliningPhase.Options.AlwaysInlineIntrinsics;
@@ -100,14 +98,14 @@
         return size;
     }
 
-    protected static double determineInvokeProbability(ToDoubleFunction<FixedNode> probabilities, InlineInfo info) {
+    protected static double determineInvokeProbability(InlineInfo info) {
         double invokeProbability = 0;
         for (int i = 0; i < info.numberOfMethods(); i++) {
             Inlineable callee = info.inlineableElementAt(i);
             Iterable<Invoke> invokes = callee.getInvokes();
             if (invokes.iterator().hasNext()) {
                 for (Invoke invoke : invokes) {
-                    invokeProbability += probabilities.applyAsDouble(invoke.asNode());
+                    invokeProbability += callee.getProbability(invoke);
                 }
             }
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java	Tue Sep 09 14:31:36 2014 -0700
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.debug.Debug;
 import com.oracle.graal.debug.DebugMetric;
-import com.oracle.graal.nodes.FixedNode;
 import com.oracle.graal.nodes.Invoke;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.spi.Replacements;
@@ -33,7 +32,6 @@
 import com.oracle.graal.phases.common.inlining.walker.MethodInvocation;
 
 import java.util.Map;
-import java.util.function.ToDoubleFunction;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 
@@ -55,7 +53,7 @@
     }
 
     @Override
-    public boolean isWorthInlining(ToDoubleFunction<FixedNode> probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+    public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
 
         final InlineInfo info = invocation.callee();
         final double probability = invocation.probability();
@@ -97,7 +95,7 @@
          * inline those methods but increases bootstrap time (maybe those methods are also getting
          * queued in the compilation queue concurrently)
          */
-        double invokes = determineInvokeProbability(probabilities, info);
+        double invokes = determineInvokeProbability(info);
         if (LimitInlinedInvokes.getValue() > 0 && fullyProcessed && invokes > LimitInlinedInvokes.getValue() * inliningBonus) {
             InliningUtil.logNotInlinedMethod(info, inliningDepth, "callee invoke probability is too high (invokeP=%f, relevance=%f, probability=%f, bonus=%f, nodes=%d)", invokes, relevance,
                             probability, inliningBonus, nodes);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java	Tue Sep 09 14:31:36 2014 -0700
@@ -23,13 +23,10 @@
 package com.oracle.graal.phases.common.inlining.policy;
 
 import com.oracle.graal.api.code.BailoutException;
-import com.oracle.graal.nodes.FixedNode;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.spi.Replacements;
 import com.oracle.graal.phases.common.inlining.walker.MethodInvocation;
 
-import java.util.function.ToDoubleFunction;
-
 import static com.oracle.graal.compiler.common.GraalOptions.MaximumDesiredSize;
 
 public final class InlineEverythingPolicy implements InliningPolicy {
@@ -41,7 +38,7 @@
         return true;
     }
 
-    public boolean isWorthInlining(ToDoubleFunction<FixedNode> probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+    public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
         return true;
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InliningPolicy.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InliningPolicy.java	Tue Sep 09 14:31:36 2014 -0700
@@ -22,16 +22,13 @@
  */
 package com.oracle.graal.phases.common.inlining.policy;
 
-import com.oracle.graal.nodes.FixedNode;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.spi.Replacements;
 import com.oracle.graal.phases.common.inlining.walker.MethodInvocation;
 
-import java.util.function.ToDoubleFunction;
-
 public interface InliningPolicy {
 
     boolean continueInlining(StructuredGraph graph);
 
-    boolean isWorthInlining(ToDoubleFunction<FixedNode> probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed);
+    boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed);
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Tue Sep 09 14:31:36 2014 -0700
@@ -46,12 +46,10 @@
 import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph;
 import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode;
 import com.oracle.graal.phases.common.inlining.policy.InliningPolicy;
-import com.oracle.graal.phases.graph.FixedNodeProbabilityCache;
 import com.oracle.graal.phases.tiers.HighTierContext;
 import com.oracle.graal.phases.util.Providers;
 
 import java.util.*;
-import java.util.function.ToDoubleFunction;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.phases.common.inlining.walker.CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER;
@@ -95,7 +93,6 @@
      */
     private final ArrayDeque<CallsiteHolder> graphQueue = new ArrayDeque<>();
     private final ArrayDeque<MethodInvocation> invocationQueue = new ArrayDeque<>();
-    private final ToDoubleFunction<FixedNode> probabilities = new FixedNodeProbabilityCache();
 
     private final HighTierContext context;
     private final int maxMethodPerInlining;
@@ -426,7 +423,7 @@
         Assumptions callerAssumptions = parentInvocation.assumptions();
         metricInliningConsidered.increment();
 
-        if (inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), calleeInvocation, inliningDepth, true)) {
+        if (inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true)) {
             doInline(callerCallsiteHolder, calleeInvocation, callerAssumptions);
             return true;
         }
@@ -683,7 +680,7 @@
 
         final MethodInvocation currentInvocation = currentInvocation();
 
-        final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), currentInvocation, inliningDepth(), false));
+        final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, inliningDepth(), false));
         if (backtrack) {
             int remainingGraphs = currentInvocation.totalGraphs() - currentInvocation.processedGraphs();
             assert remainingGraphs > 0;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Tue Sep 09 14:31:36 2014 -0700
@@ -104,7 +104,11 @@
             if (current instanceof MergeNode) {
                 MergeNode currentMerge = (MergeNode) current;
                 NodeInputList<AbstractEndNode> currentForwardEnds = currentMerge.forwardEnds();
-                // Using simple iteration instead of lambda as the lambda blows up the stack
+                /*
+                 * Use simple iteration instead of streams, since the stream infrastructure adds
+                 * many frames which causes the recursion to overflow the stack earlier than it
+                 * would otherwise.
+                 */
                 for (AbstractEndNode endNode : currentForwardEnds) {
                     probability += applyAsDouble(endNode);
                 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -625,10 +625,8 @@
             cdbc.apply(cfg.getNodeToBlock().get(succ));
         }
         ensureScheduledUsages(node, strategy);
-        if (node.recordsUsages()) {
-            for (Node usage : node.usages()) {
-                blocksForUsage(node, usage, cdbc, strategy);
-            }
+        for (Node usage : node.usages()) {
+            blocksForUsage(node, usage, cdbc, strategy);
         }
 
         if (assertionEnabled()) {
@@ -820,10 +818,8 @@
     }
 
     private void ensureScheduledUsages(Node node, SchedulingStrategy strategy) {
-        if (node.recordsUsages()) {
-            for (Node usage : node.usages().filter(ScheduledNode.class)) {
-                assignBlockToNode((ScheduledNode) usage, strategy);
-            }
+        for (Node usage : node.usages().filter(ScheduledNode.class)) {
+            assignBlockToNode((ScheduledNode) usage, strategy);
         }
         // now true usages are ready
     }
@@ -1149,16 +1145,14 @@
             }
 
             visited.mark(instruction);
-            if (instruction.recordsUsages()) {
-                for (Node usage : instruction.usages()) {
-                    if (usage instanceof VirtualState) {
-                        // only fixed nodes can have VirtualState -> no need to schedule them
+            for (Node usage : instruction.usages()) {
+                if (usage instanceof VirtualState) {
+                    // only fixed nodes can have VirtualState -> no need to schedule them
+                } else {
+                    if (instruction instanceof LoopExitNode && usage instanceof ProxyNode) {
+                        // value proxies should be scheduled before the loopexit, not after
                     } else {
-                        if (instruction instanceof LoopExitNode && usage instanceof ProxyNode) {
-                            // value proxies should be scheduled before the loopexit, not after
-                        } else {
-                            addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited);
-                        }
+                        addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited);
                     }
                 }
             }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Tue Sep 09 14:31:36 2014 -0700
@@ -33,6 +33,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -128,7 +129,8 @@
     private void writeGraph(Graph graph, SchedulePhase predefinedSchedule) throws IOException {
         SchedulePhase schedule = predefinedSchedule;
         if (schedule == null) {
-            if (PrintIdealGraphSchedule.getValue()) {
+            // Also provide a schedule when an error occurs
+            if (PrintIdealGraphSchedule.getValue() || Debug.contextLookup(Throwable.class) != null) {
                 try {
                     schedule = new SchedulePhase();
                     schedule.apply((StructuredGraph) graph);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Sep 09 14:31:36 2014 -0700
@@ -343,7 +343,7 @@
         out.println("=== Succesors ===");
         printNamedNodes(node, node.successors().iterator(), "", "\n", null);
         out.println("=== Usages ===");
-        if (node.recordsUsages() && !node.usages().isEmpty()) {
+        if (!node.usages().isEmpty()) {
             for (Node usage : node.usages()) {
                 out.print(nodeToString(usage)).print(" ");
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -343,8 +343,7 @@
     }
 
     public void cleanUpReturnCheckCast(Node newInstance) {
-        if (newInstance.recordsUsages() && newInstance instanceof ValueNode &&
-                        (((ValueNode) newInstance).getKind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) {
+        if (newInstance instanceof ValueNode && (((ValueNode) newInstance).getKind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) {
             StructuredGraph graph = (StructuredGraph) newInstance.graph();
             for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) {
                 for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Sep 09 14:31:36 2014 -0700
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -511,7 +512,7 @@
                     new CollapseFrameForSingleSideEffectPhase().apply(graph);
                     break;
             }
-            new DeadCodeEliminationPhase().apply(graph);
+            new DeadCodeEliminationPhase(REQUIRED).apply(graph);
         }
 
         /**
@@ -613,7 +614,7 @@
          */
         protected void afterInlining(StructuredGraph graph) {
             new NodeIntrinsificationPhase(providers, snippetReflection).apply(graph);
-            new DeadCodeEliminationPhase().apply(graph);
+            new DeadCodeEliminationPhase(OPTIONAL).apply(graph);
             if (OptCanonicalizer.getValue()) {
                 new CanonicalizerPhase(true).apply(graph, new PhaseContext(providers, assumptions));
             }
@@ -686,7 +687,7 @@
                     end.disableSafepoint();
                 }
 
-                new DeadCodeEliminationPhase().apply(graph);
+                new DeadCodeEliminationPhase(REQUIRED).apply(graph);
             } catch (Throwable e) {
                 throw Debug.handle(e);
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Sep 09 14:31:36 2014 -0700
@@ -26,6 +26,7 @@
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.debug.Debug.*;
 import static com.oracle.graal.graph.util.CollectionsAccess.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
 import static com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates.*;
 import static java.util.FormattableFlags.*;
 
@@ -670,7 +671,7 @@
             }
         }
 
-        new DeadCodeEliminationPhase().apply(snippetCopy);
+        new DeadCodeEliminationPhase(REQUIRED).apply(snippetCopy);
 
         assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders);
 
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Tue Sep 09 14:31:36 2014 -0700
@@ -377,8 +377,8 @@
     }
 
     @Override
-    public List<RootCallTarget> getCallTargets() {
-        return new ArrayList<>(callTargets.keySet());
+    public Collection<RootCallTarget> getCallTargets() {
+        return Collections.unmodifiableSet(callTargets.keySet());
     }
 
     public void notifyTransferToInterpreter() {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Tue Sep 09 14:31:36 2014 -0700
@@ -206,13 +206,13 @@
     @Override
     public void invalidate() {
         this.runtime.invalidateInstalledCode(this);
-        invalidateInlining();
     }
 
     protected void invalidate(Node oldNode, Node newNode, CharSequence reason) {
         if (isValid()) {
             CompilerAsserts.neverPartOfCompilation();
             invalidate();
+            invalidateInlining();
             compilationProfile.reportInvalidated();
             logOptimizedInvalidated(this, oldNode, newNode, reason);
         }
@@ -273,14 +273,15 @@
             // Compilation was successful.
         } else {
             compilationPolicy.recordCompilationFailure(t);
-            logOptimizingFailed(this, t.getMessage());
             if (t instanceof BailoutException) {
+                logOptimizingFailed(this, t.getMessage());
                 // Bailout => move on.
-            } else {
-                if (TruffleCompilationExceptionsAreFatal.getValue()) {
-                    t.printStackTrace(OUT);
-                    System.exit(-1);
-                }
+            } else if (TruffleCompilationExceptionsAreFatal.getValue()) {
+                logOptimizingFailed(this, t.getMessage());
+                t.printStackTrace(OUT);
+                System.exit(-1);
+            } else if (TruffleCompilationExceptionsAreThrown.getValue()) {
+                throw new OptimizationFailedException(t, rootNode);
             }
         }
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Sep 09 14:31:36 2014 -0700
@@ -132,17 +132,27 @@
             }
             HighTierContext tierContext = new HighTierContext(providers, assumptions, graphCache, new PhaseSuite<HighTierContext>(), OptimisticOptimizations.NONE);
 
-            for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) {
-                Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage());
-                throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception);
-            }
-
             // EA frame and clean up.
             try (Scope pe = Debug.scope("TrufflePartialEscape", graph)) {
                 new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext);
             } catch (Throwable t) {
                 Debug.handle(t);
             }
+
+            // to make frame propagations visible retry expandTree
+            while (expandTree(graph, assumptions)) {
+                try (Scope pe = Debug.scope("TrufflePartialEscape", graph)) {
+                    new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext);
+                } catch (Throwable t) {
+                    Debug.handle(t);
+                }
+            }
+
+            for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) {
+                Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage());
+                throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception);
+            }
+
             new VerifyNoIntrinsicsLeftPhase().apply(graph, false);
             for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) {
                 materializeNode.replaceAtUsages(materializeNode.getFrame());
@@ -184,15 +194,16 @@
         new DebugHistogramAsciiPrinter(TTY.out().out()).print(histogram);
     }
 
-    private void expandTree(StructuredGraph graph, Assumptions assumptions) {
+    private boolean expandTree(StructuredGraph graph, Assumptions assumptions) {
         PhaseContext phaseContext = new PhaseContext(providers, assumptions);
         TruffleExpansionLogger expansionLogger = null;
         if (TraceTruffleExpansion.getValue()) {
             expansionLogger = new TruffleExpansionLogger(providers, graph);
         }
-        boolean changed;
+        boolean changed = false;
+        boolean changedInIteration;
         do {
-            changed = false;
+            changedInIteration = false;
             for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class)) {
                 InvokeKind kind = methodCallTargetNode.invokeKind();
                 try (Indent id1 = Debug.logAndIndent("try inlining %s, kind = %s", methodCallTargetNode.targetMethod(), kind)) {
@@ -205,7 +216,7 @@
                         Class<? extends FixedWithNextNode> macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod());
                         if (macroSubstitution != null) {
                             InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution);
-                            changed = true;
+                            changed = changedInIteration = true;
                             continue;
                         }
 
@@ -215,7 +226,8 @@
                         }
 
                         if (inlineGraph != null) {
-                            changed = expandTreeInline(graph, phaseContext, expansionLogger, methodCallTargetNode, inlineGraph);
+                            expandTreeInline(graph, phaseContext, expansionLogger, methodCallTargetNode, inlineGraph);
+                            changed = changedInIteration = true;
                         }
                     }
                 }
@@ -224,14 +236,15 @@
                     throw new BailoutException("Truffle compilation is exceeding maximum node count: " + graph.getNodeCount());
                 }
             }
-        } while (changed);
+        } while (changedInIteration);
 
         if (TraceTruffleExpansion.getValue()) {
             expansionLogger.print();
         }
+        return changed;
     }
 
-    private boolean expandTreeInline(StructuredGraph graph, PhaseContext phaseContext, TruffleExpansionLogger expansionLogger, MethodCallTargetNode methodCallTargetNode, StructuredGraph inlineGraph) {
+    private void expandTreeInline(StructuredGraph graph, PhaseContext phaseContext, TruffleExpansionLogger expansionLogger, MethodCallTargetNode methodCallTargetNode, StructuredGraph inlineGraph) {
         try (Indent indent = Debug.logAndIndent("inline graph %s", methodCallTargetNode.targetMethod())) {
             int nodeCountBefore = graph.getNodeCount();
             if (TraceTruffleExpansion.getValue()) {
@@ -248,8 +261,6 @@
             }
             AbstractInlineInfo.getInlinedParameterUsages(canonicalizedNodes, inlineGraph, inlined);
             canonicalizer.applyIncremental(graph, phaseContext, canonicalizedNodes);
-
-            return true;
         }
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Tue Sep 09 14:31:36 2014 -0700
@@ -243,7 +243,7 @@
         Mark beforeInvokeMark = graph.getMark();
         expandInvoke(methodCallTarget);
         for (Node arg : argumentSnapshot) {
-            if (arg != null && arg.recordsUsages()) {
+            if (arg != null) {
                 for (Node argUsage : arg.usages()) {
                     if (graph.isNew(beforeInvokeMark, argUsage) && argUsage instanceof Canonicalizable) {
                         canonicalizerUsages.add(argUsage);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Tue Sep 09 14:31:36 2014 -0700
@@ -116,6 +116,8 @@
     @Option(help = "")
     public static final OptionValue<Boolean> TruffleCompilationExceptionsAreFatal = new OptionValue<>(false);
     @Option(help = "")
+    public static final OptionValue<Boolean> TruffleCompilationExceptionsAreThrown = new OptionValue<>(false);
+    @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleInlining = new OptionValue<>(false);
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleSplitting = new OptionValue<>(false);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.virtual.phases.ea;
 
 import static com.oracle.graal.debug.Debug.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
 
 import java.util.*;
 
@@ -100,7 +101,7 @@
                     Debug.dump(graph, "after " + getName() + " iteration");
                 }
 
-                new DeadCodeEliminationPhase().apply(graph);
+                new DeadCodeEliminationPhase(REQUIRED).apply(graph);
 
                 Set<Node> changedNodes = listener.getNodes();
                 for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.debug.Debug.*;
+import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
 
 import java.util.*;
 
@@ -70,7 +71,7 @@
                 inlining.apply(graph, context);
                 progress |= inlining.getInliningCount() > 0;
 
-                new DeadCodeEliminationPhase().apply(graph);
+                new DeadCodeEliminationPhase(OPTIONAL).apply(graph);
 
                 boolean reduceOrEliminate = FlowSensitiveReduction.getValue() || ConditionalElimination.getValue();
                 if (reduceOrEliminate && OptCanonicalizer.getValue()) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Tue Sep 09 14:31:36 2014 -0700
@@ -62,9 +62,6 @@
         InferStamps.inferStamps(graph);
 
         for (ValueNode node : graph.getNodes().filter(ValueNode.class)) {
-            if (!node.recordsUsages()) {
-                continue;
-            }
             for (Node usage : node.usages()) {
                 if (usage instanceof AccessMonitorNode) {
                     verify(!isWord(node), node, usage, "word value has no monitor");
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -86,7 +86,7 @@
     public void testGetCallTargets1() {
         RootNode rootNode = createTestRootNode();
         RootCallTarget target = runtime.createCallTarget(rootNode);
-        assertTrue(runtime.getCallTargets().indexOf(target) != -1);
+        assertTrue(runtime.getCallTargets().contains(target));
     }
 
     @Test
@@ -94,8 +94,8 @@
         RootNode rootNode = createTestRootNode();
         RootCallTarget target1 = runtime.createCallTarget(rootNode);
         RootCallTarget target2 = runtime.createCallTarget(rootNode);
-        assertTrue(runtime.getCallTargets().indexOf(target1) != -1);
-        assertTrue(runtime.getCallTargets().indexOf(target2) != -1);
+        assertTrue(runtime.getCallTargets().contains(target1));
+        assertTrue(runtime.getCallTargets().contains(target2));
     }
 
     /*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/BytesSourceSectionTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.source;
+
+import static org.junit.Assert.*;
+
+import java.nio.charset.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.source.*;
+
+public class BytesSourceSectionTest {
+
+    @Test
+    public void testSectionsFromLineNumberASCII() {
+        final byte[] bytes = "foo\nbar\nbaz\n".getBytes(StandardCharsets.UTF_8);
+        final Source source = Source.fromBytes(bytes, "description", new BytesDecoder.UTF8BytesDecoder());
+        assertEquals("foo", source.createSection("identifier", 1).getCode());
+        assertEquals("bar", source.createSection("identifier", 2).getCode());
+        assertEquals("baz", source.createSection("identifier", 3).getCode());
+    }
+
+    @Test
+    public void testSectionsFromOffsetsASCII() {
+        final byte[] bytes = "foo\nbar\nbaz\n".getBytes(StandardCharsets.UTF_8);
+        final Source source = Source.fromBytes(bytes, "description", new BytesDecoder.UTF8BytesDecoder());
+        assertEquals("foo", source.createSection("identifier", 0, 3).getCode());
+        assertEquals("bar", source.createSection("identifier", 4, 3).getCode());
+        assertEquals("baz", source.createSection("identifier", 8, 3).getCode());
+    }
+
+    @Test
+    public void testSectionsFromLineNumberUTF8() {
+        // ☃ is three bytes in UTF8
+        final byte[] bytes = "foo\n☃\nbaz\n".getBytes(StandardCharsets.UTF_8);
+        final Source source = Source.fromBytes(bytes, "description", new BytesDecoder.UTF8BytesDecoder());
+        assertEquals("foo", source.createSection("identifier", 1).getCode());
+        assertEquals("☃", source.createSection("identifier", 2).getCode());
+        assertEquals("baz", source.createSection("identifier", 3).getCode());
+    }
+
+    @Test
+    public void testSectionsFromOffsetsUTF8() {
+        // ☃ is three bytes in UTF8
+        final byte[] bytes = "foo\n☃\nbaz\n".getBytes(StandardCharsets.UTF_8);
+        final Source source = Source.fromBytes(bytes, "description", new BytesDecoder.UTF8BytesDecoder());
+        assertEquals("foo", source.createSection("identifier", 0, 3).getCode());
+        assertEquals("☃", source.createSection("identifier", 4, 3).getCode());
+        assertEquals("baz", source.createSection("identifier", 8, 3).getCode());
+    }
+
+    @Test
+    public void testOffset() {
+        final byte[] bytes = "xxxfoo\nbar\nbaz\nxxx".getBytes(StandardCharsets.UTF_8);
+        final Source source = Source.fromBytes(bytes, 3, bytes.length - 6, "description", new BytesDecoder.UTF8BytesDecoder());
+        assertEquals("foo", source.createSection("identifier", 0, 3).getCode());
+        assertEquals("bar", source.createSection("identifier", 4, 3).getCode());
+        assertEquals("baz", source.createSection("identifier", 8, 3).getCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/ExactClassValueProfileTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,106 @@
+/*
+ * 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.truffle.api.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class ExactClassValueProfileTest {
+
+    @DataPoint public static final String O1 = new String();
+    @DataPoint public static final String O2 = new String();
+    @DataPoint public static final Object O3 = new Object();
+    @DataPoint public static final Integer O4 = new Integer(1);
+    @DataPoint public static final Integer O5 = null;
+
+    private ExactClassValueProfile profile;
+
+    @Before
+    public void create() {
+        profile = (ExactClassValueProfile) ValueProfile.createClassProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.isGeneric(), is(false));
+        assertThat(profile.isUninitialized(), is(true));
+        assertNull(profile.getCachedClass());
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOne(Object value) {
+        Object result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedClass(), expectedClass(value));
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwo(Object value0, Object value1) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+
+        Object expectedClass = expectedClass(value0) == expectedClass(value1) ? expectedClass(value0) : Object.class;
+
+        assertEquals(profile.getCachedClass(), expectedClass);
+        assertThat(profile.isUninitialized(), is(false));
+        assertThat(profile.isGeneric(), is(expectedClass == Object.class));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThree(Object value0, Object value1, Object value2) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+        Object result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+
+        Object expectedClass = expectedClass(value0) == expectedClass(value1) && expectedClass(value1) == expectedClass(value2) ? expectedClass(value0) : Object.class;
+
+        assertEquals(profile.getCachedClass(), expectedClass);
+        assertThat(profile.isUninitialized(), is(false));
+        assertThat(profile.isGeneric(), is(expectedClass == Object.class));
+        profile.toString(); // test that it is not crashing
+    }
+
+    private static Class<?> expectedClass(Object value) {
+        return value == null ? Object.class : value.getClass();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/IdentityValueProfileTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,104 @@
+/*
+ * 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.truffle.api.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class IdentityValueProfileTest {
+
+    @DataPoint public static final String O1 = new String();
+    @DataPoint public static final String O2 = O1;
+    @DataPoint public static final Object O3 = new Object();
+    @DataPoint public static final Integer O4 = new Integer(1);
+    @DataPoint public static final Integer O5 = null;
+
+    private IdentityValueProfile profile;
+
+    @Before
+    public void create() {
+        profile = (IdentityValueProfile) ValueProfile.createIdentityProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.isGeneric(), is(false));
+        assertThat(profile.isUninitialized(), is(true));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOne(Object value) {
+        Object result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwo(Object value0, Object value1) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+
+        if (value0 == value1) {
+            assertThat(profile.getCachedValue(), is(value0));
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThree(Object value0, Object value1, Object value2) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+        Object result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+
+        if (value0 == value1 && value1 == value2) {
+            assertThat(profile.getCachedValue(), is(value0));
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/NeverValidAssumptionTest.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 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.truffle.api.test.utilities;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
+
+public class NeverValidAssumptionTest {
+
+    @Test
+    public void testCheck() {
+        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
+
+        try {
+            assumption.check();
+            fail();
+        } catch (InvalidAssumptionException e) {
+        } catch (Exception e) {
+            fail();
+        }
+    }
+
+    @Test
+    public void testIsValid() {
+        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
+        assertFalse(assumption.isValid());
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testCannotInvalidate() {
+        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
+        assumption.invalidate();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/OptimizationFailedException.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api;
+
+import com.oracle.truffle.api.nodes.*;
+
+public class OptimizationFailedException extends RuntimeException {
+
+    private final RootNode rootNode;
+
+    public OptimizationFailedException(Throwable cause, RootNode rootNode) {
+        super(cause);
+        this.rootNode = rootNode;
+    }
+
+    public RootNode getRootNode() {
+        return rootNode;
+    }
+
+    private static final long serialVersionUID = -8797188744430210785L;
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Tue Sep 09 14:31:36 2014 -0700
@@ -142,7 +142,7 @@
      * Returns a list of all still referenced {@link RootCallTarget} instances that were created
      * using {@link #createCallTarget(RootNode)}.
      */
-    List<RootCallTarget> getCallTargets();
+    Collection<RootCallTarget> getCallTargets();
 
     /**
      * Internal API method. Do not use.
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Tue Sep 09 14:31:36 2014 -0700
@@ -135,8 +135,8 @@
     }
 
     @Override
-    public List<RootCallTarget> getCallTargets() {
-        return new ArrayList<>(callTargets.keySet());
+    public Collection<RootCallTarget> getCallTargets() {
+        return Collections.unmodifiableSet(callTargets.keySet());
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java	Tue Sep 09 14:31:36 2014 -0700
@@ -145,4 +145,19 @@
 
         return probes;
     }
+
+    public void forget(Source source) {
+        final Set<LineLocation> mappedLines = lineToProbesMap.keySet();
+        if (mappedLines.size() > 0) {
+            List<LineLocation> forgetLines = new ArrayList<>();
+            for (LineLocation line : mappedLines) {
+                if (line.getSource().equals(source)) {
+                    forgetLines.add(line);
+                }
+            }
+            for (LineLocation line : forgetLines) {
+                lineToProbesMap.remove(line);
+            }
+        }
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java	Tue Sep 09 14:31:36 2014 -0700
@@ -38,7 +38,7 @@
      *
      * @param engine a just-created engine
      */
-    protected void engineCreated(ScriptEngine engine) {
+    protected final void engineCreated(ScriptEngine engine) {
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/BytesDecoder.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,66 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.source;
+
+import java.nio.charset.*;
+import java.util.*;
+
+/**
+ * For a language where strings do not map into Java strings, provides utilities to find line
+ * endings and to decode raw bytes into an approximate representation for tools to display.
+ * <p>
+ * See {@link Source#fromBytes}.
+ */
+public interface BytesDecoder {
+
+    String decode(byte[] bytes, int byteIndex, int length);
+
+    void decodeLines(byte[] bytes, int byteIndex, int length, LineMarker lineMarker);
+
+    public interface LineMarker {
+
+        void markLine(int index);
+
+    }
+
+    public static class UTF8BytesDecoder implements BytesDecoder {
+
+        @Override
+        public String decode(byte[] bytes, int byteIndex, int length) {
+            return new String(Arrays.copyOfRange(bytes, byteIndex, byteIndex + length), StandardCharsets.UTF_8);
+        }
+
+        @Override
+        public void decodeLines(byte[] bytes, int byteIndex, int length, LineMarker lineMarker) {
+            for (int n = byteIndex; n < byteIndex + length; n++) {
+                if (bytes[n] == '\n') {
+                    lineMarker.markLine(n + 1);
+                }
+            }
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Tue Sep 09 14:31:36 2014 -0700
@@ -158,6 +158,37 @@
     }
 
     /**
+     * Creates a source from raw bytes. This can be used if the encoding of strings in your language
+     * is not compatible with Java strings, or if your parser returns byte indices instead of
+     * character indices. The returned source is then indexed by byte, not by character.
+     *
+     * @param bytes the raw bytes of the source
+     * @param description a note about the origin, possibly useful for debugging
+     * @param decoder how to decode the bytes into Java strings
+     * @return a newly created, non-indexed source representation
+     */
+    public static Source fromBytes(byte[] bytes, String description, BytesDecoder decoder) {
+        return fromBytes(bytes, 0, bytes.length, description, decoder);
+    }
+
+    /**
+     * Creates a source from raw bytes. This can be used if the encoding of strings in your language
+     * is not compatible with Java strings, or if your parser returns byte indices instead of
+     * character indices. The returned source is then indexed by byte, not by character. Offsets are
+     * relative to byteIndex.
+     *
+     * @param bytes the raw bytes of the source
+     * @param byteIndex where the string starts in the byte array
+     * @param length the length of the string in the byte array
+     * @param description a note about the origin, possibly useful for debugging
+     * @param decoder how to decode the bytes into Java strings
+     * @return a newly created, non-indexed source representation
+     */
+    public static Source fromBytes(byte[] bytes, int byteIndex, int length, String description, BytesDecoder decoder) {
+        return new BytesSource(description, bytes, byteIndex, length, decoder);
+    }
+
+    /**
      * Creates a source from literal text, but which acts as a file and can be retrieved by name
      * (unlike other literal sources); intended for testing.
      *
@@ -246,6 +277,10 @@
      */
     public abstract String getCode();
 
+    public String getCode(int charIndex, int charLength) {
+        return getCode().substring(charIndex, charIndex + charLength);
+    }
+
     /**
      * Gets the text (not including a possible terminating newline) in a (1-based) numbered line.
      */
@@ -368,10 +403,7 @@
      * @throws IllegalStateException if the source is one of the "null" instances
      */
     public final SourceSection createSection(String identifier, int charIndex, int length) throws IllegalArgumentException {
-        final int codeLength = getCode().length();
-        if (!(charIndex >= 0 && length >= 0 && charIndex + length <= codeLength)) {
-            throw new IllegalArgumentException("text positions out of range");
-        }
+        checkRange(charIndex, length);
         checkTextMap();
         final int startLine = getLineNumber(charIndex);
         final int startColumn = charIndex - getLineStartOffset(startLine) + 1;
@@ -379,6 +411,12 @@
         return new DefaultSourceSection(this, identifier, startLine, startColumn, charIndex, length);
     }
 
+    protected void checkRange(int charIndex, int length) {
+        if (!(charIndex >= 0 && length >= 0 && charIndex + length <= getCode().length())) {
+            throw new IllegalArgumentException("text positions out of range");
+        }
+    }
+
     /**
      * Creates a representation of a line of text in the source identified only by line number, from
      * which the character information will be computed.
@@ -409,15 +447,19 @@
 
     private TextMap checkTextMap() {
         if (textMap == null) {
-            final String code = getCode();
-            if (code == null) {
-                throw new RuntimeException("can't read file " + getName());
-            }
-            textMap = new TextMap(code);
+            textMap = createTextMap();
         }
         return textMap;
     }
 
+    protected TextMap createTextMap() {
+        final String code = getCode();
+        if (code == null) {
+            throw new RuntimeException("can't read file " + getName());
+        }
+        return TextMap.fromString(code);
+    }
+
     private static final class LiteralSource extends Source {
 
         private final String name; // Name used originally to describe the source
@@ -621,6 +663,74 @@
 
     }
 
+    private static final class BytesSource extends Source {
+
+        private final String name;
+        private final byte[] bytes;
+        private final int byteIndex;
+        private final int length;
+        private final BytesDecoder decoder;
+
+        public BytesSource(String name, byte[] bytes, int byteIndex, int length, BytesDecoder decoder) {
+            this.name = name;
+            this.bytes = bytes;
+            this.byteIndex = byteIndex;
+            this.length = length;
+            this.decoder = decoder;
+        }
+
+        @Override
+        protected void reset() {
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String getShortName() {
+            return name;
+        }
+
+        @Override
+        public String getPath() {
+            return name;
+        }
+
+        @Override
+        public URL getURL() {
+            return null;
+        }
+
+        @Override
+        public Reader getReader() {
+            return null;
+        }
+
+        @Override
+        public String getCode() {
+            return decoder.decode(bytes, byteIndex, length);
+        }
+
+        @Override
+        public String getCode(int byteOffset, int codeLength) {
+            return decoder.decode(bytes, byteIndex + byteOffset, codeLength);
+        }
+
+        @Override
+        protected void checkRange(int charIndex, int rangeLength) {
+            if (!(charIndex >= 0 && rangeLength >= 0 && charIndex + rangeLength <= length)) {
+                throw new IllegalArgumentException("text positions out of range");
+            }
+        }
+
+        @Override
+        protected TextMap createTextMap() {
+            return TextMap.fromBytes(bytes, byteIndex, length, decoder);
+        }
+    }
+
     private static final class DefaultSourceSection implements SourceSection {
 
         private final Source source;
@@ -704,7 +814,7 @@
 
         @Override
         public final String getCode() {
-            return getSource().getCode().substring(charIndex, charIndex + charLength);
+            return getSource().getCode(charIndex, charLength);
         }
 
         @Override
@@ -866,12 +976,18 @@
         // Is the final text character a newline?
         final boolean finalNL;
 
+        public TextMap(int[] nlOffsets, int textLength, boolean finalNL) {
+            this.nlOffsets = nlOffsets;
+            this.textLength = textLength;
+            this.finalNL = finalNL;
+        }
+
         /**
          * Constructs map permitting translation between 0-based character offsets and 1-based
          * lines/columns.
          */
-        public TextMap(String text) {
-            this.textLength = text.length();
+        public static TextMap fromString(String text) {
+            final int textLength = text.length();
             final ArrayList<Integer> lines = new ArrayList<>();
             lines.add(0);
             int offset = 0;
@@ -887,12 +1003,37 @@
             }
             lines.add(Integer.MAX_VALUE);
 
-            nlOffsets = new int[lines.size()];
+            final int[] nlOffsets = new int[lines.size()];
             for (int line = 0; line < lines.size(); line++) {
                 nlOffsets[line] = lines.get(line);
             }
 
-            finalNL = textLength > 0 && (textLength == nlOffsets[nlOffsets.length - 2]);
+            final boolean finalNL = textLength > 0 && (textLength == nlOffsets[nlOffsets.length - 2]);
+
+            return new TextMap(nlOffsets, textLength, finalNL);
+        }
+
+        public static TextMap fromBytes(byte[] bytes, int byteIndex, int length, BytesDecoder bytesDecoder) {
+            final ArrayList<Integer> lines = new ArrayList<>();
+            lines.add(0);
+
+            bytesDecoder.decodeLines(bytes, byteIndex, length, new BytesDecoder.LineMarker() {
+
+                public void markLine(int index) {
+                    lines.add(index);
+                }
+            });
+
+            lines.add(Integer.MAX_VALUE);
+
+            final int[] nlOffsets = new int[lines.size()];
+            for (int line = 0; line < lines.size(); line++) {
+                nlOffsets[line] = lines.get(line);
+            }
+
+            final boolean finalNL = length > 0 && (length == nlOffsets[nlOffsets.length - 2]);
+
+            return new TextMap(nlOffsets, length, finalNL);
         }
 
         /**
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AssumedValue.java	Tue Sep 09 12:22:48 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AssumedValue.java	Tue Sep 09 14:31:36 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -35,12 +35,19 @@
  */
 public class AssumedValue<T> {
 
+    private final String name;
+
     @CompilationFinal private T value;
-    private final CyclicAssumption assumption;
+    @CompilationFinal private Assumption assumption;
+
+    public AssumedValue(T initialValue) {
+        this(null, initialValue);
+    }
 
     public AssumedValue(String name, T initialValue) {
-        assumption = new CyclicAssumption(name);
+        this.name = name;
         value = initialValue;
+        assumption = Truffle.getRuntime().createAssumption(name);
     }
 
     /**
@@ -49,9 +56,9 @@
      */
     public T get() {
         try {
-            assumption.getAssumption().check();
+            assumption.check();
         } catch (InvalidAssumptionException e) {
-            // No need to rewrite anything - just pick up the new value
+            // No need to rewrite anything - just pick up the new values
         }
 
         return value;
@@ -61,8 +68,12 @@
      * Set a new value, which will be picked up the next time {@link #get} is called.
      */
     public void set(T newValue) {
+        CompilerDirectives.transferToInterpreter();
+
         value = newValue;
-        assumption.invalidate();
+        final Assumption oldAssumption = assumption;
+        assumption = Truffle.getRuntime().createAssumption(name);
+        oldAssumption.invalidate();
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ExactClassValueProfile.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,72 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+
+/**
+ * Represents a {@link ValueProfile} that speculates on the exact class of a value.
+ */
+public final class ExactClassValueProfile extends ValueProfile {
+
+    @CompilationFinal protected Class<?> cachedClass;
+
+    ExactClassValueProfile() {
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T profile(T value) {
+        if (cachedClass != null && cachedClass.isInstance(value)) {
+            return (T) cachedClass.cast(value);
+        } else {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            if (cachedClass == null && value != null) {
+                cachedClass = value.getClass();
+            } else {
+                cachedClass = Object.class;
+            }
+        }
+        return value;
+    }
+
+    public boolean isGeneric() {
+        return cachedClass == Object.class;
+    }
+
+    public boolean isUninitialized() {
+        return cachedClass == null;
+    }
+
+    public Class<?> getCachedClass() {
+        return cachedClass;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(%s)@%x", getClass().getSimpleName(), isUninitialized() ? "uninitialized" : (isGeneric() ? "generic" : cachedClass.getName()), hashCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/IdentityValueProfile.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,80 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.utilities;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+
+/**
+ * Represents a {@link ValueProfile} that speculates on the object identity of a value.
+ */
+public final class IdentityValueProfile extends ValueProfile {
+
+    private static final Object UNINITIALIZED = new Object();
+    private static final Object GENERIC = new Object();
+
+    @CompilationFinal protected Object cachedValue = UNINITIALIZED;
+
+    IdentityValueProfile() {
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T profile(T value) {
+        if (cachedValue != GENERIC) {
+            if (cachedValue == value) {
+                return (T) cachedValue;
+            } else {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (cachedValue == UNINITIALIZED) {
+                    cachedValue = value;
+                } else {
+                    cachedValue = GENERIC;
+                }
+            }
+        }
+        return value;
+    }
+
+    public boolean isGeneric() {
+        return getCachedValue() == GENERIC;
+    }
+
+    public boolean isUninitialized() {
+        return getCachedValue() == UNINITIALIZED;
+    }
+
+    public Object getCachedValue() {
+        return cachedValue;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(%s)@%x", getClass().getSimpleName(), isUninitialized() ? "uninitialized" : (isGeneric() ? "generic" : String.format("@%x", Objects.hash(cachedValue))), hashCode());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/NeverValidAssumption.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An assumption that is never valid. Used as a placeholder where an assumption is needed that
+ * should be invalid from the start.
+ */
+public final class NeverValidAssumption implements Assumption {
+
+    public static final NeverValidAssumption INSTANCE = new NeverValidAssumption();
+
+    private NeverValidAssumption() {
+    }
+
+    @Override
+    public void check() throws InvalidAssumptionException {
+        throw new InvalidAssumptionException();
+    }
+
+    @Override
+    public void invalidate() {
+        throw new UnsupportedOperationException("Cannot invalidate this assumption - it is never valid");
+    }
+
+    @Override
+    public String getName() {
+        return getClass().getName();
+    }
+
+    @Override
+    public boolean isValid() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java	Tue Sep 09 14:31:36 2014 -0700
@@ -0,0 +1,62 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.utilities;
+
+/**
+ * Utility class to speculate on certain properties of values.
+ *
+ * Example usage:
+ *
+ * <pre>
+ * private final ValueProfile classProfile = ValueProfile.createClassProfile();
+ *
+ * return classProfile.profile(value);
+ * </pre>
+ *
+ * All instances of {@code ValueProfile} (and subclasses) must be held in {@code final} fields for
+ * compiler optimizations to take effect.
+ *
+ * @see #createIdentityProfile()
+ * @see #createClassProfile()
+ */
+public abstract class ValueProfile {
+
+    public abstract <T> T profile(T value);
+
+    /**
+     * Returns a {@link ValueProfile} that speculates on the exact class of a value.
+     */
+    public static ValueProfile createClassProfile() {
+        return new ExactClassValueProfile();
+    }
+
+    /**
+     * Returns a {@link ValueProfile} that speculates on the object identity of a value.
+     */
+    public static ValueProfile createIdentityProfile() {
+        return new IdentityValueProfile();
+    }
+
+}
--- a/mx/mx_graal.py	Tue Sep 09 12:22:48 2014 -0700
+++ b/mx/mx_graal.py	Tue Sep 09 14:31:36 2014 -0700
@@ -378,7 +378,9 @@
 def _jdksDir():
     return os.path.abspath(join(_installed_jdks if _installed_jdks else _graal_home, 'jdk' + str(mx.java().version)))
 
-def _handle_missing_VM(bld, vm):
+def _handle_missing_VM(bld, vm=None):
+    if not vm:
+        vm = _get_vm()
     mx.log('The ' + bld + ' ' + vm + ' VM has not been created')
     if sys.stdout.isatty():
         if mx.ask_yes_no('Build it now', 'y'):
@@ -387,10 +389,12 @@
             return
     mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM')
 
-def _jdk(build='product', vmToCheck=None, create=False, installJars=True):
+def _jdk(build=None, vmToCheck=None, create=False, installJars=True):
     """
     Get the JDK into which Graal is installed, creating it first if necessary.
     """
+    if not build:
+        build = _vmbuild if _vmSourcesAvailable else 'product'
     jdk = join(_jdksDir(), build)
     if create:
         srcJdk = mx.java().jdk
@@ -462,7 +466,7 @@
         if not exists(jdk):
             if _installed_jdks:
                 mx.log("The selected JDK directory does not (yet) exist: " + jdk)
-            _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal')
+            _handle_missing_VM(build, vmToCheck)
 
     if installJars:
         for jdkDist in _jdkDeployedDists:
@@ -655,8 +659,7 @@
 
 def jdkhome(vm=None):
     """return the JDK directory selected for the 'vm' command"""
-    build = _vmbuild if _vmSourcesAvailable else 'product'
-    return _jdk(build, installJars=False)
+    return _jdk(installJars=False)
 
 def print_jdkhome(args, vm=None):
     """print the JDK directory selected for the 'vm' command"""
@@ -975,7 +978,7 @@
     elif _vm_cwd is not None and _vm_cwd != cwd:
         mx.abort("conflicting working directories: do not set --vmcwd for this command")
 
-    build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
+    build = vmbuild if vmbuild else _vmbuild if _vmSourcesAvailable else 'product'
     jdk = _jdk(build, vmToCheck=vm, installJars=False)
     _updateInstalledGraalOptionsFile(jdk)
     mx.expand_project_in_args(args)
@@ -1331,6 +1334,41 @@
         mx.abort(codeOrMessage)
         return self
 
+def ctw(args):
+    """run CompileTheWorld"""
+    from sanitycheck import CTWMode
+    modes = {
+             'noinline' : CTWMode.NoInline,
+             'nocomplex' : CTWMode.NoComplex,
+             'full' : CTWMode.Full
+             }
+    mode = sanitycheck.CTWMode.NoInline
+    vmargs = []
+    for a in args:
+        m = modes.get(a, None)
+        if m:
+            mode = m
+        else:
+            vmargs.append(a)
+
+    jdk = _jdk(installJars=False)
+    rtjar = join(jdk, 'jre', 'lib', 'rt.jar')
+
+    vm_ = _get_vm()
+
+    args = vmargs + ['-XX:+CompileTheWorld', '-Xbootclasspath/p:' + rtjar]
+    if vm_ == 'graal':
+        args += ['-XX:+BootstrapGraal']
+    if mode >= CTWMode.NoInline:
+        if not isGraalEnabled(vm_):
+            args.append('-XX:-Inline')
+        else:
+            args.append('-G:-Inline')
+    if mode >= CTWMode.NoComplex:
+        if isGraalEnabled(vm_):
+            args += ['-G:-OptLoopTransform', '-G:-OptTailDuplication', '-G:-FullUnroll', '-G:-MemoryAwareScheduling', '-G:-NewMemoryAwareScheduling', '-G:-PartialEscapeAnalysis']
+    vm(args)
+
 def _basic_gate_body(args, tasks):
     t = Task('BuildHotSpotGraal: fastdebug,product')
     buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product'])
@@ -2248,6 +2286,7 @@
         'c1visualizer' : [c1visualizer, ''],
         'checkheaders': [checkheaders, ''],
         'clean': [clean, ''],
+        'ctw': [ctw, '[-vmoptions|noinline|nocomplex|full]'],
         'findbugs': [findbugs, ''],
         'generateZshCompletion' : [generateZshCompletion, ''],
         'hsdis': [hsdis, '[att]'],
--- a/mx/projects	Tue Sep 09 12:22:48 2014 -0700
+++ b/mx/projects	Tue Sep 09 14:31:36 2014 -0700
@@ -103,6 +103,7 @@
 distribution@TRUFFLE@path=build/truffle.jar
 distribution@TRUFFLE@subDir=graal
 distribution@TRUFFLE@sourcesPath=build/truffle.src.zip
+distribution@TRUFFLE@javaCompliance=1.7
 distribution@TRUFFLE@dependencies=\
 com.oracle.truffle.api.dsl,\
 com.oracle.nfi
@@ -119,6 +120,7 @@
 distribution@TRUFFLE-DSL-PROCESSOR@path=build/truffle-dsl-processor.jar
 distribution@TRUFFLE-DSL-PROCESSOR@subDir=graal
 distribution@TRUFFLE-DSL-PROCESSOR@sourcesPath=build/truffle-dsl-processor.src.zip
+distribution@TRUFFLE-DSL-PROCESSOR@javaCompliance=1.7
 distribution@TRUFFLE-DSL-PROCESSOR@dependencies=\
 com.oracle.truffle.dsl.processor
 distribution@TRUFFLE-DSL-PROCESSOR@distDependencies=TRUFFLE
--- a/mxtool/mx.py	Tue Sep 09 12:22:48 2014 -0700
+++ b/mxtool/mx.py	Tue Sep 09 14:31:36 2014 -0700
@@ -64,7 +64,7 @@
 A distribution is a jar or zip file containing the output from one or more Java projects.
 """
 class Distribution:
-    def __init__(self, suite, name, path, sourcesPath, deps, mainClass, excludedDependencies, distDependencies):
+    def __init__(self, suite, name, path, sourcesPath, deps, mainClass, excludedDependencies, distDependencies, javaCompliance):
         self.suite = suite
         self.name = name
         self.path = path.replace('/', os.sep)
@@ -75,6 +75,7 @@
         self.mainClass = mainClass
         self.excludedDependencies = excludedDependencies
         self.distDependencies = distDependencies
+        self.javaCompliance = JavaCompliance(javaCompliance) if javaCompliance else None
 
     def sorted_deps(self, includeLibs=False, transitive=False):
         deps = []
@@ -169,6 +170,10 @@
                     if isCoveredByDependecy:
                         continue
 
+                    if self.javaCompliance:
+                        if p.javaCompliance > self.javaCompliance:
+                            abort("Compliance level doesn't match: Distribution {0} requires {1}, but {2} is {3}.".format(self.name, self.javaCompliance, p.name, p.javaCompliance))
+
                     # skip a  Java project if its Java compliance level is "higher" than the configured JDK
                     jdk = java(p.javaCompliance)
                     assert jdk
@@ -930,7 +935,8 @@
             mainClass = attrs.pop('mainClass', None)
             exclDeps = pop_list(attrs, 'exclude')
             distDeps = pop_list(attrs, 'distDependencies')
-            d = Distribution(self, name, path, sourcesPath, deps, mainClass, exclDeps, distDeps)
+            javaCompliance = attrs.pop('javaCompliance', None)
+            d = Distribution(self, name, path, sourcesPath, deps, mainClass, exclDeps, distDeps, javaCompliance)
             d.__dict__.update(attrs)
             self.dists.append(d)
 
@@ -955,7 +961,8 @@
                 mainClass = None
                 exclDeps = []
                 distDeps = []
-                d = Distribution(self, dname, path, sourcesPath, deps, mainClass, exclDeps, distDeps)
+                javaCompliance = None
+                d = Distribution(self, dname, path, sourcesPath, deps, mainClass, exclDeps, distDeps, javaCompliance)
                 d.subDir = os.path.relpath(os.path.dirname(p.dir), self.dir)
                 self.dists.append(d)
                 p.definedAnnotationProcessors = annotationProcessors
@@ -2445,11 +2452,11 @@
         if p.definedAnnotationProcessorsDist:
             updatedAnnotationProcessorDists.add(p.definedAnnotationProcessorsDist)
 
+        tasks[p.name] = task
         if args.parallelize:
             # Best to initialize class paths on main process
             jdk.bootclasspath()
             task.proc = None
-            tasks[p.name] = task
         else:
             task.execute()
 
@@ -3107,11 +3114,12 @@
                 if config.exists():
                     os.unlink(config.path)
 
-    if args.dist:
-        for d in _dists.keys():
-            log('Removing distribution {0}...'.format(d))
-            _rmIfExists(distribution(d).path)
-            _rmIfExists(distribution(d).sourcesPath)
+    if args.java:
+        if args.dist:
+            for d in _dists.keys():
+                log('Removing distribution {0}...'.format(d))
+                _rmIfExists(distribution(d).path)
+                _rmIfExists(distribution(d).sourcesPath)
 
     if suppliedParser:
         return args
@@ -3970,14 +3978,14 @@
         out.open('source-roots')
         out.element('root', {'id' : 'src.dir'})
         if len(p.annotation_processors()) > 0:
-            out.element('root', {'id' : 'src.ap-source-output.dir'})
+            out.element('root', {'id' : 'src.ap-source-output.dir', 'name' : 'Generated Packages'})
         out.close('source-roots')
         out.open('test-roots')
         out.close('test-roots')
         out.close('data')
 
         firstDep = True
-        for dep in p.all_deps([], True):
+        for dep in p.all_deps([], includeLibs=False, includeAnnotationProcessors=True):
             if dep == p:
                 continue
 
@@ -4012,7 +4020,10 @@
         annotationProcessorSrcFolder = ""
         if len(p.annotation_processors()) > 0:
             annotationProcessorEnabled = "true"
-            annotationProcessorSrcFolder = "src.ap-source-output.dir=${build.generated.sources.dir}/ap-source-output"
+            genSrcDir = p.source_gen_dir()
+            if not exists(genSrcDir):
+                os.makedirs(genSrcDir)
+            annotationProcessorSrcFolder = "src.ap-source-output.dir=" + genSrcDir
 
         content = """
 annotation.processing.enabled=""" + annotationProcessorEnabled + """
@@ -4025,7 +4036,6 @@
 build.classes.excludes=**/*.java,**/*.form
 # This directory is removed when the project is cleaned:
 build.dir=bin
-build.generated.dir=${build.dir}/generated
 build.generated.sources.dir=${build.dir}/generated-sources
 # Only compile against the classpath explicitly listed here:
 build.sysclasspath=ignore
@@ -4046,7 +4056,7 @@
 includes=**
 jar.compress=false
 # Space-separated list of extra javac options
-javac.compilerargs=
+javac.compilerargs=-XDignore.symbol.file
 javac.deprecation=false
 javac.source=""" + str(p.javaCompliance) + """
 javac.target=""" + str(p.javaCompliance) + """
@@ -4090,13 +4100,11 @@
             srcDir = join(p.dir, src)
             if not exists(srcDir):
                 os.mkdir(srcDir)
-            ref = 'file.reference.' + p.name + '-' + src
-            print >> out, ref + '=' + src
             if mainSrc:
-                print >> out, 'src.dir=${' + ref + '}'
+                print >> out, 'src.dir=' + srcDir
                 mainSrc = False
             else:
-                print >> out, 'src.' + src + '.dir=${' + ref + '}'
+                print >> out, 'src.' + src + '.dir=' + srcDir
 
         javacClasspath = []
 
@@ -4117,24 +4125,19 @@
 
             if dep.isLibrary():
                 path = dep.get_path(resolve=True)
-                if path:
-                    if os.sep == '\\':
-                        path = path.replace('\\', '\\\\')
-                    ref = 'file.reference.' + dep.name + '-bin'
-                    print >> out, ref + '=' + path
-                    libFiles.append(path)
+                libFiles.append(path)
 
             elif dep.isProject():
-                n = dep.name.replace('.', '_')
-                relDepPath = os.path.relpath(dep.dir, p.dir).replace(os.sep, '/')
-                ref = 'reference.' + n + '.jar'
-                print >> out, 'project.' + n + '=' + relDepPath
-                print >> out, ref + '=${project.' + n + '}/dist/' + dep.name + '.jar'
-
-            if not dep in annotationProcessorOnlyDeps:
-                javacClasspath.append('${' + ref + '}')
-            else:
-                annotationProcessorReferences.append('${' + ref + '}')
+                path = join(dep.dir, 'dist', dep.name + '.jar')
+
+            if path:
+                if os.sep == '\\':
+                    path = path.replace('\\', '\\\\')
+
+                if not dep in annotationProcessorOnlyDeps:
+                    javacClasspath.append(path)
+                else:
+                    annotationProcessorReferences.append(path)
 
         print >> out, 'javac.classpath=\\\n    ' + (os.pathsep + '\\\n    ').join(javacClasspath)
         print >> out, 'javac.processorpath=' + (os.pathsep + '\\\n    ').join(['${javac.classpath}'] + annotationProcessorReferences)
@@ -4146,10 +4149,12 @@
 
     if updated:
         log('If using NetBeans:')
-        log('  1. Ensure that the following platform(s) are defined (Tools -> Java Platforms):')
+        # http://stackoverflow.com/questions/24720665/cant-resolve-jdk-internal-package
+        log('  1. Edit etc/netbeans.conf in your NetBeans installation and modify netbeans_default_options variable to include "-J-DCachingArchiveProvider.disableCtSym=true"')
+        log('  2. Ensure that the following platform(s) are defined (Tools -> Java Platforms):')
         for jdk in jdks:
             log('        JDK_' + str(jdk.version))
-        log('  2. Open/create a Project Group for the directory containing the projects (File -> Project Group -> New Group... -> Folder of Projects)')
+        log('  3. Open/create a Project Group for the directory containing the projects (File -> Project Group -> New Group... -> Folder of Projects)')
 
     _zip_files(files, suite.dir, configZip.path)
     _zip_files(libFiles, suite.dir, configLibsZip)
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Sep 09 14:31:36 2014 -0700
@@ -516,10 +516,11 @@
                               const VMRegPair *regs,
                               Label& skip_fixup);
   void gen_i2c_adapter(int total_args_passed,
-                              // VMReg max_arg,
-                              int comp_args_on_stack, // VMRegStackSlots
-                              const BasicType *sig_bt,
-                              const VMRegPair *regs);
+                       // VMReg max_arg,
+                       int comp_args_on_stack, // VMRegStackSlots
+                       const BasicType *sig_bt,
+                       const VMRegPair *regs,
+                       int frame_extension_argument = -1);
 
   AdapterGenerator(MacroAssembler *_masm) : masm(_masm) {}
 };
@@ -763,12 +764,13 @@
   __ bind(L_fail);
 }
 
-void AdapterGenerator::gen_i2c_adapter(
-                            int total_args_passed,
-                            // VMReg max_arg,
-                            int comp_args_on_stack, // VMRegStackSlots
-                            const BasicType *sig_bt,
-                            const VMRegPair *regs) {
+void AdapterGenerator::gen_i2c_adapter(int total_args_passed,
+                                       // VMReg max_arg,
+                                       int comp_args_on_stack, // VMRegStackSlots
+                                       const BasicType *sig_bt,
+                                       const VMRegPair *regs,
+                                       int frame_extension_argument) {
+  assert(frame_extension_argument == -1, "unsupported");
 
   // Generate an I2C adapter: adjust the I-frame to make space for the C-frame
   // layout.  Lesp was saved by the calling I-frame and will be restored on
@@ -1026,9 +1028,10 @@
                                     int total_args_passed,
                                     int comp_args_on_stack,
                                     const BasicType *sig_bt,
-                                    const VMRegPair *regs) {
+                                    const VMRegPair *regs,
+                                    int frame_extension_arguments) {
   AdapterGenerator agen(masm);
-  agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs);
+  agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs, frame_extension_arguments);
 }
 
 // ---------------------------------------------------------------
--- a/src/cpu/x86/vm/frame_x86.cpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/cpu/x86/vm/frame_x86.cpp	Tue Sep 09 14:31:36 2014 -0700
@@ -695,6 +695,13 @@
     DESCRIBE_FP_OFFSET(interpreter_frame_locals);
     DESCRIBE_FP_OFFSET(interpreter_frame_bcx);
     DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
+  } else if (is_entry_frame()) {
+    // This could be more descriptive if we use the enum in
+    // stubGenerator to map to real names but it's most important to
+    // claim these frame slots so the error checking works.
+    for (int i = 0; i < entry_frame_after_call_words; i++) {
+      values.describe(frame_no, fp() - i, err_msg("call_stub word fp - %d", i));
+    }
   }
 }
 #endif
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Tue Sep 09 14:31:36 2014 -0700
@@ -712,10 +712,12 @@
 }
 
 void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
-                            int total_args_passed,
-                            int comp_args_on_stack,
-                            const BasicType *sig_bt,
-                            const VMRegPair *regs) {
+                                    int total_args_passed,
+                                    int comp_args_on_stack,
+                                    const BasicType *sig_bt,
+                                    const VMRegPair *regs
+                                    int frame_extension_argument) {
+  assert(frame_extension_arguments == -1, "unsupported");
 
   // Note: rsi contains the senderSP on entry. We must preserve it since
   // we may do a i2c -> c2i transition if we lose a race where compiled
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue Sep 09 14:31:36 2014 -0700
@@ -643,10 +643,11 @@
 }
 
 void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
-                            int total_args_passed,
-                            int comp_args_on_stack,
-                            const BasicType *sig_bt,
-                            const VMRegPair *regs) {
+                                    int total_args_passed,
+                                    int comp_args_on_stack,
+                                    const BasicType *sig_bt,
+                                    const VMRegPair *regs,
+                                    int frame_extension_argument) {
 
   // Note: r13 contains the senderSP on entry. We must preserve it since
   // we may do a i2c -> c2i transition if we lose a race where compiled
@@ -704,6 +705,42 @@
     __ block_comment("} verify_i2ce ");
   }
 
+#ifdef GRAAL
+  if (frame_extension_argument != -1) {
+    // The frame_extension_argument is an int that describes the
+    // expected amount of argument space in the caller frame.  If that
+    // is greater than total_args_passed then enlarge the caller frame
+    // by that amount to ensure deopt works correctly.
+    assert(frame_extension_argument < total_args_passed, "out of range");
+    assert(sig_bt[frame_extension_argument] == T_INT, "wrong signature");
+
+    Label done;
+    int i = frame_extension_argument;
+    int ld_off = (total_args_passed - i)*Interpreter::stackElementSize;
+    // Check if anything needs to be done.  Too much space is ok.
+    __ movl(r13, Address(rsp, ld_off));
+    __ cmpl(r13, total_args_passed);
+    __ jcc(Assembler::lessEqual, done);
+    // Save the old rsp for the copy code
+    __ movptr(r11, rsp);
+    // Enlarge the frame
+    __ subl(r13, total_args_passed);
+    __ shlq(r13, 3);
+    __ subptr(rsp, r13);
+
+    // Now copy the arguments in reverse order so they don't get
+    // overwritten during the copy.
+    for (int i = total_args_passed - 1; i >= 0; i--) {
+      int ld_off = (total_args_passed - i) * Interpreter::stackElementSize;
+      __ movptr(r13, Address(r11, ld_off));
+      __ movptr(Address(rsp, ld_off), r13);
+    }
+    __ bind(done);
+  }
+#else
+  assert(frame_extension_argument == -1, "unsupported");
+#endif
+
   // Must preserve original SP for loading incoming arguments because
   // we need to align the outgoing SP for compiled code.
   __ movptr(r11, rsp);
--- a/src/gpu/hsail/vm/gpu_hsail.cpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/gpu/hsail/vm/gpu_hsail.cpp	Tue Sep 09 14:31:36 2014 -0700
@@ -249,6 +249,7 @@
             int myActionReason = Deoptimization::make_trap_request(Deoptimization::trap_request_reason(pdeopt->reason()), Deoptimization::Action_none);
             javaArgs.push_int(myActionReason);
             javaArgs.push_oop((oop) NULL);
+            javaArgs.push_int(mh->size_of_parameters());
             if (TraceGPUInteraction) {
               tty->print_cr("[HSAIL] Deoptimizing to host for workitem=%d (slot=%d) with deoptId=%d, frame=" INTPTR_FORMAT ", actionAndReason=%d", workitem, k, deoptId, hsailFrame, myActionReason);
               // show the $d registers or stack slots containing references
--- a/src/share/vm/graal/graalCompiler.cpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/share/vm/graal/graalCompiler.cpp	Tue Sep 09 14:31:36 2014 -0700
@@ -63,7 +63,7 @@
     CompilationPolicy::completed_vm_startup();
 
 #ifndef PRODUCT
-    if (CompileTheWorld) {
+    if (CompileTheWorld && !BootstrapGraal) {
       compile_the_world();
     }
 #endif
@@ -113,6 +113,11 @@
     tty->print_cr(" in %d ms (compiled %d methods)", os::javaTimeMillis() - start, _methodsCompiled);
   }
   _bootstrapping = false;
+#ifndef PRODUCT
+    if (CompileTheWorld) {
+      compile_the_world();
+    }
+#endif
 }
 
 void GraalCompiler::compile_method(methodHandle method, int entry_bci, CompileTask* task) {
--- a/src/share/vm/graal/graalRuntime.cpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/share/vm/graal/graalRuntime.cpp	Tue Sep 09 14:31:36 2014 -0700
@@ -24,6 +24,7 @@
 #include "precompiled.hpp"
 #include "asm/codeBuffer.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/disassembler.hpp"
 #include "graal/graalRuntime.hpp"
 #include "graal/graalCompilerToVM.hpp"
 #include "graal/graalCompiler.hpp"
@@ -56,7 +57,12 @@
 
     graal_compute_offsets();
 
+#ifdef TARGET_ARCH_x86
+#ifdef _LP64
+    // Only supported on x86_64 for now
     _external_deopt_i2c_entry = create_external_deopt_i2c();
+#endif
+#endif
 
     // Ensure _non_oop_bits is initialized
     Universe::non_oop_word();
@@ -88,7 +94,7 @@
   cb.insts()->initialize_shared_locs((relocInfo*)buffer_locs, sizeof(buffer_locs)/sizeof(relocInfo));
   MacroAssembler masm(&cb);
 
-  int total_args_passed = 5;
+  int total_args_passed = 6;
 
   BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed);
   VMRegPair* regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed);
@@ -98,13 +104,19 @@
   sig_bt[i++] = T_VOID; // long stakes 2 slots
   sig_bt[i++] = T_INT;
   sig_bt[i++] = T_OBJECT;
+  sig_bt[i++] = T_INT; // The number of actual arguments pass to the method.
 
   int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, false);
 
-  SharedRuntime::gen_i2c_adapter(&masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
+  SharedRuntime::gen_i2c_adapter(&masm, total_args_passed, comp_args_on_stack, sig_bt, regs, total_args_passed - 1);
   masm.flush();
 
-  return AdapterBlob::create(&cb)->content_begin();
+  AdapterBlob* adapter = AdapterBlob::create(&cb);
+  if (PrintAdapterHandlers) {
+    tty->print_cr("Decoding external_deopt_i2c");
+    Disassembler::decode(adapter->code_begin(), adapter->code_end());
+  }
+  return adapter->code_begin();
 }
 
 BasicType GraalRuntime::kindToBasicType(jchar ch) {
--- a/src/share/vm/graal/graalRuntime.hpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/share/vm/graal/graalRuntime.hpp	Tue Sep 09 14:31:36 2014 -0700
@@ -217,7 +217,10 @@
 
   static BasicType kindToBasicType(jchar ch);
   static address create_external_deopt_i2c();
-  static address get_external_deopt_i2c_entry() {return _external_deopt_i2c_entry;}
+  static address get_external_deopt_i2c_entry() {
+    guarantee(_external_deopt_i2c_entry != NULL, "unsupported");
+    return _external_deopt_i2c_entry;
+  }
 
   // The following routines are all called from compiled Graal code
 
--- a/src/share/vm/runtime/sharedRuntime.hpp	Tue Sep 09 12:22:48 2014 -0700
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Tue Sep 09 14:31:36 2014 -0700
@@ -405,7 +405,8 @@
                               int total_args_passed,
                               int comp_args_on_stack,
                               const BasicType *sig_bt,
-                              const VMRegPair *regs);
+                              const VMRegPair *regs,
+                              int frame_extension_argument = -1);
 
   // OSR support