changeset 13708:0fbe961a32df

Merge.
author Christian Humer <christian.humer@gmail.com>
date Mon, 20 Jan 2014 14:22:56 +0100
parents 40fd9958cdf5 (current diff) 0e8c22aa6ec3 (diff)
children c2ed2ce2cfe0
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java
diffstat 55 files changed, 743 insertions(+), 439 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Mon Jan 20 14:22:56 2014 +0100
@@ -70,13 +70,17 @@
     /**
      * Encodes a deoptimization action and a deoptimization reason in an integer value.
      * 
-     * @param speculationId a speculation ID returned by SpeculationLog.addSpeculation
+     * @param debugId an integer that can be used to track the origin of a deoptimization at
+     *            runtime. There is no guarantee that the runtime will use this value. The runtime
+     *            may even keep fewer than 32 bits.
      * 
      * @return the encoded value as an integer
      */
-    Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int speculationId);
+    Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId);
 
     DeoptimizationReason decodeDeoptReason(Constant constant);
 
     DeoptimizationAction decodeDeoptAction(Constant constant);
+
+    int decodeDebugId(Constant constant);
 }
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Jan 20 14:22:56 2014 +0100
@@ -700,4 +700,7 @@
         bra(str);
     }
 
+    public void nullCheck(Register r) {
+        // setp(....);
+    }
 }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -43,15 +43,15 @@
         test("staticIntKernel", 'a', 42);
     }
 
+    public static int staticIntKernel(char p0, int p1) {
+        return p1 + p0;
+    }
+
     @Test
     public void testVirtualIntKernel() {
         test("virtualIntKernel", 'a', 42);
     }
 
-    public static int staticIntKernel(char p0, int p1) {
-        return p1 + p0;
-    }
-
     public int virtualIntKernel(char p0, int p1) {
         return p1 + p0;
     }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Jan 20 14:22:56 2014 +0100
@@ -827,7 +827,8 @@
 
     @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitNullCheck()");
+        assert v.kind() == Kind.Object;
+        append(new PTXMove.NullCheckOp(load(operand(v)), state(deopting)));
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -299,8 +299,8 @@
 
     final ValueNode getResult(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-        return graph.getNodes().filter(ReturnNode.class).first().result();
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first().result();
     }
 
     private void processMethod(final String snippet) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -98,11 +98,9 @@
         for (int i = 1; i <= 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("integerTest" + i);
 
-            ValueNode result = getResult(graph);
-            assertTrue(result instanceof ConditionalNode);
-            ConditionalNode mat = (ConditionalNode) result;
-            assertTrue(mat.condition() instanceof IntegerTestNode);
-            IntegerTestNode test = (IntegerTestNode) mat.condition();
+            ReturnNode returnNode = (ReturnNode) graph.start().next();
+            ConditionalNode conditional = (ConditionalNode) returnNode.result();
+            IntegerTestNode test = (IntegerTestNode) conditional.condition();
             ParameterNode param0 = graph.getParameter(0);
             ParameterNode param1 = graph.getParameter(1);
             assertTrue((test.x() == param0 && test.y() == param1) || (test.x() == param1 && test.y() == param0));
@@ -133,8 +131,9 @@
         assertTrue(result.isConstant() && result.asConstant().asLong() == 1);
         result = getResult(getCanonicalizedGraph("integerTestCanonicalization2"));
         assertTrue(result.isConstant() && result.asConstant().asLong() == 1);
-        result = getResult(getCanonicalizedGraph("integerTestCanonicalization3"));
-        assertTrue(result instanceof ConditionalNode);
+        StructuredGraph graph = getCanonicalizedGraph("integerTestCanonicalization3");
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        assertTrue(graph.getNodes(ReturnNode.class).first().result() instanceof ConditionalNode);
     }
 
     public static int integerTestCanonicalization1(boolean b) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -154,14 +154,18 @@
 
     @SuppressWarnings("unused")
     public static int testDisjunctionSnippet(Object a) {
-        if (a instanceof Integer) {
-            if (a == null) {
-                return -1;
+        try {
+            if (a instanceof Integer) {
+                if (a == null) {
+                    return -1;
+                } else {
+                    return 2;
+                }
             } else {
-                return 2;
+                return 3;
             }
-        } else {
-            return 3;
+        } finally {
+            field = null;
         }
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -68,6 +68,7 @@
 
             for (Node n : graph.getNodes()) {
                 if (n instanceof ReturnNode) {
+                    assert returnNode == null;
                     returnNode = (ReturnNode) n;
                 } else if (n instanceof MonitorExit) {
                     monitorexit = (MonitorExit) n;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -172,8 +172,8 @@
 
     protected void assertConstantReturn(StructuredGraph graph, int value) {
         String graphString = getCanonicalGraphString(graph, false);
-        Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes().filter(ReturnNode.class).count(), 1);
-        ValueNode result = graph.getNodes().filter(ReturnNode.class).first().result();
+        Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1);
+        ValueNode result = graph.getNodes(ReturnNode.class).first().result();
         Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant());
         Assert.assertEquals("unexpected ReturnNode result kind: " + graphString, result.asConstant().getKind(), Kind.Int);
         Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asConstant().asInt(), value);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -115,7 +115,7 @@
         for (TestMode mode : TestMode.values()) {
             SchedulePhase schedule = getFinalSchedule("testSplit1Snippet", mode);
             assertReadWithinStartBlock(schedule, true);
-            assertReadWithinReturnBlock(schedule, false);
+            assertReadWithinAllReturnBlocks(schedule, false);
         }
     }
 
@@ -131,6 +131,7 @@
             } else {
                 container.b = 15;
             }
+            container.obj = null;
         }
     }
 
@@ -138,7 +139,7 @@
     public void testSplit2() {
         SchedulePhase schedule = getFinalSchedule("testSplit2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     /**
@@ -163,7 +164,7 @@
         SchedulePhase schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(6, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, true);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
     /**
@@ -188,7 +189,7 @@
         SchedulePhase schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(6, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     /**
@@ -208,9 +209,9 @@
     @Test
     public void testLoop3() {
         SchedulePhase schedule = getFinalSchedule("testLoop3Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertEquals(7, schedule.getCFG().getBlocks().length);
+        assertEquals(6, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, true);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
     public String testStringReplaceSnippet(String input) {
@@ -246,7 +247,7 @@
         SchedulePhase schedule = getFinalSchedule("testLoop5Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(7, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
     /**
@@ -261,10 +262,11 @@
     public void testArrayCopy() {
         SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES);
         StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph();
-        ReturnNode ret = graph.getNodes().filter(ReturnNode.class).first();
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        ReturnNode ret = graph.getNodes(ReturnNode.class).first();
         assertTrue(ret.result() instanceof FloatingReadNode);
         assertEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result()));
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     /**
@@ -281,7 +283,7 @@
     @Test
     public void testIfRead1() {
         SchedulePhase schedule = getFinalSchedule("testIfRead1Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertEquals(4, schedule.getCFG().getBlocks().length);
+        assertEquals(3, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, true);
         assertReadAndWriteInSameBlock(schedule, false);
     }
@@ -302,10 +304,10 @@
     @Test
     public void testIfRead2() {
         SchedulePhase schedule = getFinalSchedule("testIfRead2Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertEquals(4, schedule.getCFG().getBlocks().length);
+        assertEquals(3, schedule.getCFG().getBlocks().length);
         assertEquals(1, schedule.getCFG().graph.getNodes().filter(FloatingReadNode.class).count());
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
         assertReadAndWriteInSameBlock(schedule, false);
     }
 
@@ -326,7 +328,7 @@
         SchedulePhase schedule = getFinalSchedule("testIfRead3Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(4, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     /**
@@ -345,9 +347,9 @@
     @Test
     public void testIfRead4() {
         SchedulePhase schedule = getFinalSchedule("testIfRead4Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertEquals(4, schedule.getCFG().getBlocks().length);
+        assertEquals(3, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
         assertReadAndWriteInSameBlock(schedule, true);
     }
 
@@ -366,7 +368,7 @@
         SchedulePhase schedule = getFinalSchedule("testIfRead5Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(4, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
         assertReadAndWriteInSameBlock(schedule, false);
     }
 
@@ -432,7 +434,7 @@
     public void testBlockSchedule2() {
         SchedulePhase schedule = getFinalSchedule("testBlockSchedule2Snippet", TestMode.WITHOUT_FRAMESTATES, MemoryScheduling.OPTIMAL, SchedulingStrategy.LATEST);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
         assertReadAndWriteInSameBlock(schedule, false);
     }
 
@@ -454,7 +456,7 @@
          * read of container.b for increment operation should be in return block. TODO: not sure
          * though, could be replaced by read of container.b of the loop header...
          */
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     public static void testProxy2Snippet() {
@@ -476,7 +478,7 @@
     public void testProxy2() {
         SchedulePhase schedule = getFinalSchedule("testProxy2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
     private int hash = 0;
@@ -499,7 +501,7 @@
     public void testStringHashCode() {
         SchedulePhase schedule = getFinalSchedule("testStringHashCodeSnippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, true);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
 
         hash = 0x1337;
         value[0] = 'a';
@@ -531,30 +533,26 @@
     public void testLoop4() {
         SchedulePhase schedule = getFinalSchedule("testLoop4Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
-    private void assertReadWithinReturnBlock(SchedulePhase schedule, boolean withinReturnBlock) {
+    private void assertReadWithinAllReturnBlocks(SchedulePhase schedule, boolean withinReturnBlock) {
         StructuredGraph graph = schedule.getCFG().graph;
-        assertEquals(graph.getNodes().filter(ReturnNode.class).count(), 1);
+        assertTrue(graph.getNodes(ReturnNode.class).isNotEmpty());
 
-        Block end = null;
-        outer: for (Block b : schedule.getCFG().getBlocks()) {
-            for (Node n : b.getNodes()) {
-                if (n instanceof ReturnNode) {
-                    end = b;
-                    break outer;
+        int withRead = 0;
+        int returnBlocks = 0;
+        for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) {
+            Block block = schedule.getCFG().getNodeToBlock().get(returnNode);
+            for (Node node : schedule.getBlockToNodesMap().get(block)) {
+                if (node instanceof FloatingReadNode) {
+                    withRead++;
+                    break;
                 }
             }
+            returnBlocks++;
         }
-        assertNotNull("no block with ReturnNode found", end);
-        boolean readEncountered = false;
-        for (Node node : schedule.getBlockToNodesMap().get(end)) {
-            if (node instanceof FloatingReadNode) {
-                readEncountered = true;
-            }
-        }
-        assertEquals(readEncountered, withinReturnBlock);
+        assertEquals(withRead == returnBlocks, withinReturnBlock);
     }
 
     private void assertReadWithinStartBlock(SchedulePhase schedule, boolean withinStartBlock) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class MergeCanonicalizerTest extends GraalCompilerTest {
+
+    public static int staticField;
+
+    private int field;
+
+    @Test
+    public void testSplitReturn() {
+        test("testSplitReturnSnippet", 2);
+        testReturnCount("testSplitReturnSnippet", 2);
+    }
+
+    public int testSplitReturnSnippet(int b) {
+        int v;
+        if (b < 0) {
+            staticField = 1;
+            v = 10;
+        } else {
+            staticField = 2;
+            v = 20;
+        }
+        int i = field;
+        i = field + i;
+        return v;
+    }
+
+    private void testReturnCount(String snippet, int returnCount) {
+        StructuredGraph graph = parse(snippet);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
+        Debug.dump(graph, "Graph");
+        assertEquals(returnCount, graph.getNodes(ReturnNode.class).count());
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -86,7 +86,7 @@
             PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false));
             new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
             new FloatingReadPhase().apply(graph);
-            new OptimizeGuardAnchors().apply(graph);
+            new OptimizeGuardAnchorsPhase().apply(graph);
             new ReadEliminationPhase().apply(graph);
             new CanonicalizerPhase(true).apply(graph, context);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -167,7 +167,6 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         StructuredGraph referenceGraph = parse(referenceSnippet);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -76,7 +76,6 @@
         test("test1Snippet");
     }
 
-    @Test(expected = AssertionError.class)
     public void test2() {
         test("test2Snippet");
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -98,13 +98,11 @@
         test("test4Snippet", "referenceSnippet3");
     }
 
-    public static final Object constantObject1 = "1";
-    public static final Object constantObject2 = "2";
-    public static final Object constantObject3 = "3";
-
+    @SuppressWarnings("unused")
     public static int test4Snippet(Object o) {
         if (o == null) {
-            if (o == constantObject1) {
+            Object o2 = Integer.class;
+            if (o == o2) {
                 return 3;
             } else {
                 return 1;
@@ -121,40 +119,41 @@
 
     public static int referenceSnippet5(Object o, Object a) {
         if (o == null) {
-            if (a == constantObject1 || a == constantObject2) {
+            if (a == Integer.class || a == Double.class) {
                 return 1;
             }
         } else {
-            if (a == constantObject2 || a == constantObject3) {
+            if (a == Double.class || a == Long.class) {
                 return 11;
             }
         }
-        if (a == constantObject1) {
+        if (a == Integer.class) {
             return 3;
         }
         return 5;
     }
 
+    @SuppressWarnings("unused")
     public static int test5Snippet(Object o, Object a) {
         if (o == null) {
-            if (a == constantObject1 || a == constantObject2) {
+            if (a == Integer.class || a == Double.class) {
                 if (a == null) {
                     return 10;
                 }
                 return 1;
             }
         } else {
-            if (a == constantObject2 || a == constantObject3) {
+            if (a == Double.class || a == Long.class) {
                 if (a != null) {
                     return 11;
                 }
                 return 2;
             }
         }
-        if (a == constantObject1) {
+        if (a == Integer.class) {
             return 3;
         }
-        if (a == constantObject2) {
+        if (a == Double.class) {
             return 4;
         }
         return 5;
@@ -185,7 +184,6 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         // a second canonicalizer is needed to process nested MaterializeNodes
@@ -198,8 +196,8 @@
     @Override
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
         if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
-            outputGraph(expected, "expected");
-            outputGraph(graph, "actual");
+            Debug.dump(expected, "expected (node count)");
+            Debug.dump(graph, "graph (node count)");
             Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount());
         }
     }
@@ -239,12 +237,11 @@
 
     private <T extends Node> void testHelper(String snippet, Class<T> clazz) {
         StructuredGraph graph = parse(snippet);
-        Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
-        Debug.dump(graph, "Graph");
+        Debug.dump(graph, "Graph " + snippet);
         Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -33,8 +33,9 @@
     @Test
     public void testSimpleMerge() {
         testEscapeAnalysis("simpleMergeSnippet", null, false);
-        assertTrue(returnNode.result() instanceof PhiNode);
-        PhiNode phi = (PhiNode) returnNode.result();
+        assertEquals(1, returnNodes.size());
+        assertTrue(returnNodes.get(0).result() instanceof PhiNode);
+        PhiNode phi = (PhiNode) returnNodes.get(0).result();
         assertTrue(phi.valueAt(0) instanceof ParameterNode);
         assertTrue(phi.valueAt(1) instanceof ParameterNode);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Mon Jan 20 14:22:56 2014 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
+import java.util.*;
+
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
@@ -119,7 +121,7 @@
 
     protected StructuredGraph graph;
     protected HighTierContext context;
-    protected ReturnNode returnNode;
+    protected List<ReturnNode> returnNodes;
 
     /**
      * Runs Escape Analysis on the given snippet and makes sure that no allocations remain in the
@@ -134,8 +136,10 @@
     protected void testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) {
         prepareGraph(snippet, iterativeEscapeAnalysis);
         if (expectedConstantResult != null) {
-            Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
-            Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+            for (ReturnNode returnNode : returnNodes) {
+                Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
+                Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+            }
         }
         int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() +
                         graph.getNodes().filter(CommitAllocationNode.class).count();
@@ -153,8 +157,7 @@
             new DeadCodeEliminationPhase().apply(graph);
             new CanonicalizerPhase(true).apply(graph, context);
             new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true)).apply(graph, context);
-            Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-            returnNode = graph.getNodes().filter(ReturnNode.class).first();
+            returnNodes = graph.getNodes(ReturnNode.class).snapshot();
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -213,8 +213,9 @@
         prepareGraph("testFullyUnrolledLoopSnippet", false);
         new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
-        Assert.assertTrue(returnNode.result() instanceof AllocatedObjectNode);
-        CommitAllocationNode commit = ((AllocatedObjectNode) returnNode.result()).getCommit();
+        Assert.assertEquals(1, returnNodes.size());
+        Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode);
+        CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit();
         Assert.assertEquals(2, commit.getValues().size());
         Assert.assertEquals(1, commit.getVirtualObjects().size());
         Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -79,8 +79,8 @@
 
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-        return graph.getNodes().filter(ReturnNode.class).first();
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first();
     }
 
     private void processMethod(final String snippet) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -24,6 +24,8 @@
 
 import static org.junit.Assert.*;
 
+import java.util.*;
+
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
@@ -194,14 +196,14 @@
 
     @Test
     public void testPhi() {
-        ValueNode result = getReturn("testPhiSnippet").result();
+        processMethod("testPhiSnippet");
         assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty());
-        assertTrue(result instanceof PhiNode);
-        PhiNode phi = (PhiNode) result;
-        assertTrue(phi.valueAt(0).isConstant());
-        assertTrue(phi.valueAt(1).isConstant());
-        assertEquals(1, phi.valueAt(0).asConstant().asInt());
-        assertEquals(2, phi.valueAt(1).asConstant().asInt());
+        List<ReturnNode> returnNodes = graph.getNodes(ReturnNode.class).snapshot();
+        assertEquals(2, returnNodes.size());
+        assertTrue(returnNodes.get(0).predecessor() instanceof StoreFieldNode);
+        assertTrue(returnNodes.get(1).predecessor() instanceof StoreFieldNode);
+        assertTrue(returnNodes.get(0).result().isConstant());
+        assertTrue(returnNodes.get(1).result().isConstant());
     }
 
     @SuppressWarnings("all")
@@ -236,8 +238,8 @@
 
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-        return graph.getNodes().filter(ReturnNode.class).first();
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first();
     }
 
     protected void processMethod(final String snippet) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -86,8 +86,9 @@
     @Test
     public void testMergedDouble() {
         testEscapeAnalysis("testMergedDoubleSnippet", null, false);
-        Assert.assertTrue(returnNode.result() instanceof PhiNode);
-        PhiNode phi = (PhiNode) returnNode.result();
+        Assert.assertEquals(1, returnNodes.size());
+        Assert.assertTrue(returnNodes.get(0).result() instanceof PhiNode);
+        PhiNode phi = (PhiNode) returnNodes.get(0).result();
         Assert.assertTrue(phi.valueAt(0) instanceof LoadFieldNode);
         Assert.assertTrue(phi.valueAt(1) instanceof LoadFieldNode);
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Mon Jan 20 14:22:56 2014 +0100
@@ -65,7 +65,7 @@
         }
 
         if (OptEliminatePartiallyRedundantGuards.getValue()) {
-            appendPhase(new OptimizeGuardAnchors());
+            appendPhase(new OptimizeGuardAnchorsPhase());
         }
 
         if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
@@ -73,7 +73,7 @@
         }
 
         if (OptEliminatePartiallyRedundantGuards.getValue()) {
-            appendPhase(new OptimizeGuardAnchors());
+            appendPhase(new OptimizeGuardAnchorsPhase());
         }
 
         if (OptCanonicalizer.getValue()) {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Mon Jan 20 14:22:56 2014 +0100
@@ -94,6 +94,8 @@
 
     public PTXHotSpotBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
         super(runtime, providers);
+        CompilerToGPU compilerToGPU = getRuntime().getCompilerToGPU();
+        deviceInitialized = OmitDeviceInit || compilerToGPU.deviceInit();
     }
 
     @Override
@@ -110,7 +112,6 @@
     public void completeInitialization() {
         HotSpotHostForeignCallsProvider hostForeignCalls = (HotSpotHostForeignCallsProvider) getRuntime().getHostProviders().getForeignCalls();
         CompilerToGPU compilerToGPU = getRuntime().getCompilerToGPU();
-        deviceInitialized = OmitDeviceInit || compilerToGPU.deviceInit();
         if (deviceInitialized) {
             long launchKernel = compilerToGPU.getLaunchKernelAddress();
             hostForeignCalls.registerForeignCall(LAUNCH_KERNEL, launchKernel, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java	Mon Jan 20 14:22:56 2014 +0100
@@ -25,12 +25,18 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import java.util.Arrays;
 
 public class PTXHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider {
 
     public PTXHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) {
         super(runtime, target);
+    }
 
+    @Override
+    public String disassemble(CompilationResult compResult, InstalledCode installedCode) {
+        byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode();
+        return new String(code);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java	Mon Jan 20 14:22:56 2014 +0100
@@ -33,10 +33,12 @@
         throw GraalInternalError.unimplemented();
     }
 
+    @Override
     public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
         throw GraalInternalError.unimplemented();
     }
 
+    @Override
     public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
         throw GraalInternalError.unimplemented();
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Jan 20 14:22:56 2014 +0100
@@ -556,8 +556,9 @@
                 int id = allocateCompileTaskId(method, entryBCI);
                 HotSpotBackend backend = runtime.getHostBackend();
                 CompilationTask task = new CompilationTask(backend, method, entryBCI, id);
+                boolean isLambdaMethod = (method.getName().contains("lambda$main$") & method.isSynthetic());
 
-                if (blocking) {
+                if (blocking || isLambdaMethod) {
                     task.runCompilation(true);
                 } else {
                     try {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Mon Jan 20 14:22:56 2014 +0100
@@ -130,12 +130,12 @@
     }
 
     @Override
-    public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int speculationId) {
+    public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) {
         HotSpotVMConfig config = runtime.getConfig();
         int actionValue = convertDeoptAction(action);
         int reasonValue = convertDeoptReason(reason);
-        int speculationValue = speculationId & intMaskRight(config.deoptimizationDebugIdBits);
-        Constant c = Constant.forInt(~((speculationValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift)));
+        int debugValue = debugId & intMaskRight(config.deoptimizationDebugIdBits);
+        Constant c = Constant.forInt(~((debugValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift)));
         assert c.asInt() < 0;
         return c;
     }
@@ -154,9 +154,9 @@
         return action;
     }
 
-    public short decodeSpeculationId(Constant constant) {
+    public int decodeDebugId(Constant constant) {
         HotSpotVMConfig config = runtime.getConfig();
-        return (short) (((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits));
+        return ((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits);
     }
 
     public int convertDeoptAction(DeoptimizationAction action) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Mon Jan 20 14:22:56 2014 +0100
@@ -118,8 +118,8 @@
 
     @MacroSubstitution(macro = ClassIsInstanceNode.class, isStatic = false)
     @MethodSubstitution(isStatic = false)
-    public static boolean isInstance(final Class<?> thisObj, Object obj) {
-        return !isPrimitive(thisObj) && ConditionalNode.materializeIsInstance(thisObj, obj);
+    public static boolean isInstance(Class<?> thisObj, Object obj) {
+        return ConditionalNode.materializeIsInstance(thisObj, obj);
     }
 
     @MacroSubstitution(macro = ClassCastNode.class, isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Jan 20 14:22:56 2014 +0100
@@ -187,7 +187,7 @@
         BeginNode anchorNode = BeginNode.anchor();
         Word hub = loadWordFromObject(mirror, klassOffset());
         Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode);
-        if (!checkUnknownSubType(hub, objectHub)) {
+        if (hub.equal(0) || !checkUnknownSubType(hub, objectHub)) {
             return falseValue;
         }
         return trueValue;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Jan 20 14:22:56 2014 +0100
@@ -521,7 +521,7 @@
                     StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod());
                     InliningUtil.inline(invoke, inlineeGraph, false);
 
-                    List<ReturnNode> rets = graph.getNodes().filter(ReturnNode.class).snapshot();
+                    List<ReturnNode> rets = graph.getNodes(ReturnNode.class).snapshot();
                     for (ReturnNode ret : rets) {
                         returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass());
                         String msg = "unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d";
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Jan 20 14:22:56 2014 +0100
@@ -120,7 +120,6 @@
 
         private ValueNode methodSynchronizedObject;
         private ExceptionDispatchBlock unwindBlock;
-        private Block returnBlock;
 
         private FixedWithNextNode lastInstr;                 // the last instruction added
 
@@ -198,7 +197,6 @@
             this.stream = new BytecodeStream(method.getCode());
             this.constantPool = method.getConstantPool();
             unwindBlock = null;
-            returnBlock = null;
             methodSynchronizedObject = null;
             this.currentGraph = graph;
             this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
@@ -270,7 +268,6 @@
             for (Block block : blockMap.blocks) {
                 processBlock(block);
             }
-            processBlock(returnBlock);
             processBlock(unwindBlock);
 
             Debug.dump(currentGraph, "After bytecode parsing");
@@ -305,16 +302,6 @@
             return unwindBlock;
         }
 
-        private Block returnBlock(int bci) {
-            if (returnBlock == null) {
-                returnBlock = new Block();
-                returnBlock.startBci = bci;
-                returnBlock.endBci = bci;
-                returnBlock.blockID = Integer.MAX_VALUE;
-            }
-            return returnBlock;
-        }
-
         public BytecodeStream stream() {
             return stream;
         }
@@ -1264,11 +1251,18 @@
         }
 
         private void genReturn(ValueNode x) {
+            frameState.setRethrowException(false);
             frameState.clearStack();
-            if (x != null) {
-                frameState.push(x.kind(), x);
+            if (graphBuilderConfig.eagerInfopointMode()) {
+                append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci())));
             }
-            appendGoto(createTarget(returnBlock(bci()), frameState));
+
+            synchronizedEpilogue(FrameState.AFTER_BCI, x);
+            if (frameState.lockDepth() != 0) {
+                throw new BailoutException("unbalanced monitors");
+            }
+
+            append(new ReturnNode(x));
         }
 
         private MonitorEnterNode genMonitorEnter(ValueNode x) {
@@ -1648,10 +1642,7 @@
                 ((MergeNode) lastInstr).setStateAfter(frameState.create(bci));
             }
 
-            if (block == returnBlock) {
-                frameState.setRethrowException(false);
-                createReturn();
-            } else if (block == unwindBlock) {
+            if (block == unwindBlock) {
                 frameState.setRethrowException(false);
                 createUnwind();
             } else if (block instanceof ExceptionDispatchBlock) {
@@ -1692,26 +1683,12 @@
             append(new UnwindNode(exception));
         }
 
-        private void createReturn() {
-            Kind returnKind = method.getSignature().getReturnKind().getStackKind();
-            ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind);
-            assert frameState.stackSize() == 0;
-
-            if (graphBuilderConfig.eagerInfopointMode()) {
-                append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci())));
-            }
-
-            synchronizedEpilogue(FrameState.AFTER_BCI, x);
-            if (frameState.lockDepth() != 0) {
-                throw new BailoutException("unbalanced monitors");
-            }
-
-            append(new ReturnNode(x));
-        }
-
         private void synchronizedEpilogue(int bci, ValueNode returnValue) {
             if (Modifier.isSynchronized(method.getModifiers())) {
                 MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue);
+                if (returnValue != null) {
+                    frameState.push(returnValue.kind(), returnValue);
+                }
                 monitorExit.setStateAfter(frameState.create(bci));
                 assert !frameState.rethrowException();
             }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Mon Jan 20 14:22:56 2014 +0100
@@ -32,7 +32,7 @@
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 
 public class PTXMove {
@@ -239,4 +239,29 @@
     protected static void compareAndSwap(CompilationResultBuilder crb, PTXAssembler masm, AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
         throw new InternalError("NYI");
     }
+
+    public static class NullCheckOp extends PTXLIRInstruction implements NullCheck {
+
+        @Use({REG}) protected AllocatableValue input;
+        @State protected LIRFrameState state;
+
+        public NullCheckOp(Variable input, LIRFrameState state) {
+            this.input = input;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
+            crb.recordImplicitException(masm.codeBuffer.position(), state);
+            masm.nullCheck(asRegister(input));
+        }
+
+        public Value getCheckedValue() {
+            return input;
+        }
+
+        public LIRFrameState getState() {
+            return state;
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Mon Jan 20 14:22:56 2014 +0100
@@ -60,9 +60,12 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (actionAndReason.isConstant()) {
+        if (actionAndReason.isConstant() && speculation.isConstant()) {
             Constant constant = actionAndReason.asConstant();
-            DeoptimizeNode newDeopt = graph().add(new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant)));
+            Constant speculationConstant = speculation.asConstant();
+            DeoptimizeNode newDeopt = graph().add(
+                            new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), tool.getMetaAccess().decodeDebugId(constant),
+                                            speculationConstant));
             newDeopt.setDeoptimizationState(getDeoptimizationState());
             return newDeopt;
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Jan 20 14:22:56 2014 +0100
@@ -371,6 +371,29 @@
                 }
             }
         }
+        if (trueSuccessor().next() instanceof ReturnNode && falseSuccessor().next() instanceof ReturnNode) {
+            ReturnNode trueEnd = (ReturnNode) trueSuccessor().next();
+            ReturnNode falseEnd = (ReturnNode) falseSuccessor().next();
+            ValueNode trueValue = trueEnd.result();
+            ValueNode falseValue = falseEnd.result();
+            ConditionalNode conditional = null;
+            if (trueValue != null) {
+                if (trueValue.kind() != falseValue.kind()) {
+                    return false;
+                }
+                if (trueValue.kind() != Kind.Int && trueValue.kind() != Kind.Long) {
+                    return false;
+                }
+                conditional = canonicalizeConditionalCascade(trueValue, falseValue);
+                if (conditional == null) {
+                    return false;
+                }
+            }
+            ReturnNode newReturn = graph().add(new ReturnNode(conditional));
+            replaceAtPredecessor(newReturn);
+            GraphUtil.killCFG(this);
+            return true;
+        }
         return false;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Mon Jan 20 14:22:56 2014 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -34,4 +36,6 @@
     }
 
     public abstract MemoryNode getLastLocationAccess(LocationIdentity locationIdentity);
+
+    public abstract Set<LocationIdentity> getLocations();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Jan 20 14:22:56 2014 +0100
@@ -24,6 +24,8 @@
 
 import static com.oracle.graal.graph.iterators.NodePredicates.*;
 
+import java.util.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -194,6 +196,35 @@
                 tool.addToWorkList(newEnd.predecessor()); // ?
             }
             graph().reduceTrivialMerge(this);
+        } else if (next instanceof ReturnNode) {
+            ReturnNode returnNode = (ReturnNode) next;
+            if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) {
+                return;
+            }
+            List<PhiNode> phis = phis().snapshot();
+            for (PhiNode phi : phis) {
+                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
+                    if (usage != returnNode) {
+                        return;
+                    }
+                }
+            }
+
+            PhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (PhiNode) returnNode.result();
+            List<AbstractEndNode> endNodes = forwardEnds().snapshot();
+            for (AbstractEndNode end : endNodes) {
+                ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
+                end.replaceAtPredecessor(newReturn);
+            }
+            GraphUtil.killCFG(this);
+            for (AbstractEndNode end : endNodes) {
+                end.safeDelete();
+            }
+            for (PhiNode phi : phis) {
+                if (phi.isAlive() && phi.usages().isEmpty()) {
+                    GraphUtil.killWithUnusedFloatingInputs(phi);
+                }
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Mon Jan 20 14:22:56 2014 +0100
@@ -28,7 +28,7 @@
 /**
  * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call.
  */
-@NodeInfo(nameTemplate = "Local({p#index})")
+@NodeInfo(nameTemplate = "Param({p#index})")
 public final class ParameterNode extends AbstractLocalNode implements IterableNodeType {
 
     public ParameterNode(int index, Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Mon Jan 20 14:22:56 2014 +0100
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class ReturnNode extends ControlSinkNode implements LIRLowerable {
+public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
 
     @Input private ValueNode result;
     @Input private MemoryMapNode memoryMap;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Mon Jan 20 14:22:56 2014 +0100
@@ -62,7 +62,11 @@
         if (mirror().isConstant()) {
             Class clazz = (Class) mirror().asConstant().asObject();
             ResolvedJavaType t = tool.getMetaAccess().lookupJavaType(clazz);
-            return graph().unique(new InstanceOfNode(t, object(), null));
+            if (t.isPrimitive()) {
+                return LogicConstantNode.contradiction(graph());
+            } else {
+                return graph().unique(new InstanceOfNode(t, object(), null));
+            }
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Jan 20 14:22:56 2014 +0100
@@ -60,6 +60,9 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
+        if (usages().isEmpty() && (isStatic() || ObjectStamp.isObjectNonNull(object().stamp()))) {
+            return null;
+        }
         MetaAccessProvider metaAccess = tool.getMetaAccess();
         if (tool.canonicalizeReads() && metaAccess != null) {
             ConstantNode constant = asConstant(metaAccess);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Jan 20 14:22:56 2014 +0100
@@ -84,6 +84,7 @@
             return false;
         }
 
+        @Override
         public Set<LocationIdentity> getLocations() {
             return lastMemorySnapshot.keySet();
         }
@@ -111,6 +112,46 @@
         }
     }
 
+    public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List<? extends MemoryMapNode> states) {
+        MemoryMapImpl newState = new MemoryMapImpl();
+
+        Set<LocationIdentity> keys = new HashSet<>();
+        for (MemoryMapNode other : states) {
+            keys.addAll(other.getLocations());
+        }
+        assert !keys.contains(FINAL_LOCATION);
+
+        for (LocationIdentity key : keys) {
+            int mergedStatesCount = 0;
+            boolean isPhi = false;
+            MemoryNode merged = null;
+            for (MemoryMapNode state : states) {
+                MemoryNode last = state.getLastLocationAccess(key);
+                if (isPhi) {
+                    merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last));
+                } else {
+                    if (merged == last) {
+                        // nothing to do
+                    } else if (merged == null) {
+                        merged = last;
+                    } else {
+                        MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
+                        for (int j = 0; j < mergedStatesCount; j++) {
+                            phi.addInput(ValueNodeUtil.asNode(merged));
+                        }
+                        phi.addInput(ValueNodeUtil.asNode(last));
+                        merged = phi;
+                        isPhi = true;
+                    }
+                }
+                mergedStatesCount++;
+            }
+            newState.lastMemorySnapshot.put(key, merged);
+        }
+        return newState;
+
+    }
+
     private static class CollectMemoryCheckpointsClosure extends NodeIteratorClosure<Set<LocationIdentity>> {
 
         private final Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops;
@@ -238,42 +279,7 @@
 
         @Override
         protected MemoryMapImpl merge(MergeNode merge, List<MemoryMapImpl> states) {
-            MemoryMapImpl newState = new MemoryMapImpl();
-
-            Set<LocationIdentity> keys = new HashSet<>();
-            for (MemoryMapImpl other : states) {
-                keys.addAll(other.lastMemorySnapshot.keySet());
-            }
-            assert !keys.contains(FINAL_LOCATION);
-
-            for (LocationIdentity key : keys) {
-                int mergedStatesCount = 0;
-                boolean isPhi = false;
-                MemoryNode merged = null;
-                for (MemoryMapImpl state : states) {
-                    MemoryNode last = state.getLastLocationAccess(key);
-                    if (isPhi) {
-                        merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last));
-                    } else {
-                        if (merged == last) {
-                            // nothing to do
-                        } else if (merged == null) {
-                            merged = last;
-                        } else {
-                            MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
-                            for (int j = 0; j < mergedStatesCount; j++) {
-                                phi.addInput(ValueNodeUtil.asNode(merged));
-                            }
-                            phi.addInput(ValueNodeUtil.asNode(last));
-                            merged = phi;
-                            isPhi = true;
-                        }
-                    }
-                    mergedStatesCount++;
-                }
-                newState.lastMemorySnapshot.put(key, merged);
-            }
-            return newState;
+            return mergeMemoryMaps(merge, states);
         }
 
         @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Jan 20 14:22:56 2014 +0100
@@ -1295,8 +1295,10 @@
      */
     public static Map<Node, Node> inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
         final NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
-        StructuredGraph graph = invoke.asNode().graph();
+        FixedNode invokeNode = invoke.asNode();
+        StructuredGraph graph = invokeNode.graph();
         assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal();
+        Kind returnKind = invokeNode.kind();
 
         FrameState stateAfter = invoke.stateAfter();
         assert stateAfter == null || stateAfter.isAlive();
@@ -1305,7 +1307,7 @@
         }
 
         ArrayList<Node> nodes = new ArrayList<>(inlineGraph.getNodes().count());
-        ReturnNode returnNode = null;
+        ArrayList<ReturnNode> returnNodes = new ArrayList<>(4);
         UnwindNode unwindNode = null;
         final StartNode entryPointNode = inlineGraph.start();
         FixedNode firstCFGNode = entryPointNode.next();
@@ -1318,8 +1320,7 @@
             } else {
                 nodes.add(node);
                 if (node instanceof ReturnNode) {
-                    assert returnNode == null;
-                    returnNode = (ReturnNode) node;
+                    returnNodes.add((ReturnNode) node);
                 } else if (node instanceof UnwindNode) {
                     assert unwindNode == null;
                     unwindNode = (UnwindNode) node;
@@ -1327,7 +1328,7 @@
             }
         }
 
-        final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invoke.asNode());
+        final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode);
         DuplicationReplacement localReplacement = new DuplicationReplacement() {
 
             public Node replacement(Node node) {
@@ -1340,12 +1341,12 @@
             }
         };
 
-        assert invoke.asNode().successors().first() != null : invoke;
-        assert invoke.asNode().predecessor() != null;
+        assert invokeNode.successors().first() != null : invoke;
+        assert invokeNode.predecessor() != null;
 
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement);
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
-        invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate);
+        invokeNode.replaceAtPredecessor(firstCFGNodeDuplicate);
 
         FrameState stateAtExceptionEdge = null;
         if (invoke instanceof InvokeWithExceptionNode) {
@@ -1400,7 +1401,8 @@
                 if (frameState != null) {
                     assert frameState.bci != FrameState.BEFORE_BCI : frameState;
                     if (frameState.bci == FrameState.AFTER_BCI) {
-                        frameState.replaceAndDelete(stateAfter);
+                        frameState.replaceAndDelete(returnKind == Kind.Void ? stateAfter : stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), returnKind,
+                                        frameState.stackAt(0)));
                     } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) {
                         if (frameState.isAlive()) {
                             assert stateAtExceptionEdge != null;
@@ -1413,7 +1415,7 @@
                         if (frameState.outerFrameState() == null) {
                             assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method() == inlineGraph.method();
                             if (outerFrameState == null) {
-                                outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.asNode().kind());
+                                outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invokeNode.kind());
                                 outerFrameState.setDuringCall(true);
                             }
                             frameState.setOuterFrameState(outerFrameState);
@@ -1430,27 +1432,55 @@
         } else {
             assert checkContainsOnlyInvalidOrAfterFrameState(duplicates);
         }
-        Node returnValue = null;
-        if (returnNode != null) {
-            if (returnNode.result() instanceof ParameterNode) {
-                returnValue = localReplacement.replacement(returnNode.result());
-            } else if (returnNode.result() != null) {
-                returnValue = duplicates.get(returnNode.result());
+        if (!returnNodes.isEmpty()) {
+            FixedNode n = invoke.next();
+            invoke.setNext(null);
+            if (returnNodes.size() == 1) {
+                ReturnNode returnNode = (ReturnNode) duplicates.get(returnNodes.get(0));
+                Node returnValue = returnNode.result();
+                invokeNode.replaceAtUsages(returnValue);
+                returnNode.clearInputs();
+                returnNode.replaceAndDelete(n);
+            } else {
+                ArrayList<ReturnNode> returnDuplicates = new ArrayList<>(returnNodes.size());
+                for (ReturnNode returnNode : returnNodes) {
+                    returnDuplicates.add((ReturnNode) duplicates.get(returnNode));
+                }
+                MergeNode merge = graph.add(new MergeNode());
+                merge.setStateAfter(stateAfter);
+                ValueNode returnValue = mergeReturns(merge, returnDuplicates);
+                invokeNode.replaceAtUsages(returnValue);
+                merge.setNext(n);
             }
-            invoke.asNode().replaceAtUsages(returnValue);
-            Node returnDuplicate = duplicates.get(returnNode);
-            returnDuplicate.clearInputs();
-            Node n = invoke.next();
-            invoke.setNext(null);
-            returnDuplicate.replaceAndDelete(n);
         }
 
-        invoke.asNode().replaceAtUsages(null);
-        GraphUtil.killCFG(invoke.asNode());
+        invokeNode.replaceAtUsages(null);
+        GraphUtil.killCFG(invokeNode);
 
         return duplicates;
     }
 
+    public static ValueNode mergeReturns(MergeNode merge, List<? extends ReturnNode> returnNodes) {
+        PhiNode returnValuePhi = null;
+
+        for (ReturnNode returnNode : returnNodes) {
+            // create and wire up a new EndNode
+            EndNode endNode = merge.graph().add(new EndNode());
+            merge.addForwardEnd(endNode);
+
+            if (returnNode.result() != null) {
+                if (returnValuePhi == null) {
+                    returnValuePhi = merge.graph().addWithoutUnique(new PhiNode(returnNode.result().kind(), merge));
+                }
+                returnValuePhi.addInput(returnNode.result());
+            }
+            returnNode.clearInputs();
+            returnNode.replaceAndDelete(endNode);
+
+        }
+        return returnValuePhi;
+    }
+
     private static boolean checkContainsOnlyInvalidOrAfterFrameState(Map<Node, Node> duplicates) {
         for (Node node : duplicates.values()) {
             if (node instanceof FrameState) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java	Fri Jan 17 17:10:46 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common;
-
-import java.util.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.phases.*;
-
-public class OptimizeGuardAnchors extends Phase {
-    private static final DebugMetric metricGuardsAnchorOptimized = Debug.metric("GuardsAnchorOptimized");
-    private static final DebugMetric metricGuardsOptimizedAtSplit = Debug.metric("GuardsOptimizedAtSplit");
-
-    private static class LazyCFG {
-        private ControlFlowGraph cfg;
-        private StructuredGraph graph;
-
-        public LazyCFG(StructuredGraph graph) {
-            this.graph = graph;
-        }
-
-        public ControlFlowGraph get() {
-            if (cfg == null) {
-                cfg = ControlFlowGraph.compute(graph, true, false, true, true);
-            }
-            return cfg;
-        }
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        LazyCFG cfg = new LazyCFG(graph);
-        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
-            if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) {
-                NodeIterable<GuardNode> guards = begin.guards();
-                if (guards.isNotEmpty()) {
-                    AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin);
-                    // newAnchor == begin is possible because postdominator computation assumes that
-                    // loops never end
-                    if (newAnchor != begin) {
-                        for (GuardNode guard : guards.snapshot()) {
-                            guard.setGuard(newAnchor);
-                        }
-                        metricGuardsAnchorOptimized.increment();
-                    }
-                }
-            }
-        }
-        for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) {
-            optimizeAtControlSplit(controlSplit, cfg);
-        }
-    }
-
-    private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) {
-        Block anchor = cfg.blockFor(begin);
-        while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) {
-            anchor = anchor.getDominator();
-        }
-        return anchor.getBeginNode();
-    }
-
-    private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) {
-        AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit);
-        int successorCount = controlSplit.successors().count();
-        List<GuardNode> otherGuards = new ArrayList<>(successorCount - 1);
-        for (GuardNode guard : successor.guards().snapshot()) {
-            if (guard.isDeleted() || guard.condition().usages().count() < successorCount) {
-                continue;
-            }
-            for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) {
-                if (conditonGuard != guard) {
-                    GuardingNode conditonGuardAnchor = conditonGuard.getGuard();
-                    if (conditonGuardAnchor.asNode().predecessor() == controlSplit && compatibleGuards(guard, conditonGuard)) {
-                        otherGuards.add(conditonGuard);
-                    }
-                }
-            }
-
-            if (otherGuards.size() == successorCount - 1) {
-                AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit));
-                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
-                for (GuardNode otherGuard : otherGuards) {
-                    otherGuard.replaceAndDelete(newGuard);
-                }
-                guard.replaceAndDelete(newGuard);
-                metricGuardsOptimizedAtSplit.increment();
-            }
-            otherGuards.clear();
-        }
-    }
-
-    private static boolean compatibleGuards(GuardNode guard, GuardNode conditonGuard) {
-        return conditonGuard.negated() == guard.negated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason() &&
-                        conditonGuard.getSpeculation().equals(guard.getSpeculation());
-    }
-
-    private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
-        NodeClassIterator successors = controlSplit.successors().iterator();
-        AbstractBeginNode min = (AbstractBeginNode) successors.next();
-        int minUsages = min.usages().count();
-        while (successors.hasNext()) {
-            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
-            int count = successor.usages().count();
-            if (count < minUsages) {
-                minUsages = count;
-                min = successor;
-            }
-        }
-        return min;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Mon Jan 20 14:22:56 2014 +0100
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.common;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.phases.*;
+
+public class OptimizeGuardAnchorsPhase extends Phase {
+    private static final DebugMetric metricGuardsAnchorOptimized = Debug.metric("GuardsAnchorOptimized");
+    private static final DebugMetric metricGuardsOptimizedAtSplit = Debug.metric("GuardsOptimizedAtSplit");
+
+    public static class LazyCFG {
+        private ControlFlowGraph cfg;
+        private StructuredGraph graph;
+
+        public LazyCFG(StructuredGraph graph) {
+            this.graph = graph;
+        }
+
+        public ControlFlowGraph get() {
+            if (cfg == null) {
+                cfg = ControlFlowGraph.compute(graph, true, false, true, true);
+            }
+            return cfg;
+        }
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        LazyCFG cfg = new LazyCFG(graph);
+        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
+            if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) {
+                NodeIterable<GuardNode> guards = begin.guards();
+                if (guards.isNotEmpty()) {
+                    AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin);
+                    // newAnchor == begin is possible because postdominator computation assumes that
+                    // loops never end
+                    if (newAnchor != begin) {
+                        for (GuardNode guard : guards.snapshot()) {
+                            guard.setGuard(newAnchor);
+                        }
+                        metricGuardsAnchorOptimized.increment();
+                    }
+                }
+            }
+        }
+        for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) {
+            optimizeAtControlSplit(controlSplit, cfg);
+        }
+    }
+
+    public static AbstractBeginNode getOptimalAnchor(LazyCFG cfg, AbstractBeginNode begin) {
+        if (begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode) {
+            return begin;
+        }
+        return computeOptimalAnchor(cfg.get(), begin);
+    }
+
+    private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) {
+        Block anchor = cfg.blockFor(begin);
+        while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) {
+            anchor = anchor.getDominator();
+        }
+        return anchor.getBeginNode();
+    }
+
+    private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) {
+        AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit);
+        int successorCount = controlSplit.successors().count();
+        List<GuardNode> otherGuards = new ArrayList<>(successorCount - 1);
+        for (GuardNode guard : successor.guards().snapshot()) {
+            if (guard.isDeleted() || guard.condition().usages().count() < successorCount) {
+                continue;
+            }
+            for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) {
+                if (conditonGuard != guard) {
+                    GuardingNode conditonGuardAnchor = conditonGuard.getGuard();
+                    if (conditonGuardAnchor.asNode().predecessor() == controlSplit && compatibleGuards(guard, conditonGuard)) {
+                        otherGuards.add(conditonGuard);
+                    }
+                }
+            }
+
+            if (otherGuards.size() == successorCount - 1) {
+                AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit));
+                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
+                for (GuardNode otherGuard : otherGuards) {
+                    otherGuard.replaceAndDelete(newGuard);
+                }
+                guard.replaceAndDelete(newGuard);
+                metricGuardsOptimizedAtSplit.increment();
+            }
+            otherGuards.clear();
+        }
+    }
+
+    private static boolean compatibleGuards(GuardNode guard, GuardNode conditonGuard) {
+        return conditonGuard.negated() == guard.negated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason() &&
+                        conditonGuard.getSpeculation().equals(guard.getSpeculation());
+    }
+
+    private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
+        NodeClassIterator successors = controlSplit.successors().iterator();
+        AbstractBeginNode min = (AbstractBeginNode) successors.next();
+        int minUsages = min.usages().count();
+        while (successors.hasNext()) {
+            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
+            int count = successor.usages().count();
+            if (count < minUsages) {
+                minUsages = count;
+                min = successor;
+            }
+        }
+        return min;
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Mon Jan 20 14:22:56 2014 +0100
@@ -50,7 +50,7 @@
         if (deopt.reason() != DeoptimizationReason.NullCheckException) {
             return;
         }
-        if (deopt.getSpeculation() != null && deopt.getSpeculation() != Constant.NULL_OBJECT) {
+        if (deopt.getSpeculation() != null && !deopt.getSpeculation().equals(Constant.NULL_OBJECT)) {
             return;
         }
         Node predecessor = deopt.predecessor();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Mon Jan 20 14:22:56 2014 +0100
@@ -153,7 +153,7 @@
     }
 
     private static boolean doesNotAlwaysDeopt(StructuredGraph graph) {
-        return graph.getNodes().filter(ReturnNode.class).iterator().hasNext();
+        return graph.getNodes(ReturnNode.class).isNotEmpty();
     }
 
     private void computeLoopFactors() {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Jan 20 14:22:56 2014 +0100
@@ -36,9 +36,8 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.Mark;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
@@ -623,43 +622,49 @@
         assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders);
 
         new FloatingReadPhase(FloatingReadPhase.ExecutionMode.ANALYSIS_ONLY).apply(snippetCopy);
-        this.memoryMap = null;
 
         this.snippet = snippetCopy;
-        ReturnNode retNode = null;
+        List<ReturnNode> returnNodes = new ArrayList<>(4);
+        List<MemoryMapNode> memMaps = new ArrayList<>(4);
         StartNode entryPointNode = snippet.start();
-        nodes = new ArrayList<>(snippet.getNodeCount());
-        boolean seenReturn = false;
-        boolean containsMemoryMap = false;
-        for (Node node : snippet.getNodes()) {
-            if (node == entryPointNode || node == entryPointNode.stateAfter()) {
-                // Do nothing.
-            } else {
-                nodes.add(node);
-                if (node instanceof ReturnNode) {
-                    retNode = (ReturnNode) node;
-                    NodeIterable<MemoryMapNode> memstates = retNode.inputs().filter(MemoryMapNode.class);
-                    assert memstates.count() == 1;
-                    memoryMap = memstates.first();
-                    retNode.replaceFirstInput(memoryMap, null);
-                    memoryMap.safeDelete();
-
-                    assert !seenReturn : "can handle only one ReturnNode";
-                    seenReturn = true;
-                } else if (node instanceof MemoryMapNode) {
-                    containsMemoryMap = true;
-                }
+        for (ReturnNode retNode : snippet.getNodes(ReturnNode.class)) {
+            MemoryMapNode memMap = retNode.getMemoryMap();
+            memMaps.add(memMap);
+            retNode.setMemoryMap(null);
+            returnNodes.add(retNode);
+            if (memMap.usages().isEmpty()) {
+                memMap.safeDelete();
             }
         }
-        assert !containsMemoryMap;
+        assert snippet.getNodes().filter(MemoryMapNode.class).isEmpty();
+        if (returnNodes.isEmpty()) {
+            this.returnNode = null;
+            this.memoryMap = null;
+        } else if (returnNodes.size() == 1) {
+            this.returnNode = returnNodes.get(0);
+            this.memoryMap = memMaps.get(0);
+        } else {
+            MergeNode merge = snippet.add(new MergeNode());
+            ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes);
+            this.returnNode = snippet.add(new ReturnNode(returnValue));
+            this.memoryMap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps);
+            merge.setNext(this.returnNode);
+        }
 
         this.sideEffectNodes = curSideEffectNodes;
         this.deoptNodes = curDeoptNodes;
         this.stampNodes = curStampNodes;
-        this.returnNode = retNode;
+
+        nodes = new ArrayList<>(snippet.getNodeCount());
+        for (Node node : snippet.getNodes()) {
+            if (node != entryPointNode && node != entryPointNode.stateAfter()) {
+                nodes.add(node);
+            }
+        }
 
         Debug.metric(debugValueName("SnippetTemplateNodeCount", args)).add(nodes.size());
         args.info.notifyNewTemplate();
+        Debug.dump(snippet, "SnippetTemplate final state");
     }
 
     private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, VarargsPlaceholderNode[] placeholders) {
@@ -720,7 +725,7 @@
 
     /**
      * Nodes that inherit the {@link DeoptimizingNode#getDeoptimizationState()} from the replacee
-     * during insantiation.
+     * during instantiation.
      */
     private final ArrayList<DeoptimizingNode> deoptNodes;
 
@@ -737,7 +742,7 @@
     /**
      * map of killing locations to memory checkpoints (nodes).
      */
-    private MemoryMapNode memoryMap;
+    private final MemoryMapNode memoryMap;
 
     /**
      * Times instantiations of this template.
@@ -876,7 +881,7 @@
                         // MemoryCheckPoint inside the snippet graph
                         MemoryNode lastAccess = mmap.getLastLocationAccess(identity);
 
-                        assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)";
+                        assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kills the same location as the lowerable node?)";
                         if (usage instanceof MemoryAccess) {
                             MemoryAccess access = (MemoryAccess) usage;
                             if (access.getLastLocationAccess() == oldNode) {
@@ -961,6 +966,11 @@
                 return (MemoryNode) duplicates.get(ValueNodeUtil.asNode(lastLocationAccess));
             }
         }
+
+        @Override
+        public Set<LocationIdentity> getLocations() {
+            return memoryMap.getLocations();
+        }
     }
 
     /**
@@ -1014,25 +1024,18 @@
                 }
             }
 
-            for (ValueNode stampNode : stampNodes) {
-                Node stampDup = duplicates.get(stampNode);
-                ((ValueNode) stampDup).setStamp(((ValueNode) replacee).stamp());
-            }
+            updateStamps(replacee, duplicates);
 
             // Replace all usages of the replacee with the value returned by the snippet
             ValueNode returnValue = null;
             if (returnNode != null && !(replacee instanceof ControlSinkNode)) {
-                if (returnNode.result() instanceof ParameterNode) {
-                    returnValue = (ValueNode) replacements.get(returnNode.result());
-                } else if (returnNode.result() != null) {
-                    returnValue = (ValueNode) duplicates.get(returnNode.result());
-                }
-                Node returnDuplicate = duplicates.get(returnNode);
+                ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode);
+                returnValue = returnDuplicate.result();
                 MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
                 if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
                     replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap);
                 } else {
-                    assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages();
+                    assert returnValue != null || replacee.usages().isEmpty();
                     replacer.replace(replacee, returnValue, mmap);
                 }
                 if (returnDuplicate.isAlive()) {
@@ -1051,6 +1054,30 @@
         }
     }
 
+    private void propagateStamp(Node node) {
+        if (node instanceof PhiNode) {
+            PhiNode phi = (PhiNode) node;
+            if (phi.inferPhiStamp()) {
+                for (Node usage : node.usages()) {
+                    propagateStamp(usage);
+                }
+            }
+        }
+    }
+
+    private void updateStamps(ValueNode replacee, Map<Node, Node> duplicates) {
+        for (ValueNode stampNode : stampNodes) {
+            Node stampDup = duplicates.get(stampNode);
+            ((ValueNode) stampDup).setStamp(replacee.stamp());
+        }
+        for (ParameterNode paramNode : snippet.getNodes(ParameterNode.class)) {
+            for (Node usage : paramNode.usages()) {
+                Node usageDup = duplicates.get(usage);
+                propagateStamp(usageDup);
+            }
+        }
+    }
+
     /**
      * Gets a copy of the specialized graph.
      */
@@ -1097,23 +1124,14 @@
                     ((StateSplit) sideEffectDup).setStateAfter(((StateSplit) replacee).stateAfter());
                 }
             }
-            for (ValueNode stampNode : stampNodes) {
-                Node stampDup = duplicates.get(stampNode);
-                ((ValueNode) stampDup).setStamp(((ValueNode) replacee).stamp());
-            }
+            updateStamps(replacee, duplicates);
 
             // Replace all usages of the replacee with the value returned by the snippet
-            assert returnNode != null : replaceeGraph;
-            ValueNode returnValue = null;
-            if (returnNode.result() instanceof ParameterNode) {
-                returnValue = (ValueNode) replacements.get(returnNode.result());
-            } else {
-                returnValue = (ValueNode) duplicates.get(returnNode.result());
-            }
+            ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode);
+            ValueNode returnValue = returnDuplicate.result();
             assert returnValue != null || replacee.usages().isEmpty();
             replacer.replace(replacee, returnValue, new DuplicateMapper(duplicates, replaceeGraph.start()));
 
-            Node returnDuplicate = duplicates.get(returnNode);
             if (returnDuplicate.isAlive()) {
                 returnDuplicate.clearInputs();
                 returnDuplicate.replaceAndDelete(next);
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Jan 20 14:22:56 2014 +0100
@@ -70,7 +70,7 @@
     protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, Arguments arguments) {
         Assumptions assumptions = new Assumptions(true);
         StructuredGraph actual = partialEval(root, arguments, assumptions, true);
-        InstalledCode result = new TruffleCompilerImpl().compileMethodHelper(actual, GraphBuilderConfiguration.getDefault(), assumptions);
+        InstalledCode result = new TruffleCompilerImpl().compileMethodHelper(actual, GraphBuilderConfiguration.getDefault(), assumptions, root.toString());
         StructuredGraph expected = parseForComparison(methodName);
         removeFrameStates(actual);
         Assert.assertEquals(getCanonicalGraphString(expected, true), getCanonicalGraphString(actual, true));
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Jan 20 14:22:56 2014 +0100
@@ -156,7 +156,7 @@
         }
         long timePartialEvaluationFinished = System.nanoTime();
         int nodeCountPartialEval = graph.getNodeCount();
-        InstalledCode compiledMethod = compileMethodHelper(graph, config, assumptions);
+        InstalledCode compiledMethod = compileMethodHelper(graph, config, assumptions, compilable.toString());
         long timeCompilationFinished = System.nanoTime();
         int nodeCountLowered = graph.getNodeCount();
 
@@ -208,7 +208,7 @@
         }
     }
 
-    public InstalledCode compileMethodHelper(StructuredGraph graph, GraphBuilderConfiguration config, Assumptions assumptions) {
+    public InstalledCode compileMethodHelper(StructuredGraph graph, GraphBuilderConfiguration config, Assumptions assumptions, String name) {
         try (Scope s = Debug.scope("TruffleFinal")) {
             Debug.dump(graph, "After TruffleTier");
         } catch (Throwable e) {
@@ -219,7 +219,7 @@
         try (TimerCloseable a = CompilationTime.start(); Scope s = Debug.scope("TruffleGraal.GraalCompiler", graph, providers.getCodeCache())) {
             CodeCacheProvider codeCache = providers.getCodeCache();
             CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false);
-            CompilationResult compilationResult = new CompilationResult(graph.method().toString());
+            CompilationResult compilationResult = new CompilationResult(name);
             result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, createGraphBuilderSuite(config), OptimisticOptimizations.ALL, getProfilingInfo(graph),
                             new SpeculationLog(), suites, false, compilationResult, CompilationResultBuilderFactory.Default);
         } catch (Throwable e) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Fri Jan 17 17:10:46 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Mon Jan 20 14:22:56 2014 +0100
@@ -32,31 +32,53 @@
  */
 public class TruffleOptions {
 
-    /** Enables/disables the rewriting of traces in the truffle runtime to stdout. */
-    public static boolean TraceRewrites = false;
+    /**
+     * Enables/disables the rewriting of traces in the truffle runtime to stdout.
+     * <p>
+     * Can be set with {@code -Dtruffle.TraceRewrites=true}.
+     */
+    public static boolean TraceRewrites = Boolean.getBoolean("truffle.TraceRewrites");
 
     /**
      * Enables the generation of detailed rewrite reasons. Enabling this may introduce some overhead
      * for rewriting nodes.
+     * <p>
+     * Can be set with {@code -Dtruffle.DetailedRewriteReasons=true}.
      */
-    public static final boolean DetailedRewriteReasons = false;
+    public static final boolean DetailedRewriteReasons = Boolean.getBoolean("truffle.DetailedRewriteReasons");
 
     /**
      * Filters rewrites that do not contain the given string in the qualified name of the source or
      * target class hierarchy.
+     * <p>
+     * Can be set with {@code -Dtruffle.TraceRewritesFilterClass=name}.
      */
-    public static String TraceRewritesFilterClass = null;
+    public static String TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass");
 
     /**
      * Filters rewrites which does not contain the {@link Kind} in its source {@link NodeInfo}. If
      * no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * <p>
+     * Can be set with
+     * {@code -Dtruffle.TraceRewritesFilterFromKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
      */
-    public static NodeInfo.Kind TraceRewritesFilterFromKind = null;
+    public static NodeInfo.Kind TraceRewritesFilterFromKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromKind"));
 
     /**
      * Filters rewrites which does not contain the {@link Kind} in its target {@link NodeInfo}. If
      * no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * <p>
+     * Can be set with
+     * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
      */
-    public static NodeInfo.Kind TraceRewritesFilterToKind = null;
+    public static NodeInfo.Kind TraceRewritesFilterToKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToKind"));
+
+    private static NodeInfo.Kind parseNodeInfoKind(String kind) {
+        if (kind == null) {
+            return null;
+        }
+
+        return NodeInfo.Kind.valueOf(kind);
+    }
 
 }
--- a/mxtool/mx.py	Fri Jan 17 17:10:46 2014 +0100
+++ b/mxtool/mx.py	Mon Jan 20 14:22:56 2014 +0100
@@ -2866,23 +2866,24 @@
 
     generate_eclipse_workingsets()
 
-def _check_ide_timestamp(suite, timestamp):
-    """return True if and only if the projects file, imports file, eclipse-settings files, and mx itself are all older than timestamp"""
+def _check_ide_timestamp(suite, configZip, ide):
+    """return True if and only if the projects file, imports file, eclipse-settings files, and mx itself are all older than configZip"""
     projectsFile = join(suite.mxDir, 'projects')
-    if timestamp.isOlderThan(projectsFile):
+    if configZip.isOlderThan(projectsFile):
         return False
-    if timestamp.isOlderThan(suite.import_timestamp()):
+    if configZip.isOlderThan(suite.import_timestamp()):
         return False
     # Assume that any mx change might imply changes to the generated IDE files
-    if timestamp.isOlderThan(__file__):
+    if configZip.isOlderThan(__file__):
         return False
 
-    eclipseSettingsDir = join(suite.mxDir, 'eclipse-settings')
-    if exists(eclipseSettingsDir):
-        for name in os.listdir(eclipseSettingsDir):
-            path = join(eclipseSettingsDir, name)
-            if timestamp.isOlderThan(path):
-                return False
+    if ide == 'eclipse':
+        eclipseSettingsDir = join(suite.mxDir, 'eclipse-settings')
+        if exists(eclipseSettingsDir):
+            for name in os.listdir(eclipseSettingsDir):
+                path = join(eclipseSettingsDir, name)
+                if configZip.isOlderThan(path):
+                    return False
     return True
 
 def _eclipseinit_suite(args, suite, buildProcessorJars=True, refreshOnly=False):
@@ -2891,7 +2892,7 @@
     if refreshOnly and not configZip.exists():
         return
 
-    if _check_ide_timestamp(suite, configZip):
+    if _check_ide_timestamp(suite, configZip, 'eclipse'):
         logv('[Eclipse configurations are up to date - skipping]')
         return
 
@@ -3351,7 +3352,7 @@
     if refreshOnly and not configZip.exists():
         return
 
-    if _check_ide_timestamp(suite, configZip):
+    if _check_ide_timestamp(suite, configZip, 'netbeans'):
         logv('[NetBeans configurations are up to date - skipping]')
         return
 
@@ -3561,11 +3562,10 @@
                 javacClasspath.append('${' + ref + '}')
             else:
                 annotationProcessorReferences.append('${' + ref + '}')
-                annotationProcessorReferences += ":\\\n    ${" + ref + "}"
 
         print >> out, 'javac.classpath=\\\n    ' + (os.pathsep + '\\\n    ').join(javacClasspath)
-        print >> out, 'javac.test.processorpath=${javac.test.classpath}\\\n    ' + (os.pathsep + '\\\n    ').join(annotationProcessorReferences)
-        print >> out, 'javac.processorpath=${javac.classpath}\\\n    ' + (os.pathsep + '\\\n    ').join(annotationProcessorReferences)
+        print >> out, 'javac.processorpath=' + (os.pathsep + '\\\n    ').join(['${javac.classpath}'] + annotationProcessorReferences)
+        print >> out, 'javac.test.processorpath=' + (os.pathsep + '\\\n    ').join(['${javac.test.classpath}'] + annotationProcessorReferences)
 
         updated = update_file(join(p.dir, 'nbproject', 'project.properties'), out.getvalue()) or updated
         out.close()
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Fri Jan 17 17:10:46 2014 +0100
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Mon Jan 20 14:22:56 2014 +0100
@@ -331,7 +331,7 @@
   }
 
   if (TraceGPUInteraction) {
-    tty->print_cr("[CUDA] Got function handle for %s", name);
+    tty->print_cr("[CUDA] Got function handle for %s kernel address %p", name, cu_function);
   }
 
   return cu_function;
@@ -375,7 +375,9 @@
       return 0L;
     }
     // Push device_return_value to kernelParams
-    gpu::Ptx::CUdeviceptr* returnValuePtr = (gpu::Ptx::CUdeviceptr*) (address) parametersAndReturnValueBuffer + parametersAndReturnValueBufferSize - sizeof(device_return_value);
+    gpu::Ptx::CUdeviceptr* returnValuePtr = (gpu::Ptx::CUdeviceptr*)
+                                               ((address) parametersAndReturnValueBuffer +
+                                                parametersAndReturnValueBufferSize - sizeof(device_return_value));
     *returnValuePtr = device_return_value;
   }
 
@@ -417,7 +419,7 @@
     }
     thread->set_vm_result(return_val);
   } else if (returnTypeSize > 0) {
-    status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&primitiveReturnValue, device_return_value, T_LONG_BYTE_SIZE);
+    status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&primitiveReturnValue, device_return_value, returnTypeSize);
     if (status != GRAAL_CUDA_SUCCESS) {
       tty->print_cr("[CUDA] *** Error (%d) Failed to copy value from device argument", status);
       SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_Exception(), "[CUDA] Failed to copy value from device argument");
--- a/src/share/vm/oops/method.cpp	Fri Jan 17 17:10:46 2014 +0100
+++ b/src/share/vm/oops/method.cpp	Mon Jan 20 14:22:56 2014 +0100
@@ -2025,3 +2025,28 @@
   guarantee(md == NULL ||
       md->is_methodData(), "should be method data");
 }
+
+#ifdef GRAAL
+
+// Return true if the name of the method indicates that this is a
+// lambda method other than <init>. Lambda method is one with a name 
+// that starts with lambda$ and is synthetic.
+
+bool Method::is_lambda() const {
+  Symbol * klass_name = method_holder()->name();
+  Symbol * method_name = name();
+  ResourceMark rm;
+  if (klass_name != NULL) {
+    if (klass_name != NULL && method_name != NULL) {
+      const char* lambdaPrefix = "lambda$main$";
+      char* methodPrefix = strstr(method_name->as_C_string(), lambdaPrefix);
+      if (methodPrefix != 0) {
+        if ((strncmp(lambdaPrefix, methodPrefix, strlen(lambdaPrefix)) == 0) && is_synthetic()) {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+#endif
--- a/src/share/vm/oops/method.hpp	Fri Jan 17 17:10:46 2014 +0100
+++ b/src/share/vm/oops/method.hpp	Mon Jan 20 14:22:56 2014 +0100
@@ -617,6 +617,11 @@
   // simultaneously. Use with caution.
   bool has_compiled_code() const                 { return code() != NULL; }
 
+#ifdef GRAAL
+  // Return true if the name of the method indicates that this is a
+  // lambda method other than <init>.
+  bool is_lambda() const;
+#endif
   // sizing
   static int header_size()                       { return sizeof(Method)/HeapWordSize; }
   static int size(bool is_native);
--- a/src/share/vm/runtime/compilationPolicy.cpp	Fri Jan 17 17:10:46 2014 +0100
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Mon Jan 20 14:22:56 2014 +0100
@@ -45,6 +45,9 @@
 #include "runtime/vm_operations.hpp"
 #include "utilities/events.hpp"
 #include "utilities/globalDefinitions.hpp"
+#ifdef GRAAL
+#include "runtime/gpu.hpp"
+#endif
 
 CompilationPolicy* CompilationPolicy::_policy;
 elapsedTimer       CompilationPolicy::_accumulated_time;
@@ -101,6 +104,32 @@
   if (ReplayCompiles) return false;
 
   if (m->has_compiled_code()) return false;       // already compiled
+
+#ifdef GRAAL
+  // Check if this is a Lambda method that can be compiled to a GPU.
+  if (m->is_lambda()) {
+    // If GPU is available and the necessary linkage is available
+    // rerurn true indicatin that this method must be compiled.
+    if (gpu::is_available() && gpu::has_gpu_linkage()) {
+      if (TraceGPUInteraction) {
+        tty->print("Compiling Lambda method");
+        m->print_short_name();
+        switch (gpu::get_target_il_type()) {
+        case gpu::PTX :
+          tty->print_cr(" to PTX");
+          break;
+        case gpu::HSAIL :
+          tty->print_cr(" to HSAIL");
+          break;
+        default :
+          tty->print_cr(" to Unknown GPU!!!");
+        }
+      }
+      return true;
+    }
+  }
+#endif
+
   if (!can_be_compiled(m, comp_level)) return false;
 
   return !UseInterpreter ||                                              // must compile all methods