changeset 10474:55827d611da7

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 21 Jun 2013 17:52:19 +0200
parents 0d40e1cf70db (current diff) e4dd840a39de (diff)
children 3489047ffea2
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierAdditionTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExecuteChildren.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExtensionAnnotation.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionCodeElementFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionContextImpl.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java
diffstat 47 files changed, 1974 insertions(+), 1488 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierAdditionTest.java	Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.test;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.hotspot.phases.*;
-import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.tiers.*;
-
-public class WriteBarrierAdditionTest extends GraalCompilerTest {
-
-    public static class Container {
-
-        public Container a;
-        public Container b;
-    }
-
-    public static void test1Snippet() {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        main.a = temp1;
-        main.b = temp2;
-    }
-
-    public static void test2Snippet(boolean test) {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        for (int i = 0; i < 10; i++) {
-            if (test) {
-                main.a = temp1;
-                main.b = temp2;
-            } else {
-                main.a = temp2;
-                main.b = temp1;
-            }
-        }
-    }
-
-    public static void test3Snippet() {
-        Container[] main = new Container[10];
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        for (int i = 0; i < 10; i++) {
-            main[i].a = main[i].b = temp1;
-        }
-
-        for (int i = 0; i < 10; i++) {
-            main[i].a = main[i].b = temp2;
-        }
-
-    }
-
-    @Test
-    public void test1() {
-        test("test1Snippet", 2);
-    }
-
-    @Test
-    public void test2() {
-        test("test2Snippet", 4);
-    }
-
-    @Test
-    public void test3() {
-        test("test3Snippet", 4);
-    }
-
-    private void test(final String snippet, final int expectedBarriers) {
-        Debug.scope("WriteBarrierAditionTest", new DebugDumpScope(snippet), new Runnable() {
-
-            public void run() {
-                StructuredGraph graph = parse(snippet);
-                HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
-                new WriteBarrierAdditionPhase().apply(graph);
-                Debug.dump(graph, "After Write Barrier Addition");
-                final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
-                Assert.assertTrue(barriers == expectedBarriers);
-                for (WriteNode write : graph.getNodes(WriteNode.class)) {
-                    if (write.getWriteBarrierType() != WriteBarrierType.NONE) {
-                        Assert.assertTrue(write.successors().count() == 1);
-                        Assert.assertTrue(write.next() instanceof SerialWriteBarrier);
-                    }
-                }
-            }
-        });
-    }
-}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java	Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,712 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.test;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.hotspot.phases.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.graph.*;
-import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
-import com.oracle.graal.phases.tiers.*;
-
-/**
- * The following tests validate the write barrier verification phase. For every tested snippet, an
- * array of write barrier indices and the total write barrier number are passed as parameters. The
- * indices denote the barriers that will be manually removed. The write barrier verification phase
- * runs after the write barrier removal and depending on the result an assertion might be generated.
- * The tests anticipate the presence or not of an assertion generated by the verification phase.
- */
-public class WriteBarrierVerificationTest extends GraalCompilerTest {
-
-    public static int barrierIndex;
-
-    public static class Container {
-
-        public Container a;
-        public Container b;
-    }
-
-    private static native void safepoint();
-
-    public static void test1Snippet() {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        barrierIndex = 0;
-        safepoint();
-        barrierIndex = 1;
-        main.a = temp1;
-        safepoint();
-        barrierIndex = 2;
-        main.b = temp2;
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test1() {
-        test("test1Snippet", 2, new int[]{1});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test2() {
-        test("test1Snippet", 2, new int[]{2});
-    }
-
-    public static void test2Snippet() {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        barrierIndex = 0;
-        safepoint();
-        barrierIndex = 1;
-        main.a = temp1;
-        barrierIndex = 2;
-        main.b = temp2;
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test3() {
-        test("test2Snippet", 2, new int[]{1});
-    }
-
-    @Test
-    public void test4() {
-        test("test2Snippet", 2, new int[]{2});
-    }
-
-    public static void test3Snippet(boolean test) {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        barrierIndex = 0;
-        safepoint();
-        for (int i = 0; i < 10; i++) {
-            if (test) {
-                barrierIndex = 1;
-                main.a = temp1;
-                barrierIndex = 2;
-                main.b = temp2;
-            } else {
-                barrierIndex = 3;
-                main.a = temp1;
-                barrierIndex = 4;
-                main.b = temp2;
-            }
-        }
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test5() {
-        test("test3Snippet", 4, new int[]{1, 2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test6() {
-        test("test3Snippet", 4, new int[]{3, 4});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test7() {
-        test("test3Snippet", 4, new int[]{1});
-    }
-
-    @Test
-    public void test8() {
-        test("test3Snippet", 4, new int[]{2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test9() {
-        test("test3Snippet", 4, new int[]{3});
-    }
-
-    @Test
-    public void test10() {
-        test("test3Snippet", 4, new int[]{4});
-    }
-
-    public static void test4Snippet(boolean test) {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        safepoint();
-        barrierIndex = 1;
-        main.a = temp1;
-        for (int i = 0; i < 10; i++) {
-            if (test) {
-                barrierIndex = 2;
-                main.a = temp1;
-                barrierIndex = 3;
-                main.b = temp2;
-            } else {
-                barrierIndex = 4;
-                main.a = temp2;
-                barrierIndex = 5;
-                main.b = temp1;
-            }
-        }
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test11() {
-        test("test4Snippet", 5, new int[]{2, 3});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test12() {
-        test("test4Snippet", 5, new int[]{4, 5});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test13() {
-        test("test4Snippet", 5, new int[]{1});
-    }
-
-    public static void test5Snippet() {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        safepoint();
-        barrierIndex = 1;
-        main.a = temp1;
-        if (main.a == main.b) {
-            barrierIndex = 2;
-            main.a = temp1;
-            barrierIndex = 3;
-            main.b = temp2;
-        } else {
-            barrierIndex = 4;
-            main.a = temp2;
-            barrierIndex = 5;
-            main.b = temp1;
-        }
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test14() {
-        test("test5Snippet", 5, new int[]{1});
-    }
-
-    @Test
-    public void test15() {
-        test("test5Snippet", 5, new int[]{2});
-    }
-
-    @Test
-    public void test16() {
-        test("test5Snippet", 5, new int[]{4});
-    }
-
-    @Test
-    public void test17() {
-        test("test5Snippet", 5, new int[]{3});
-    }
-
-    @Test
-    public void test18() {
-        test("test5Snippet", 5, new int[]{5});
-    }
-
-    @Test
-    public void test19() {
-        test("test5Snippet", 5, new int[]{2, 3});
-    }
-
-    @Test
-    public void test20() {
-        test("test5Snippet", 5, new int[]{4, 5});
-    }
-
-    public static void test6Snippet(boolean test) {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        safepoint();
-        barrierIndex = 1;
-        main.a = temp1;
-        if (test) {
-            barrierIndex = 2;
-            main.a = temp1;
-            barrierIndex = 3;
-            main.b = temp1.a.a;
-        } else {
-            barrierIndex = 4;
-            main.a = temp2;
-            barrierIndex = 5;
-            main.b = temp2.a.a;
-        }
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test21() {
-        test("test6Snippet", 5, new int[]{1});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test22() {
-        test("test6Snippet", 5, new int[]{1, 2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test23() {
-        test("test6Snippet", 5, new int[]{3});
-    }
-
-    @Test
-    public void test24() {
-        test("test6Snippet", 5, new int[]{4});
-    }
-
-    public static void test7Snippet(boolean test) {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        safepoint();
-        barrierIndex = 1;
-        main.a = temp1;
-        if (test) {
-            barrierIndex = 2;
-            main.a = temp1;
-        }
-        barrierIndex = 3;
-        main.b = temp2;
-        safepoint();
-    }
-
-    @Test
-    public void test25() {
-        test("test7Snippet", 3, new int[]{2});
-    }
-
-    @Test
-    public void test26() {
-        test("test7Snippet", 3, new int[]{3});
-    }
-
-    @Test
-    public void test27() {
-        test("test7Snippet", 3, new int[]{2, 3});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test28() {
-        test("test7Snippet", 3, new int[]{1});
-    }
-
-    public static void test8Snippet(boolean test) {
-        Container main = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        safepoint();
-        if (test) {
-            barrierIndex = 1;
-            main.a = temp1;
-        }
-        barrierIndex = 2;
-        main.b = temp2;
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test29() {
-        test("test8Snippet", 2, new int[]{1});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test30() {
-        test("test8Snippet", 2, new int[]{2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test31() {
-        test("test8Snippet", 2, new int[]{1, 2});
-    }
-
-    public static void test9Snippet(boolean test) {
-        Container main1 = new Container();
-        Container main2 = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        safepoint();
-        if (test) {
-            barrierIndex = 1;
-            main1.a = temp1;
-        } else {
-            barrierIndex = 2;
-            main2.a = temp1;
-        }
-        barrierIndex = 3;
-        main1.b = temp2;
-        barrierIndex = 4;
-        main2.b = temp2;
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test32() {
-        test("test9Snippet", 4, new int[]{1});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test33() {
-        test("test9Snippet", 4, new int[]{2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test34() {
-        test("test9Snippet", 4, new int[]{3});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test35() {
-        test("test9Snippet", 4, new int[]{4});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test36() {
-        test("test9Snippet", 4, new int[]{1, 2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test37() {
-        test("test9Snippet", 4, new int[]{3, 4});
-    }
-
-    public static void test10Snippet(boolean test) {
-        Container main1 = new Container();
-        Container main2 = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        safepoint();
-        if (test) {
-            barrierIndex = 1;
-            main1.a = temp1;
-            barrierIndex = 2;
-            main2.a = temp2;
-        } else {
-            barrierIndex = 3;
-            main2.a = temp1;
-        }
-        barrierIndex = 4;
-        main1.b = temp2;
-        barrierIndex = 5;
-        main2.b = temp2;
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test38() {
-        test("test10Snippet", 5, new int[]{1});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test39() {
-        test("test10Snippet", 5, new int[]{2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test40() {
-        test("test10Snippet", 5, new int[]{3});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test41() {
-        test("test10Snippet", 5, new int[]{4});
-    }
-
-    @Test
-    public void test42() {
-        test("test10Snippet", 5, new int[]{5});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test43() {
-        test("test10Snippet", 5, new int[]{1, 2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test44() {
-        test("test10Snippet", 5, new int[]{1, 2, 3});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test45() {
-        test("test10Snippet", 5, new int[]{3, 4});
-    }
-
-    public static void test11Snippet(boolean test) {
-        Container main1 = new Container();
-        Container main2 = new Container();
-        Container main3 = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        safepoint();
-        if (test) {
-            barrierIndex = 1;
-            main1.a = temp1;
-            barrierIndex = 2;
-            main3.a = temp1;
-            if (!test) {
-                barrierIndex = 3;
-                main2.a = temp2;
-            } else {
-                barrierIndex = 4;
-                main1.a = temp2;
-                barrierIndex = 5;
-                main3.a = temp2;
-            }
-        } else {
-            barrierIndex = 6;
-            main1.b = temp2;
-            for (int i = 0; i < 10; i++) {
-                barrierIndex = 7;
-                main3.a = temp1;
-            }
-            barrierIndex = 8;
-            main3.b = temp2;
-        }
-        barrierIndex = 9;
-        main1.b = temp2;
-        barrierIndex = 10;
-        main2.b = temp2;
-        barrierIndex = 11;
-        main3.b = temp2;
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test46() {
-        test("test11Snippet", 11, new int[]{1});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test47() {
-        test("test11Snippet", 11, new int[]{2});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test48() {
-        test("test11Snippet", 11, new int[]{3});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test49() {
-        test("test11Snippet", 11, new int[]{6});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test50() {
-        test("test11Snippet", 11, new int[]{7});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test51() {
-        test("test11Snippet", 11, new int[]{8});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test52() {
-        test("test11Snippet", 11, new int[]{9});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test53() {
-        test("test11Snippet", 11, new int[]{10});
-    }
-
-    @Test
-    public void test54() {
-        test("test11Snippet", 11, new int[]{4});
-    }
-
-    @Test
-    public void test55() {
-        test("test11Snippet", 11, new int[]{5});
-    }
-
-    @Test
-    public void test56() {
-        test("test11Snippet", 11, new int[]{11});
-    }
-
-    public static void test12Snippet(boolean test) {
-        Container main = new Container();
-        Container main1 = new Container();
-        Container temp1 = new Container();
-        Container temp2 = new Container();
-        barrierIndex = 0;
-        safepoint();
-        barrierIndex = 7;
-        main1.a = temp1;
-        for (int i = 0; i < 10; i++) {
-            if (test) {
-                barrierIndex = 1;
-                main.a = temp1;
-                barrierIndex = 2;
-                main.b = temp2;
-            } else {
-                barrierIndex = 3;
-                main.a = temp1;
-                barrierIndex = 4;
-                main.b = temp2;
-            }
-        }
-        barrierIndex = 5;
-        main.a = temp1;
-        barrierIndex = 6;
-        main.b = temp1;
-        barrierIndex = 8;
-        main1.b = temp1;
-        safepoint();
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test57() {
-        test("test12Snippet", 8, new int[]{5});
-    }
-
-    @Test
-    public void test58() {
-        test("test12Snippet", 8, new int[]{6});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test59() {
-        test("test12Snippet", 8, new int[]{7});
-    }
-
-    @Test(expected = AssertionError.class)
-    public void test60() {
-        test("test12Snippet", 8, new int[]{8});
-    }
-
-    private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) {
-
-        AssertionError expectedError = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet), new Callable<AssertionError>() {
-
-            public AssertionError call() {
-                final StructuredGraph graph = parse(snippet);
-                HighTierContext highTierContext = new HighTierContext(runtime(), new Assumptions(false), replacements);
-                MidTierContext midTierContext = new MidTierContext(runtime(), new Assumptions(false), replacements, runtime().getTarget(), OptimisticOptimizations.ALL);
-
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, highTierContext);
-                new GuardLoweringPhase().apply(graph, midTierContext);
-                new SafepointInsertionPhase().apply(graph);
-                new WriteBarrierAdditionPhase().apply(graph);
-
-                // First, the total number of expected barriers is checked.
-                final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
-                Assert.assertTrue(expectedBarriers == barriers);
-
-                // Iterate over all write nodes and remove barriers according to input indices.
-                NodeIteratorClosure<Boolean> closure = new NodeIteratorClosure<Boolean>() {
-
-                    @Override
-                    protected Boolean processNode(FixedNode node, Boolean currentState) {
-                        if (node instanceof WriteNode) {
-                            WriteNode write = (WriteNode) node;
-                            LocationIdentity obj = write.getLocationIdentity();
-                            if (obj instanceof ResolvedJavaField) {
-                                if (((ResolvedJavaField) obj).getName().equals("barrierIndex")) {
-                                    /*
-                                     * A "barrierIndex" variable was found and is checked against
-                                     * the input barrier array.
-                                     */
-                                    if (eliminateBarrier(write.value().asConstant().asInt(), removedBarrierIndices)) {
-                                        return true;
-                                    }
-                                }
-                            }
-                        } else if (node instanceof SerialWriteBarrier) {
-                            // Remove flagged write barriers.
-                            if (currentState) {
-                                graph.removeFixed(((SerialWriteBarrier) node));
-                                return false;
-                            }
-                        }
-                        return currentState;
-                    }
-
-                    private boolean eliminateBarrier(int index, int[] map) {
-                        for (int i = 0; i < map.length; i++) {
-                            if (map[i] == index) {
-                                return true;
-                            }
-                        }
-                        return false;
-                    }
-
-                    @Override
-                    protected Map<LoopExitNode, Boolean> processLoop(LoopBeginNode loop, Boolean initialState) {
-                        return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
-                    }
-
-                    @Override
-                    protected Boolean merge(MergeNode merge, List<Boolean> states) {
-                        return false;
-                    }
-
-                    @Override
-                    protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
-                        return false;
-                    }
-                };
-
-                DebugConfig config = DebugScope.getConfig();
-                try {
-                    ReentrantNodeIterator.apply(closure, graph.start(), false, null);
-                    Debug.setConfig(Debug.fixedConfig(false, false, false, false, config.dumpHandlers(), config.output()));
-                    new WriteBarrierVerificationPhase().apply(graph);
-                } catch (AssertionError error) {
-                    /*
-                     * Catch assertion, test for expected one and re-throw in order to validate unit
-                     * test.
-                     */
-                    Assert.assertTrue(error.getMessage().equals("Write barrier must be present"));
-                    return error;
-                } finally {
-                    Debug.setConfig(config);
-                }
-                return null;
-            }
-        });
-        if (expectedError != null) {
-            throw expectedError;
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Fri Jun 21 17:52:19 2013 +0200
@@ -37,5 +37,7 @@
         appendPhase(new ExpandLogicPhase());
 
         appendPhase(new DeadCodeEliminationPhase());
+
+        appendPhase(new RemoveValueProxyPhase());
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class WriteBarrierAdditionTest extends GraalCompilerTest {
+
+    public static class Container {
+
+        public Container a;
+        public Container b;
+    }
+
+    public static void test1Snippet() {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        main.a = temp1;
+        main.b = temp2;
+    }
+
+    public static void test2Snippet(boolean test) {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        for (int i = 0; i < 10; i++) {
+            if (test) {
+                main.a = temp1;
+                main.b = temp2;
+            } else {
+                main.a = temp2;
+                main.b = temp1;
+            }
+        }
+    }
+
+    public static void test3Snippet() {
+        Container[] main = new Container[10];
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        for (int i = 0; i < 10; i++) {
+            main[i].a = main[i].b = temp1;
+        }
+
+        for (int i = 0; i < 10; i++) {
+            main[i].a = main[i].b = temp2;
+        }
+
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet", 2);
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", 4);
+    }
+
+    @Test
+    public void test3() {
+        test("test3Snippet", 4);
+    }
+
+    private void test(final String snippet, final int expectedBarriers) {
+        Debug.scope("WriteBarrierAditionTest", new DebugDumpScope(snippet), new Runnable() {
+
+            public void run() {
+                StructuredGraph graph = parse(snippet);
+                HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+                new WriteBarrierAdditionPhase().apply(graph);
+                Debug.dump(graph, "After Write Barrier Addition");
+                final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
+                Assert.assertTrue(barriers == expectedBarriers);
+                for (WriteNode write : graph.getNodes(WriteNode.class)) {
+                    if (write.getWriteBarrierType() != WriteBarrierType.NONE) {
+                        Assert.assertTrue(write.successors().count() == 1);
+                        Assert.assertTrue(write.next() instanceof SerialWriteBarrier);
+                    }
+                }
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * The following tests validate the write barrier verification phase. For every tested snippet, an
+ * array of write barrier indices and the total write barrier number are passed as parameters. The
+ * indices denote the barriers that will be manually removed. The write barrier verification phase
+ * runs after the write barrier removal and depending on the result an assertion might be generated.
+ * The tests anticipate the presence or not of an assertion generated by the verification phase.
+ */
+public class WriteBarrierVerificationTest extends GraalCompilerTest {
+
+    public static int barrierIndex;
+
+    public static class Container {
+
+        public Container a;
+        public Container b;
+    }
+
+    private static native void safepoint();
+
+    public static void test1Snippet() {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        barrierIndex = 0;
+        safepoint();
+        barrierIndex = 1;
+        main.a = temp1;
+        safepoint();
+        barrierIndex = 2;
+        main.b = temp2;
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test1() {
+        test("test1Snippet", 2, new int[]{1});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test2() {
+        test("test1Snippet", 2, new int[]{2});
+    }
+
+    public static void test2Snippet() {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        barrierIndex = 0;
+        safepoint();
+        barrierIndex = 1;
+        main.a = temp1;
+        barrierIndex = 2;
+        main.b = temp2;
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test3() {
+        test("test2Snippet", 2, new int[]{1});
+    }
+
+    @Test
+    public void test4() {
+        test("test2Snippet", 2, new int[]{2});
+    }
+
+    public static void test3Snippet(boolean test) {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        barrierIndex = 0;
+        safepoint();
+        for (int i = 0; i < 10; i++) {
+            if (test) {
+                barrierIndex = 1;
+                main.a = temp1;
+                barrierIndex = 2;
+                main.b = temp2;
+            } else {
+                barrierIndex = 3;
+                main.a = temp1;
+                barrierIndex = 4;
+                main.b = temp2;
+            }
+        }
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test5() {
+        test("test3Snippet", 4, new int[]{1, 2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test6() {
+        test("test3Snippet", 4, new int[]{3, 4});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test7() {
+        test("test3Snippet", 4, new int[]{1});
+    }
+
+    @Test
+    public void test8() {
+        test("test3Snippet", 4, new int[]{2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test9() {
+        test("test3Snippet", 4, new int[]{3});
+    }
+
+    @Test
+    public void test10() {
+        test("test3Snippet", 4, new int[]{4});
+    }
+
+    public static void test4Snippet(boolean test) {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        safepoint();
+        barrierIndex = 1;
+        main.a = temp1;
+        for (int i = 0; i < 10; i++) {
+            if (test) {
+                barrierIndex = 2;
+                main.a = temp1;
+                barrierIndex = 3;
+                main.b = temp2;
+            } else {
+                barrierIndex = 4;
+                main.a = temp2;
+                barrierIndex = 5;
+                main.b = temp1;
+            }
+        }
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test11() {
+        test("test4Snippet", 5, new int[]{2, 3});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test12() {
+        test("test4Snippet", 5, new int[]{4, 5});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test13() {
+        test("test4Snippet", 5, new int[]{1});
+    }
+
+    public static void test5Snippet() {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        safepoint();
+        barrierIndex = 1;
+        main.a = temp1;
+        if (main.a == main.b) {
+            barrierIndex = 2;
+            main.a = temp1;
+            barrierIndex = 3;
+            main.b = temp2;
+        } else {
+            barrierIndex = 4;
+            main.a = temp2;
+            barrierIndex = 5;
+            main.b = temp1;
+        }
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test14() {
+        test("test5Snippet", 5, new int[]{1});
+    }
+
+    @Test
+    public void test15() {
+        test("test5Snippet", 5, new int[]{2});
+    }
+
+    @Test
+    public void test16() {
+        test("test5Snippet", 5, new int[]{4});
+    }
+
+    @Test
+    public void test17() {
+        test("test5Snippet", 5, new int[]{3});
+    }
+
+    @Test
+    public void test18() {
+        test("test5Snippet", 5, new int[]{5});
+    }
+
+    @Test
+    public void test19() {
+        test("test5Snippet", 5, new int[]{2, 3});
+    }
+
+    @Test
+    public void test20() {
+        test("test5Snippet", 5, new int[]{4, 5});
+    }
+
+    public static void test6Snippet(boolean test) {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        safepoint();
+        barrierIndex = 1;
+        main.a = temp1;
+        if (test) {
+            barrierIndex = 2;
+            main.a = temp1;
+            barrierIndex = 3;
+            main.b = temp1.a.a;
+        } else {
+            barrierIndex = 4;
+            main.a = temp2;
+            barrierIndex = 5;
+            main.b = temp2.a.a;
+        }
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test21() {
+        test("test6Snippet", 5, new int[]{1});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test22() {
+        test("test6Snippet", 5, new int[]{1, 2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test23() {
+        test("test6Snippet", 5, new int[]{3});
+    }
+
+    @Test
+    public void test24() {
+        test("test6Snippet", 5, new int[]{4});
+    }
+
+    public static void test7Snippet(boolean test) {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        safepoint();
+        barrierIndex = 1;
+        main.a = temp1;
+        if (test) {
+            barrierIndex = 2;
+            main.a = temp1;
+        }
+        barrierIndex = 3;
+        main.b = temp2;
+        safepoint();
+    }
+
+    @Test
+    public void test25() {
+        test("test7Snippet", 3, new int[]{2});
+    }
+
+    @Test
+    public void test26() {
+        test("test7Snippet", 3, new int[]{3});
+    }
+
+    @Test
+    public void test27() {
+        test("test7Snippet", 3, new int[]{2, 3});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test28() {
+        test("test7Snippet", 3, new int[]{1});
+    }
+
+    public static void test8Snippet(boolean test) {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        safepoint();
+        if (test) {
+            barrierIndex = 1;
+            main.a = temp1;
+        }
+        barrierIndex = 2;
+        main.b = temp2;
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test29() {
+        test("test8Snippet", 2, new int[]{1});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test30() {
+        test("test8Snippet", 2, new int[]{2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test31() {
+        test("test8Snippet", 2, new int[]{1, 2});
+    }
+
+    public static void test9Snippet(boolean test) {
+        Container main1 = new Container();
+        Container main2 = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        safepoint();
+        if (test) {
+            barrierIndex = 1;
+            main1.a = temp1;
+        } else {
+            barrierIndex = 2;
+            main2.a = temp1;
+        }
+        barrierIndex = 3;
+        main1.b = temp2;
+        barrierIndex = 4;
+        main2.b = temp2;
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test32() {
+        test("test9Snippet", 4, new int[]{1});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test33() {
+        test("test9Snippet", 4, new int[]{2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test34() {
+        test("test9Snippet", 4, new int[]{3});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test35() {
+        test("test9Snippet", 4, new int[]{4});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test36() {
+        test("test9Snippet", 4, new int[]{1, 2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test37() {
+        test("test9Snippet", 4, new int[]{3, 4});
+    }
+
+    public static void test10Snippet(boolean test) {
+        Container main1 = new Container();
+        Container main2 = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        safepoint();
+        if (test) {
+            barrierIndex = 1;
+            main1.a = temp1;
+            barrierIndex = 2;
+            main2.a = temp2;
+        } else {
+            barrierIndex = 3;
+            main2.a = temp1;
+        }
+        barrierIndex = 4;
+        main1.b = temp2;
+        barrierIndex = 5;
+        main2.b = temp2;
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test38() {
+        test("test10Snippet", 5, new int[]{1});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test39() {
+        test("test10Snippet", 5, new int[]{2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test40() {
+        test("test10Snippet", 5, new int[]{3});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test41() {
+        test("test10Snippet", 5, new int[]{4});
+    }
+
+    @Test
+    public void test42() {
+        test("test10Snippet", 5, new int[]{5});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test43() {
+        test("test10Snippet", 5, new int[]{1, 2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test44() {
+        test("test10Snippet", 5, new int[]{1, 2, 3});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test45() {
+        test("test10Snippet", 5, new int[]{3, 4});
+    }
+
+    public static void test11Snippet(boolean test) {
+        Container main1 = new Container();
+        Container main2 = new Container();
+        Container main3 = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        safepoint();
+        if (test) {
+            barrierIndex = 1;
+            main1.a = temp1;
+            barrierIndex = 2;
+            main3.a = temp1;
+            if (!test) {
+                barrierIndex = 3;
+                main2.a = temp2;
+            } else {
+                barrierIndex = 4;
+                main1.a = temp2;
+                barrierIndex = 5;
+                main3.a = temp2;
+            }
+        } else {
+            barrierIndex = 6;
+            main1.b = temp2;
+            for (int i = 0; i < 10; i++) {
+                barrierIndex = 7;
+                main3.a = temp1;
+            }
+            barrierIndex = 8;
+            main3.b = temp2;
+        }
+        barrierIndex = 9;
+        main1.b = temp2;
+        barrierIndex = 10;
+        main2.b = temp2;
+        barrierIndex = 11;
+        main3.b = temp2;
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test46() {
+        test("test11Snippet", 11, new int[]{1});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test47() {
+        test("test11Snippet", 11, new int[]{2});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test48() {
+        test("test11Snippet", 11, new int[]{3});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test49() {
+        test("test11Snippet", 11, new int[]{6});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test50() {
+        test("test11Snippet", 11, new int[]{7});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test51() {
+        test("test11Snippet", 11, new int[]{8});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test52() {
+        test("test11Snippet", 11, new int[]{9});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test53() {
+        test("test11Snippet", 11, new int[]{10});
+    }
+
+    @Test
+    public void test54() {
+        test("test11Snippet", 11, new int[]{4});
+    }
+
+    @Test
+    public void test55() {
+        test("test11Snippet", 11, new int[]{5});
+    }
+
+    @Test
+    public void test56() {
+        test("test11Snippet", 11, new int[]{11});
+    }
+
+    public static void test12Snippet(boolean test) {
+        Container main = new Container();
+        Container main1 = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        barrierIndex = 0;
+        safepoint();
+        barrierIndex = 7;
+        main1.a = temp1;
+        for (int i = 0; i < 10; i++) {
+            if (test) {
+                barrierIndex = 1;
+                main.a = temp1;
+                barrierIndex = 2;
+                main.b = temp2;
+            } else {
+                barrierIndex = 3;
+                main.a = temp1;
+                barrierIndex = 4;
+                main.b = temp2;
+            }
+        }
+        barrierIndex = 5;
+        main.a = temp1;
+        barrierIndex = 6;
+        main.b = temp1;
+        barrierIndex = 8;
+        main1.b = temp1;
+        safepoint();
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test57() {
+        test("test12Snippet", 8, new int[]{5});
+    }
+
+    @Test
+    public void test58() {
+        test("test12Snippet", 8, new int[]{6});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test59() {
+        test("test12Snippet", 8, new int[]{7});
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test60() {
+        test("test12Snippet", 8, new int[]{8});
+    }
+
+    private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) {
+
+        AssertionError expectedError = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet), new Callable<AssertionError>() {
+
+            public AssertionError call() {
+                final StructuredGraph graph = parse(snippet);
+                HighTierContext highTierContext = new HighTierContext(runtime(), new Assumptions(false), replacements);
+                MidTierContext midTierContext = new MidTierContext(runtime(), new Assumptions(false), replacements, runtime().getTarget(), OptimisticOptimizations.ALL);
+
+                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, highTierContext);
+                new GuardLoweringPhase().apply(graph, midTierContext);
+                new SafepointInsertionPhase().apply(graph);
+                new WriteBarrierAdditionPhase().apply(graph);
+
+                // First, the total number of expected barriers is checked.
+                final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
+                Assert.assertTrue(expectedBarriers == barriers);
+
+                // Iterate over all write nodes and remove barriers according to input indices.
+                NodeIteratorClosure<Boolean> closure = new NodeIteratorClosure<Boolean>() {
+
+                    @Override
+                    protected Boolean processNode(FixedNode node, Boolean currentState) {
+                        if (node instanceof WriteNode) {
+                            WriteNode write = (WriteNode) node;
+                            LocationIdentity obj = write.getLocationIdentity();
+                            if (obj instanceof ResolvedJavaField) {
+                                if (((ResolvedJavaField) obj).getName().equals("barrierIndex")) {
+                                    /*
+                                     * A "barrierIndex" variable was found and is checked against
+                                     * the input barrier array.
+                                     */
+                                    if (eliminateBarrier(write.value().asConstant().asInt(), removedBarrierIndices)) {
+                                        return true;
+                                    }
+                                }
+                            }
+                        } else if (node instanceof SerialWriteBarrier) {
+                            // Remove flagged write barriers.
+                            if (currentState) {
+                                graph.removeFixed(((SerialWriteBarrier) node));
+                                return false;
+                            }
+                        }
+                        return currentState;
+                    }
+
+                    private boolean eliminateBarrier(int index, int[] map) {
+                        for (int i = 0; i < map.length; i++) {
+                            if (map[i] == index) {
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+
+                    @Override
+                    protected Map<LoopExitNode, Boolean> processLoop(LoopBeginNode loop, Boolean initialState) {
+                        return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
+                    }
+
+                    @Override
+                    protected Boolean merge(MergeNode merge, List<Boolean> states) {
+                        return false;
+                    }
+
+                    @Override
+                    protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
+                        return false;
+                    }
+                };
+
+                DebugConfig config = DebugScope.getConfig();
+                try {
+                    ReentrantNodeIterator.apply(closure, graph.start(), false, null);
+                    Debug.setConfig(Debug.fixedConfig(false, false, false, false, config.dumpHandlers(), config.output()));
+                    new WriteBarrierVerificationPhase().apply(graph);
+                } catch (AssertionError error) {
+                    /*
+                     * Catch assertion, test for expected one and re-throw in order to validate unit
+                     * test.
+                     */
+                    Assert.assertTrue(error.getMessage().equals("Write barrier must be present"));
+                    return error;
+                } finally {
+                    Debug.setConfig(config);
+                }
+                return null;
+            }
+        });
+        if (expectedError != null) {
+            throw expectedError;
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Jun 21 17:52:19 2013 +0200
@@ -51,6 +51,8 @@
 import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.Log.*;
 import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
+import static com.oracle.graal.hotspot.nodes.G1PostWriteBarrierStubCall.*;
+import static com.oracle.graal.hotspot.nodes.G1PreWriteBarrierStubCall.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -294,7 +296,8 @@
         linkForeignCall(r, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, NOT_REEXECUTABLE, NO_LOCATIONS);
-
+        linkForeignCall(r, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
         if (IntrinsifyObjectMethods.getValue()) {
             r.registerSubstitutions(ObjectSubstitutions.class);
         }
@@ -325,6 +328,8 @@
         writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, r, graalRuntime.getTarget());
         boxingSnippets = new BoxingSnippets.Templates(this, r, graalRuntime.getTarget());
         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, r, graalRuntime.getTarget());
+
+        r.registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(this, r, graalRuntime.getTarget()));
     }
 
     public HotSpotGraalRuntime getGraalRuntime() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrierStubCall.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.word.*;
+
+public class G1PostWriteBarrierStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
+
+    @Input private ValueNode cardAddress;
+    public static final ForeignCallDescriptor G1WBPOSTCALL = new ForeignCallDescriptor("write_barrier_post", void.class, Word.class);
+
+    public G1PostWriteBarrierStubCall(ValueNode cardAddress) {
+        super(StampFactory.forVoid());
+        this.cardAddress = cardAddress;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(G1PostWriteBarrierStubCall.G1WBPOSTCALL);
+        gen.emitForeignCall(linkage, this, gen.operand(cardAddress));
+    }
+
+    @NodeIntrinsic
+    public static native void call(Word cardAddress);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrierStubCall.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+public class G1PreWriteBarrierStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
+
+    @Input private ValueNode object;
+    public static final ForeignCallDescriptor G1WBPRECALL = new ForeignCallDescriptor("write_barrier_pre", void.class, Object.class);
+
+    public G1PreWriteBarrierStubCall(ValueNode object) {
+        super(StampFactory.forVoid());
+        this.object = object;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(G1PreWriteBarrierStubCall.G1WBPRECALL);
+        gen.emitForeignCall(linkage, this, gen.operand(object));
+    }
+
+    @NodeIntrinsic
+    public static native void call(Object hub);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Fri Jun 21 17:52:19 2013 +0200
@@ -41,8 +41,10 @@
         for (CompareAndSwapNode node : graph.getNodes(CompareAndSwapNode.class)) {
             addCASBarriers(node, graph);
         }
-        for (GenericArrayRangeWriteBarrier node : graph.getNodes(GenericArrayRangeWriteBarrier.class)) {
-            addArrayRangeBarriers(node, graph);
+        for (ArrayRangeWriteNode node : graph.getNodes(ArrayRangeWriteNode.class)) {
+            if (node.isObjectArray()) {
+                addArrayRangeBarriers(node, graph);
+            }
         }
     }
 
@@ -69,9 +71,9 @@
         }
     }
 
-    private static void addArrayRangeBarriers(GenericArrayRangeWriteBarrier node, StructuredGraph graph) {
-        SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getDstObject(), node.getDstPos(), node.getLength()));
-        graph.replaceFixedWithFixed(node, serialArrayRangeWriteBarrier);
+    private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) {
+        SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+        graph.addAfterFixed(node, serialArrayRangeWriteBarrier);
     }
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Jun 21 17:52:19 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -76,35 +76,11 @@
     private static final Kind VECTOR_KIND = Kind.Long;
     private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
 
-    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
+    private static void checkedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
         checkNonNull(src);
         checkNonNull(dest);
         checkLimits(src, srcPos, dest, destPos, length);
-        int header = arrayBaseOffset(baseKind);
-        int elementSize = arrayIndexScale(baseKind);
-        long byteLength = (long) length * elementSize;
-        long nonVectorBytes = byteLength % VECTOR_SIZE;
-        long srcOffset = (long) srcPos * elementSize;
-        long destOffset = (long) destPos * elementSize;
-        if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) {
-            // bad aliased case
-            for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) {
-                UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
-            }
-            long vectorLength = byteLength - nonVectorBytes;
-            for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        } else {
-            for (long i = 0; i < nonVectorBytes; i += elementSize) {
-                UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
-            }
-            for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        }
+        UnsafeArrayCopyNode.arraycopy(src, srcPos, dest, destPos, length, baseKind);
     }
 
     public static void checkNonNull(Object obj) {
@@ -149,85 +125,49 @@
     @Snippet
     public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
         byteCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
     }
 
     @Snippet
     public static void arraycopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
         booleanCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Boolean);
     }
 
     @Snippet
     public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
         charCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Char);
     }
 
     @Snippet
     public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
         shortCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Short);
     }
 
     @Snippet
     public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
         intCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Int);
     }
 
     @Snippet
     public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
         floatCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Float);
     }
 
     @Snippet
     public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
         longCounter.inc();
-        checkNonNull(src);
-        checkNonNull(dest);
-        checkLimits(src, srcPos, dest, destPos, length);
-        Kind baseKind = Kind.Long;
-        int header = arrayBaseOffset(baseKind);
-        long byteLength = (long) length * arrayIndexScale(baseKind);
-        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
-        long destOffset = (long) destPos * arrayIndexScale(baseKind);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        } else {
-            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        }
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Long);
     }
 
     @Snippet
     public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
         doubleCounter.inc();
-        checkNonNull(src);
-        checkNonNull(dest);
-        checkLimits(src, srcPos, dest, destPos, length);
-        Kind baseKind = Kind.Double;
-        int header = arrayBaseOffset(baseKind);
-        long byteLength = (long) length * arrayIndexScale(baseKind);
-        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
-        long destOffset = (long) destPos * arrayIndexScale(baseKind);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        } else {
-            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        }
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Double);
     }
 
     @Snippet
@@ -239,48 +179,25 @@
     @Snippet
     public static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) {
         objectCounter.inc();
-        checkNonNull(src);
-        checkNonNull(dest);
-        checkLimits(src, srcPos, dest, destPos, length);
-        final int scale = arrayIndexScale(Kind.Object);
-        int header = arrayBaseOffset(Kind.Object);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            long start = (long) (length - 1) * scale;
-            for (long i = start; i >= 0; i -= scale) {
-                Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
-                DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
-            }
-        } else {
-            long end = (long) length * scale;
-            for (long i = 0; i < end; i += scale) {
-                Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
-                DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
-
-            }
-        }
-        if (length > 0) {
-            GenericArrayRangeWriteBarrier.insertWriteBarrier(dest, destPos, length);
-        }
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Object);
     }
 
     @Snippet
     public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
-
         // loading the hubs also checks for nullness
         Word srcHub = loadHub(src);
         Word destHub = loadHub(dest);
-        int layoutHelper = checkArrayType(srcHub);
-        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
-        final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0);
+        if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, src != dest)) {
+            int layoutHelper = checkArrayType(srcHub);
+            final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0);
 
-        if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, src != dest)) {
             checkLimits(src, srcPos, dest, destPos, length);
             if (probability(FAST_PATH_PROBABILITY, isObjectArray)) {
                 genericObjectExactCallCounter.inc();
                 arrayObjectCopy(src, srcPos, dest, destPos, length);
             } else {
                 genericPrimitiveCallCounter.inc();
-                arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+                UnsafeArrayCopyNode.arraycopyPrimitive(src, srcPos, dest, destPos, length, layoutHelper);
             }
         } else {
             genericObjectCallCounter.inc();
@@ -288,33 +205,6 @@
         }
     }
 
-    public static void arraycopyInnerloop(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) {
-        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
-        int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
-
-        Word memory = (Word) Word.fromObject(src);
-
-        Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize);
-        Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize);
-        Word destStart = destOffset;
-        long sizeInBytes = ((long) length) << log2ElementSize;
-        Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize));
-
-        int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE);
-        Word destNonVectorEnd = destStart.add(nonVectorBytes);
-
-        while (destOffset.belowThan(destNonVectorEnd)) {
-            destOffset.writeByte(0, srcOffset.readByte(0, ANY_LOCATION), ANY_LOCATION);
-            destOffset = destOffset.add(1);
-            srcOffset = srcOffset.add(1);
-        }
-        while (destOffset.belowThan(destEnd)) {
-            destOffset.writeWord(0, srcOffset.readWord(0, ANY_LOCATION), ANY_LOCATION);
-            destOffset = destOffset.add(wordSize());
-            srcOffset = srcOffset.add(wordSize());
-        }
-    }
-
     private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
     private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess");
     private static final SnippetCounter checkNPECounter = new SnippetCounter(checkCounters, "checkNPE", "checkNPE");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Jun 21 17:52:19 2013 +0200
@@ -126,7 +126,7 @@
         Word hub = loadWordFromObject(elementType, arrayKlassOffset());
         if (hub.equal(Word.zero())) {
             // the array class is not yet loaded
-            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.Unresolved);
+            DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved);
         }
 
         int layoutHelper = readLayoutHelper(hub);
@@ -143,8 +143,8 @@
         //    esz is the element size in bytes
         //@formatter:on
 
-        int headerSize = (layoutHelper >> 16) & 0xFF;
-        int log2ElementSize = layoutHelper & 0xFF;
+        int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
+        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
 
         return allocateArray(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+
+public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single {
+
+    @Input private ValueNode src;
+    @Input private ValueNode srcPos;
+    @Input private ValueNode dest;
+    @Input private ValueNode destPos;
+    @Input private ValueNode length;
+    @Input private ValueNode layoutHelper;
+
+    private Kind elementKind;
+
+    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) {
+        super(StampFactory.forVoid());
+        assert layoutHelper == null || elementKind == null;
+        this.src = src;
+        this.srcPos = srcPos;
+        this.dest = dest;
+        this.destPos = destPos;
+        this.length = length;
+        this.layoutHelper = layoutHelper;
+        this.elementKind = elementKind;
+    }
+
+    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) {
+        this(src, srcPos, dest, destPos, length, null, elementKind);
+    }
+
+    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) {
+        this(src, srcPos, dest, destPos, length, layoutHelper, null);
+    }
+
+    @Override
+    public ValueNode getArray() {
+        return dest;
+    }
+
+    @Override
+    public ValueNode getIndex() {
+        return destPos;
+    }
+
+    @Override
+    public ValueNode getLength() {
+        return length;
+    }
+
+    @Override
+    public boolean isObjectArray() {
+        return elementKind == Kind.Object;
+    }
+
+    public Kind getElementKind() {
+        return elementKind;
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        if (loweringType == LoweringType.AFTER_GUARDS) {
+            UnsafeArrayCopySnippets.Templates templates = tool.getReplacements().getSnippetTemplateCache(UnsafeArrayCopySnippets.Templates.class);
+            templates.lower(this);
+        }
+    }
+
+    public void addSnippetArguments(Arguments args) {
+        args.add("src", src);
+        args.add("srcPos", srcPos);
+        args.add("dest", dest);
+        args.add("destPos", destPos);
+        args.add("length", length);
+        if (layoutHelper != null) {
+            args.add("layoutHelper", layoutHelper);
+        }
+    }
+
+    @Override
+    public LocationIdentity getLocationIdentity() {
+        if (elementKind == null) {
+            return ANY_LOCATION;
+        } else {
+            return NamedLocationIdentity.getArrayLocation(elementKind);
+        }
+    }
+
+    @NodeIntrinsic
+    public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind);
+
+    @NodeIntrinsic
+    public static native void arraycopyPrimitive(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.replacements.SnippetTemplate.*;
+import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.word.*;
+
+public class UnsafeArrayCopySnippets implements Snippets {
+
+    private static final Kind VECTOR_KIND = Kind.Long;
+    private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
+
+    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
+        int header = arrayBaseOffset(baseKind);
+        int elementSize = arrayIndexScale(baseKind);
+        long byteLength = (long) length * elementSize;
+        long nonVectorBytes = byteLength % VECTOR_SIZE;
+        long srcOffset = (long) srcPos * elementSize;
+        long destOffset = (long) destPos * elementSize;
+        if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) {
+            // bad aliased case
+            for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) {
+                UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
+            }
+            long vectorLength = byteLength - nonVectorBytes;
+            for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        } else {
+            for (long i = 0; i < nonVectorBytes; i += elementSize) {
+                UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
+            }
+            for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopyByte(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+    }
+
+    @Snippet
+    public static void arraycopyBoolean(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+    }
+
+    @Snippet
+    public static void arraycopyChar(char[] src, int srcPos, char[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char);
+    }
+
+    @Snippet
+    public static void arraycopyShort(short[] src, int srcPos, short[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short);
+    }
+
+    @Snippet
+    public static void arraycopyInt(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int);
+    }
+
+    @Snippet
+    public static void arraycopyFloat(float[] src, int srcPos, float[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float);
+    }
+
+    @Snippet
+    public static void arraycopyLong(long[] src, int srcPos, long[] dest, int destPos, int length) {
+        Kind baseKind = Kind.Long;
+        int header = arrayBaseOffset(baseKind);
+        long byteLength = (long) length * arrayIndexScale(baseKind);
+        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
+        long destOffset = (long) destPos * arrayIndexScale(baseKind);
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        } else {
+            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopyDouble(double[] src, int srcPos, double[] dest, int destPos, int length) {
+        Kind baseKind = Kind.Double;
+        int header = arrayBaseOffset(baseKind);
+        long byteLength = (long) length * arrayIndexScale(baseKind);
+        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
+        long destOffset = (long) destPos * arrayIndexScale(baseKind);
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        } else {
+            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        }
+    }
+
+    /**
+     * Does NOT perform store checks.
+     */
+    @Snippet
+    public static void arraycopyObject(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+        final int scale = arrayIndexScale(Kind.Object);
+        int header = arrayBaseOffset(Kind.Object);
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            long start = (long) (length - 1) * scale;
+            for (long i = start; i >= 0; i -= scale) {
+                Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
+                DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
+            }
+        } else {
+            long end = (long) length * scale;
+            for (long i = 0; i < end; i += scale) {
+                Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
+                DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopyPrimitive(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) {
+        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
+        int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
+
+        Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize);
+        Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize);
+        Word destStart = destOffset;
+        long sizeInBytes = ((long) length) << log2ElementSize;
+        Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize));
+
+        int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE);
+        Word destNonVectorEnd = destStart.add(nonVectorBytes);
+
+        while (destOffset.belowThan(destNonVectorEnd)) {
+            destOffset.writeByte(0, srcOffset.readByte(0, ANY_LOCATION), ANY_LOCATION);
+            destOffset = destOffset.add(1);
+            srcOffset = srcOffset.add(1);
+        }
+        while (destOffset.belowThan(destEnd)) {
+            destOffset.writeWord(0, srcOffset.readWord(0, ANY_LOCATION), ANY_LOCATION);
+            destOffset = destOffset.add(wordSize());
+            srcOffset = srcOffset.add(wordSize());
+        }
+    }
+
+    public static class Templates extends AbstractTemplates {
+
+        private final SnippetInfo[] arraycopySnippets;
+        private final SnippetInfo genericPrimitiveSnippet;
+
+        public Templates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
+
+            arraycopySnippets = new SnippetInfo[Kind.values().length];
+            arraycopySnippets[Kind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean");
+            arraycopySnippets[Kind.Byte.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyByte");
+            arraycopySnippets[Kind.Short.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyShort");
+            arraycopySnippets[Kind.Char.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyChar");
+            arraycopySnippets[Kind.Int.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyInt");
+            arraycopySnippets[Kind.Long.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyLong");
+            arraycopySnippets[Kind.Float.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyFloat");
+            arraycopySnippets[Kind.Double.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyDouble");
+            arraycopySnippets[Kind.Object.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyObject");
+
+            genericPrimitiveSnippet = snippet(UnsafeArrayCopySnippets.class, "arraycopyPrimitive");
+        }
+
+        public void lower(UnsafeArrayCopyNode node) {
+            Kind elementKind = node.getElementKind();
+            SnippetInfo snippet;
+            if (elementKind == null) {
+                // primitive array of unknown kind
+                snippet = genericPrimitiveSnippet;
+            } else {
+                snippet = arraycopySnippets[elementKind.ordinal()];
+                assert snippet != null : "arraycopy snippet for " + elementKind.name() + " not found";
+            }
+
+            Arguments args = new Arguments(snippet);
+            node.addSnippetArguments(args);
+
+            SnippetTemplate template = template(args);
+            template.instantiate(runtime, node, DEFAULT_REPLACER, args);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PostWriteBarrier.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.nodes.extended.*;
+
+public class G1PostWriteBarrier extends WriteBarrier {
+
+    @Input private ValueNode value;
+
+    public ValueNode getValue() {
+        return value;
+    }
+
+    public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) {
+        super(object, location, precise);
+        this.value = value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.nodes.extended.*;
+
+public class G1PreWriteBarrier extends WriteBarrier {
+
+    @Input private ValueNode expectedObject;
+    private final boolean doLoad;
+
+    public ValueNode getExpectedObject() {
+        return expectedObject;
+    }
+
+    public boolean doLoad() {
+        return doLoad;
+    }
+
+    public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) {
+        super(object, location, true);
+        this.doLoad = doLoad;
+        this.expectedObject = expectedObject;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java	Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class GenericArrayRangeWriteBarrier extends FixedWithNextNode implements Node.IterableNodeType {
-
-    @Input private ValueNode dstObject;
-    @Input private ValueNode dstPos;
-    @Input private ValueNode length;
-
-    public ValueNode getDstObject() {
-        return dstObject;
-    }
-
-    public ValueNode getDstPos() {
-        return dstPos;
-    }
-
-    public ValueNode getLength() {
-        return length;
-    }
-
-    public GenericArrayRangeWriteBarrier(ValueNode dstObject, ValueNode dstPos, ValueNode length) {
-        super(StampFactory.forVoid());
-        this.dstObject = dstObject;
-        this.dstPos = dstPos;
-        this.length = length;
-
-    }
-
-    @NodeIntrinsic
-    public static native void insertWriteBarrier(Object dstObject, int dstPos, int length);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java	Fri Jun 21 17:52:19 2013 +0200
@@ -22,39 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class SerialWriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType {
-
-    @Input private ValueNode object;
-    @Input private LocationNode location;
-    private final boolean precise;
 
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public LocationNode getLocation() {
-        return location;
-    }
-
-    public boolean usePrecise() {
-        return precise;
-    }
+public class SerialWriteBarrier extends WriteBarrier {
 
     public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.location = location;
-        this.precise = precise;
-    }
-
-    @Override
-    public void lower(LoweringTool generator, LoweringType loweringType) {
-        assert loweringType == LoweringType.AFTER_GUARDS;
-        generator.getRuntime().lower(this, generator);
+        super(object, location, precise);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class WriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType {
+
+    @Input private ValueNode object;
+    @Input private LocationNode location;
+    private final boolean precise;
+
+    public ValueNode getObject() {
+        return object;
+    }
+
+    public LocationNode getLocation() {
+        return location;
+    }
+
+    public boolean usePrecise() {
+        return precise;
+    }
+
+    public WriteBarrier(ValueNode object, LocationNode location, boolean precise) {
+        super(StampFactory.forVoid());
+        this.object = object;
+        this.location = location;
+        this.precise = precise;
+    }
+
+    @Override
+    public void lower(LoweringTool generator, LoweringType loweringType) {
+        assert loweringType == LoweringType.AFTER_GUARDS;
+        generator.getRuntime().lower(this, generator);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Base class for nodes that modify a range of an array.
+ */
+public abstract class ArrayRangeWriteNode extends AbstractStateSplit implements Node.IterableNodeType {
+
+    protected ArrayRangeWriteNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    /**
+     * The array that is written to.
+     */
+    public abstract ValueNode getArray();
+
+    /**
+     * The first modified index.
+     */
+    public abstract ValueNode getIndex();
+
+    /**
+     * The length of the modified range.
+     */
+    public abstract ValueNode getLength();
+
+    /**
+     * Return true if the written array is an object array, false if it is a primitive array.
+     */
+    public abstract boolean isObjectArray();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/CreateCast.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Specifies a factory method that creates a {@link Node} which is used to cast this child.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface CreateCast {
+
+    String[] value();
+
+}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExecuteChildren.java	Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.codegen;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface ExecuteChildren {
-
-    String[] value();
-
-}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExtensionAnnotation.java	Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.codegen;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.ANNOTATION_TYPE})
-public @interface ExtensionAnnotation {
-
-    String processorClassName();
-
-}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java	Fri Jun 21 17:52:19 2013 +0200
@@ -26,6 +26,10 @@
 
 import com.oracle.truffle.api.nodes.*;
 
+/**
+ * A {@link NodeChild} element defines an executable child for the enclosing {@link Node}. A
+ * {@link Node} contains multiple {@link NodeChildren} specified in linear execution order.
+ */
 @Retention(RetentionPolicy.CLASS)
 @Target({ElementType.TYPE})
 public @interface NodeChild {
@@ -35,13 +39,13 @@
     Class<?> type() default NodeClass.InheritNode.class;
 
     /**
-     * Executes the {@link NodeChild} with values from other defined {@link NodeChild} elements.
-     * These referenced children must be defined before the current node in the execution order. The
-     * current node {@link #type()} attribute must be set to a {@link Node} which supports the
-     * evaluated execution with the number of {@link #executeWith()} arguments that are defined. For
-     * example if this child is executed with one argument, the {@link #type()} attribute must
-     * define a node which publicly declares a method with the signature
-     * <code>Object execute*(VirtualFrame, Object)</code>.
+     * The {@link #executeWith()} property allows a node to pass the result of one child's
+     * executable as an input to another child's executable. These referenced children must be
+     * defined before the current node in the execution order. The current node {@link #type()}
+     * attribute must be set to a {@link Node} which supports the evaluated execution with the
+     * number of {@link #executeWith()} arguments that are defined. For example if this child is
+     * executed with one argument, the {@link #type()} attribute must define a node which publicly
+     * declares a method with the signature <code>Object execute*(VirtualFrame, Object)</code>.
      */
     String[] executeWith() default {};
 }
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java	Fri Jun 21 17:52:19 2013 +0200
@@ -24,42 +24,56 @@
 
 import java.lang.annotation.*;
 
+import com.oracle.truffle.api.nodes.*;
+
 /**
  * <p>
- * Annotates a type system class that represents type information for a node. Generates code for
- * converting and managing types. Methods contained in the type system may be annotated with
- * {@link TypeCast} or {@link TypeCheck}. These methods alter the default behavior of the type
- * system.
+ * Each {@link Node} has one {@link TypeSystem} at its root to define the types that can be used
+ * throughout the system. Multiple {@link TypeSystem}s are allowed, but they cannot be mixed inside
+ * a single {@link Node} hierarchy. A {@link TypeSystem} defines a list of types as its child
+ * elements, in which every type precedes its super types.The latter condition ensures that the most
+ * concrete type is found first when searching the list sequentially for the type of a given generic
+ * value.
  * </p>
  * 
- * 
- * <b>Example:</b>
  * <p>
- * Shows a <code>@TypeSystem</code> definition with three types. In this example BigIntegers can be
- * also treated as integers if their bit width is less than 32.
+ * Each {@link #value()} is represented as a java type. A type can specify two annotations:
+ * {@link TypeCheck} and {@link TypeCast}. The {@link TypeCheck} checks whether a given generic
+ * value matches to the current type. The {@link TypeCast} casts a generic type value to the current
+ * type. If the {@link TypeCheck} and {@link TypeCast} annotations are not declared in the
+ * {@link TypeSystem} the a default implementation is provided. The default implementation of
+ * {@link TypeCheck} returns <code>true</code> only on an exact type match and {@link TypeCast} is
+ * only a cast to this type. Specified methods with {@link TypeCheck} and {@link TypeCast} may be
+ * used to extend the definition of a type in the language. In our example, the
+ * <code>isInteger</code> and <code>asInteger</code> methods are defined in a way so that they
+ * accept also {@link Integer} values, implicitly converting them to {@link Double} . This example
+ * points out how we express implicit type conversions.
  * </p>
  * 
+ * <p>
+ * <b>Example:</b> The {@link TypeSystem} contains the types {@link Boolean}, {@link Integer}, and
+ * {@link Double}. The type {@link Object} is always used implicitly as the generic type represent
+ * all values.
+ * 
  * <pre>
  * 
- * {@literal @}TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
- * public abstract class Types {
+ * {@literal @}TypeSystem(types = {boolean.class, int.class, double.class})
+ * public abstract class ExampleTypeSystem {
  * 
  *     {@literal @}TypeCheck
  *     public boolean isInteger(Object value) {
- *         return value instanceof Integer || (value instanceof BigInteger &amp;&amp; ((BigInteger) value).bitLength() &lt; Integer.SIZE);
+ *         return value instanceof Integer || value instanceof Double;
  *     }
  * 
  *     {@literal @}TypeCast
- *     public int asInteger(Object value) {
- *         if (value instanceof Integer) {
- *             return (int) value;
- *         } else {
- *             return ((BigInteger) value).intValue();
- *         }
+ *     public double asInteger(Object value) {
+ *         return ((Number)value).doubleValue();
  *     }
  * }
  * </pre>
  * 
+ * </p>
+ * 
  * @see TypeCast
  * @see TypeCheck
  */
@@ -68,8 +82,7 @@
 public @interface TypeSystem {
 
     /**
-     * Sets the types contained by this type system. The order of types also determines the order of
-     * specialization.
+     * The list of types as child elements of the {@link TypeSystem}. Each precedes its super type.
      */
     Class[] value();
 
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java	Fri Jun 21 17:52:19 2013 +0200
@@ -24,10 +24,20 @@
 
 import java.lang.annotation.*;
 
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * References a {@link TypeSystem} on a node. Must be applied on a {@link Node} class. At least one
+ * {@link TypeSystem} must be referenced in a {@link Node}'s type hierarchy.
+ * 
+ * @see TypeSystem
+ * @see Node
+ */
 @Retention(RetentionPolicy.CLASS)
 @Target({ElementType.TYPE})
 public @interface TypeSystemReference {
 
+    /** The {@link TypeSystem} java type. */
     Class<?> value();
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Fri Jun 21 17:52:19 2013 +0200
@@ -583,8 +583,13 @@
         List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
         List<T> result = new ArrayList<>();
 
-        for (AnnotationValue value : values) {
-            result.add(resolveAnnotationValue(expectedListType, value));
+        if (values != null) {
+            for (AnnotationValue value : values) {
+                T annotationValue = resolveAnnotationValue(expectedListType, value);
+                if (annotationValue != null) {
+                    result.add(annotationValue);
+                }
+            }
         }
         return result;
     }
@@ -595,6 +600,10 @@
 
     @SuppressWarnings({"unchecked"})
     private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
+        if (value == null) {
+            return null;
+        }
+
         Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
         if (unboxedValue != null) {
             if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Fri Jun 21 17:52:19 2013 +0200
@@ -563,7 +563,7 @@
 
     public ExecutableElement findMethod() {
         Element element = currentElement;
-        while (element != null && (element.getKind() != ElementKind.METHOD)) {
+        while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) {
             element = element.getEnclosingElement();
         }
         ExecutableElement found = element != null ? (ExecutableElement) element : null;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionCodeElementFactory.java	Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.codegen.processor.ext;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.api.element.*;
-import com.oracle.truffle.codegen.processor.ast.*;
-
-final class ExtensionCodeElementFactory implements WritableElementFactory {
-
-    private final ProcessorContext context;
-
-    Element generatorElement;
-    AnnotationMirror generatorAnnotationMirror;
-
-    public ExtensionCodeElementFactory(ProcessorContext context) {
-        this.context = context;
-    }
-
-    @Override
-    public WritableExecutableElement cloneExecutableElement(ExecutableElement method) {
-        return updateGenerators(CodeExecutableElement.clone(context.getEnvironment(), method));
-    }
-
-    @Override
-    public WritableVariableElement cloneVariableElement(VariableElement var) {
-        return updateGenerators(CodeVariableElement.clone(var));
-    }
-
-    @Override
-    public WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror) {
-        return CodeAnnotationMirror.clone(mirror);
-    }
-
-    @Override
-    public WritableVariableElement createParameter(TypeMirror type, String simpleName) {
-        return updateGenerators(new CodeVariableElement(Utils.modifiers(), type, simpleName));
-    }
-
-    @Override
-    public WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName) {
-        return updateGenerators(new CodeExecutableElement(returnType, methodName));
-    }
-
-    @Override
-    public TypeMirror createTypeMirror(Class<?> javaClass) {
-        return context.getType(javaClass);
-    }
-
-    @Override
-    public WritableAnnotationMirror createAnnotationMirror(DeclaredType typeMirror) {
-        return new CodeAnnotationMirror(typeMirror);
-    }
-
-    @Override
-    public Name createName(String name) {
-        return CodeNames.of(name);
-    }
-
-    @Override
-    public AnnotationValue createAnnotationValue(Object value) {
-        return new CodeAnnotationValue(value);
-    }
-
-    private <E extends GeneratedElement> E updateGenerators(E element) {
-        element.setGeneratorElement(generatorElement);
-        element.setGeneratorAnnotationMirror(generatorAnnotationMirror);
-        return element;
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionContextImpl.java	Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.codegen.processor.ext;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-
-import com.oracle.truffle.codegen.processor.api.*;
-import com.oracle.truffle.codegen.processor.api.element.*;
-
-public class ExtensionContextImpl implements ExtensionContext {
-
-    private final ProcessingEnvironment env;
-    private final RoundEnvironment round;
-    private final WritableElementFactory factory;
-
-    private final List<WritableElement> elements = new ArrayList<>();
-
-    public ExtensionContextImpl(ProcessingEnvironment env, RoundEnvironment round, WritableElementFactory factory) {
-        this.env = env;
-        this.round = round;
-        this.factory = factory;
-    }
-
-    List<WritableElement> returnElements() {
-        List<WritableElement> returnElements = new ArrayList<>(this.elements);
-        this.elements.clear();
-        return returnElements;
-    }
-
-    @Override
-    public ProcessingEnvironment getProcessingEnvironment() {
-        return env;
-    }
-
-    @Override
-    public RoundEnvironment getRoundEnvironment() {
-        return round;
-    }
-
-    @Override
-    public WritableElementFactory getElementFactory() {
-        return factory;
-    }
-
-    @Override
-    public void addGeneratedElement(WritableElement element) {
-        elements.add(element);
-    }
-
-    @Override
-    public void removeGeneratedElement(WritableElement element) {
-        elements.remove(element);
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java	Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.codegen.processor.ext;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.api.*;
-import com.oracle.truffle.codegen.processor.api.element.*;
-import com.oracle.truffle.codegen.processor.template.*;
-
-public class ExtensionParser {
-
-    private final Map<String, ExtensionProcessor> extensions = new HashMap<>();
-    private final ProcessorContext context;
-    private final ExtensionCodeElementFactory factory;
-    private final ExtensionContextImpl extensionContext;
-
-    public ExtensionParser(ProcessorContext context) {
-        this.context = context;
-        this.factory = new ExtensionCodeElementFactory(context);
-        this.extensionContext = new ExtensionContextImpl(context.getEnvironment(), null, factory);
-    }
-
-    public List<WritableElement> parseAll(Template template, List<? extends Element> elements) {
-        List<WritableElement> generatedMethods = new ArrayList<>();
-        parseElement(template, generatedMethods, template.getTemplateType());
-
-        List<? extends ExecutableElement> methods = ElementFilter.methodsIn(elements);
-        for (ExecutableElement method : methods) {
-            for (VariableElement var : method.getParameters()) {
-                parseElement(template, generatedMethods, var);
-            }
-            parseElement(template, generatedMethods, method);
-        }
-
-        return generatedMethods;
-    }
-
-    private void parseElement(Template template, List<WritableElement> elements, Element element) {
-        List<? extends AnnotationMirror> mirrors = element.getAnnotationMirrors();
-        for (AnnotationMirror mirror : mirrors) {
-            ExtensionProcessor processor = findProcessor(template, mirror);
-            if (processor != null) {
-                try {
-                    factory.generatorAnnotationMirror = mirror;
-                    factory.generatorElement = element;
-                    processor.process(extensionContext, mirror, element);
-                    elements.addAll(extensionContext.returnElements());
-                } catch (Throwable e) {
-                    template.addError("Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e));
-                } finally {
-                    factory.generatorAnnotationMirror = null;
-                    factory.generatorElement = null;
-                }
-            }
-        }
-    }
-
-    private ExtensionProcessor findProcessor(Template template, AnnotationMirror mirror) {
-        String processorName = Utils.getQualifiedName(mirror.getAnnotationType());
-        ExtensionProcessor processor = null;
-        if (extensions.containsKey(processorName)) {
-            processor = extensions.get(processorName);
-        } else {
-            AnnotationMirror foundExtension = Utils.findAnnotationMirror(context.getEnvironment(), mirror.getAnnotationType().asElement(), ExtensionAnnotation.class);
-            if (foundExtension != null) {
-                String className = Utils.getAnnotationValue(String.class, foundExtension, "processorClassName");
-                Class<?> processorClass;
-                try {
-                    processorClass = Class.forName(className);
-                } catch (ClassNotFoundException e) {
-                    template.addError("Could not find processor class '%s' configured in '@%s'.", className, processorName);
-                    return null;
-                }
-                try {
-                    processor = (ExtensionProcessor) processorClass.newInstance();
-                } catch (InstantiationException e) {
-                    template.addError("Could not instantiate processor class '%s' configured in '@%s'.", className, processorName);
-                    return null;
-                } catch (IllegalAccessException e) {
-                    template.addError("Could not access processor class '%s' configured in '@%s'.", className, processorName);
-                    return null;
-                } catch (ClassCastException e) {
-                    template.addError("Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName());
-                    return null;
-                }
-            }
-            extensions.put(processorName, processor);
-        }
-        return processor;
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastData.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.node;
+
+import java.util.*;
+
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class CreateCastData extends TemplateMethod {
+
+    private final List<String> childNames;
+
+    public CreateCastData(TemplateMethod method, List<String> childNames) {
+        super(method);
+        this.childNames = childNames;
+    }
+
+    public List<String> getChildNames() {
+        return childNames;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastParser.java	Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.node;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class CreateCastParser extends NodeMethodParser<CreateCastData> {
+
+    public CreateCastParser(ProcessorContext context, NodeData operation) {
+        super(context, operation);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return CreateCast.class;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
+        TypeMirror baseType = getContext().getTruffleTypes().getNode();
+        for (String childName : childNames) {
+            NodeChildData child = getNode().findChild(childName);
+            if (child != null) {
+                baseType = child.getOriginalType();
+                break;
+            }
+        }
+        MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType));
+        addDefaultFieldMethodSpec(method, spec);
+        spec.addRequired(new ParameterSpec("castedChild", baseType)).setSignature(true);
+        return spec;
+    }
+
+    @Override
+    public CreateCastData create(TemplateMethod method) {
+        AnnotationMirror mirror = method.getMarkerAnnotation();
+        List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
+        CreateCastData cast = new CreateCastData(method, childNames);
+        AnnotationValue value = Utils.getAnnotationValue(mirror, "value");
+        TypeMirror type = null;
+        if (childNames == null || childNames.isEmpty()) {
+            cast.addError(value, "No value specified but required.");
+            return cast;
+        }
+
+        for (String childName : childNames) {
+            NodeChildData child = getNode().findChild(childName);
+            if (child == null) {
+                // error
+                cast.addError(value, "Specified child '%s' not found.", childName);
+                continue;
+            }
+            if (type == null) {
+                type = child.getNodeType();
+            } else if (!Utils.typeEquals(type, child.getNodeType())) {
+                cast.addError(value, "All child nodes for a cast must have the same node type.");
+                continue;
+            }
+        }
+        return cast;
+    }
+
+    private static class InheritsParameterSpec extends ParameterSpec {
+
+        private final ProcessorContext context;
+
+        public InheritsParameterSpec(ProcessorContext context, String name, TypeMirror... allowedTypes) {
+            super(name, Arrays.asList(allowedTypes));
+            this.context = context;
+        }
+
+        @Override
+        public boolean matches(TypeMirror actualType) {
+            boolean found = false;
+            for (TypeMirror specType : getAllowedTypes()) {
+                if (Utils.isAssignable(context, actualType, specType)) {
+                    found = true;
+                    break;
+                }
+            }
+            return found;
+        }
+    }
+}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java	Fri Jun 21 17:52:19 2013 +0200
@@ -54,6 +54,7 @@
 
     private final String name;
     private final TypeMirror type;
+    private final TypeMirror originalType;
     private final Element accessElement;
 
     private final Cardinality cardinality;
@@ -63,11 +64,13 @@
 
     private NodeData nodeData;
 
-    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, Element accessElement, Cardinality cardinality, ExecutionKind executionKind) {
+    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality,
+                    ExecutionKind executionKind) {
         this.sourceElement = sourceElement;
         this.sourceAnnotationMirror = sourceMirror;
         this.name = name;
         this.type = nodeType;
+        this.originalType = originalNodeType;
         this.accessElement = accessElement;
         this.cardinality = cardinality;
         this.executionKind = executionKind;
@@ -101,6 +104,10 @@
         return nodeData.getExecutableTypes(getExecuteWith().size());
     }
 
+    public TypeMirror getOriginalType() {
+        return originalType;
+    }
+
     @Override
     public Element getMessageElement() {
         return sourceElement;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri Jun 21 17:52:19 2013 +0200
@@ -143,7 +143,8 @@
         }
     }
 
-    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) {
+    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName,
+                    String... customSignatureValueNames) {
         CodeTreeBuilder builder = parent.create();
 
         boolean castedValues = sourceMethod != targetMethod;
@@ -199,8 +200,13 @@
         }
         builder.startCall(method.getSimpleName().toString());
 
+        int signatureIndex = 0;
+
         for (ActualParameter targetParameter : targetMethod.getParameters()) {
-            ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
+            ActualParameter valueParameter = null;
+            if (sourceMethod != null) {
+                valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
+            }
             if (valueParameter == null) {
                 valueParameter = targetParameter;
             }
@@ -215,7 +221,10 @@
                 valueType = valueParameter.getTypeSystemType();
             }
 
-            if (targetParameter.getSpecification().isLocal()) {
+            if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) {
+                builder.string(customSignatureValueNames[signatureIndex]);
+                signatureIndex++;
+            } else if (targetParameter.getSpecification().isLocal()) {
                 builder.startGroup();
                 if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) {
                     builder.string(THIS_NODE_LOCAL_VAR_NAME).string(".");
@@ -522,8 +531,25 @@
         return builder.getRoot();
     }
 
-    private void emitEncounteredSynthetic(CodeTreeBuilder builder) {
-        builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
+    private void emitEncounteredSynthetic(CodeTreeBuilder builder, SpecializationData current) {
+        builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class));
+        builder.startGroup();
+        String sep = null;
+        for (ActualParameter parameters : current.getParameters()) {
+            if (parameters.getSpecification().isSignature()) {
+                if (sep == null) {
+                    builder.doubleQuote("Unsupported values: " + parameters.getLocalName() + " = ");
+                    sep = ", ";
+                } else {
+                    builder.string(" + ");
+                    builder.doubleQuote(sep + parameters.getLocalName() + " = ");
+                }
+                builder.string(" + ");
+                builder.string(parameters.getLocalName());
+            }
+        }
+        builder.end();
+        builder.end().end();
     }
 
     private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
@@ -669,7 +695,12 @@
             }
 
             for (VariableElement var : type.getFields()) {
-                method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
+                NodeChildData child = getModel().findChild(var.getSimpleName().toString());
+                if (child != null) {
+                    method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
+                } else {
+                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
+                }
             }
 
             if (superConstructor != null) {
@@ -682,14 +713,25 @@
 
             for (VariableElement var : type.getFields()) {
                 builder.startStatement();
-                String varName = var.getSimpleName().toString();
-                builder.string("this.").string(varName);
+                String fieldName = var.getSimpleName().toString();
+
+                CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString());
+                builder.string("this.").string(var.getSimpleName().toString());
+
+                NodeChildData child = getModel().findChild(fieldName);
+                if (child != null) {
+                    CreateCastData createCast = getModel().findCast(child.getName());
+                    if (createCast != null) {
+                        fieldInit = createTemplateMethodCall(builder, null, getModel().getGenericSpecialization(), createCast, null, child.getName());
+                    }
+                }
+
                 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
-                    builder.string(" = adoptChild(").string(varName).string(")");
+                    builder.string(" = adoptChild(").tree(fieldInit).string(")");
                 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
-                    builder.string(" = adoptChildren(").string(varName).string(")");
+                    builder.string(" = adoptChildren(").tree(fieldInit).string(")");
                 } else {
-                    builder.string(" = ").string(varName);
+                    builder.string(" = ").tree(fieldInit);
                 }
                 builder.end();
             }
@@ -832,7 +874,7 @@
                         unreachableSpecializations.add(specialization);
                     } else {
                         filteredSpecializations.add(specialization);
-                        if (!specialization.isUninitialized() && !specialization.hasRewrite(getContext())) {
+                        if (!specialization.isUninitialized() && specialization.isGenericSpecialization(getContext())) {
                             unreachable = true;
                         }
                     }
@@ -877,7 +919,7 @@
             }
 
             if (specialize && executeCall == null && !current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) {
-                emitEncounteredSynthetic(builder);
+                emitEncounteredSynthetic(builder, current);
             } else if (specialize) {
 
                 if (current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) {
@@ -890,7 +932,7 @@
                         }
                         builder.statement("resultIsSet = true");
                     } else {
-                        emitEncounteredSynthetic(builder);
+                        emitEncounteredSynthetic(builder, current);
                     }
                     builder.end();
                 }
@@ -922,7 +964,7 @@
                 }
             } else {
                 if (executeCall == null) {
-                    emitEncounteredSynthetic(builder);
+                    emitEncounteredSynthetic(builder, current);
                 } else {
                     builder.startReturn().tree(executeCall).end();
                 }
@@ -1165,7 +1207,7 @@
 
             CodeTreeBuilder builder = method.createBuilder();
             if (!node.needsRewrites(getContext())) {
-                builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
+                builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).doubleQuote("No specialized version.").end().end();
             } else {
                 builder.startIf();
                 builder.string("types.length == 1");
@@ -1668,7 +1710,7 @@
                 returnBuilder.doubleQuote("Uninitialized");
                 returnBuilder.end();
             } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
-                emitEncounteredSynthetic(builder);
+                emitEncounteredSynthetic(builder, specialization);
             } else if (specialization.isGeneric()) {
                 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
                 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Fri Jun 21 17:52:19 2013 +0200
@@ -50,6 +50,7 @@
     private Map<Integer, List<ExecutableTypeData>> executableTypes;
     private List<ShortCircuitData> shortCircuits;
     private List<String> assumptions;
+    private List<CreateCastData> casts;
 
     private String shortName;
 
@@ -74,6 +75,14 @@
         this.assumptions = splitSource.assumptions;
     }
 
+    public List<CreateCastData> getCasts() {
+        return casts;
+    }
+
+    void setCasts(List<CreateCastData> casts) {
+        this.casts = casts;
+    }
+
     void setShortName(String shortName) {
         this.shortName = shortName;
     }
@@ -133,6 +142,9 @@
         if (fields != null) {
             containerChildren.addAll(fields);
         }
+        if (casts != null) {
+            containerChildren.addAll(casts);
+        }
         return containerChildren;
     }
 
@@ -230,6 +242,9 @@
         methods.addAll(getSpecializationListeners());
         methods.addAll(getExecutableTypes());
         methods.addAll(getShortCircuits());
+        if (getCasts() != null) {
+            methods.addAll(getCasts());
+        }
 
         return methods;
     }
@@ -367,6 +382,7 @@
         dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
         dumpProperty(builder, indent, "specializations", getSpecializations());
         dumpProperty(builder, indent, "assumptions", getAssumptions());
+        dumpProperty(builder, indent, "casts", getCasts());
         dumpProperty(builder, indent, "messages", collectMessages());
         if (getDeclaredNodes().size() > 0) {
             builder.append(String.format("\n%s  children = [", indent));
@@ -489,4 +505,15 @@
         return getClass().getSimpleName() + "[" + getNodeId() + "]";
     }
 
+    public CreateCastData findCast(String name) {
+        if (getCasts() != null) {
+            for (CreateCastData cast : getCasts()) {
+                if (cast.getChildNames().contains(name)) {
+                    return cast;
+                }
+            }
+        }
+        return null;
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java	Fri Jun 21 17:52:19 2013 +0200
@@ -78,20 +78,15 @@
     protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) {
         MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
 
-        if (getNode().supportsFrame()) {
-            methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
-        }
-
-        resolveAndAddImplicitThis(methodSpec, method);
+        addDefaultFrame(methodSpec);
+        addDefaultImplicitThis(method, methodSpec);
+        addDefaultFieldMethodSpec(method, methodSpec);
+        addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
 
-        for (NodeFieldData field : getNode().getFields()) {
-            if (!Utils.isFieldAccessible(method, field.getVariable())) {
-                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
-                spec.setLocal(true);
-                methodSpec.addOptional(spec);
-            }
-        }
+        return methodSpec;
+    }
 
+    private void addDefaultChildren(boolean shortCircuitsEnabled, String shortCircuitName, MethodSpec methodSpec) {
         // children are null when parsing executable types
         if (getNode().getChildren() != null) {
             for (NodeChildData child : getNode().getChildren()) {
@@ -117,11 +112,25 @@
                 }
             }
         }
+    }
 
-        return methodSpec;
+    private void addDefaultFrame(MethodSpec methodSpec) {
+        if (getNode().supportsFrame()) {
+            methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
+        }
     }
 
-    protected void resolveAndAddImplicitThis(MethodSpec methodSpec, ExecutableElement method) {
+    protected void addDefaultFieldMethodSpec(ExecutableElement method, MethodSpec methodSpec) {
+        for (NodeFieldData field : getNode().getFields()) {
+            if (!Utils.isFieldAccessible(method, field.getVariable())) {
+                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
+                spec.setLocal(true);
+                methodSpec.addOptional(spec);
+            }
+        }
+    }
+
+    protected void addDefaultImplicitThis(ExecutableElement method, MethodSpec methodSpec) {
         TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType();
 
         if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Fri Jun 21 17:52:19 2013 +0200
@@ -42,7 +42,7 @@
 public class NodeParser extends TemplateParser<NodeData> {
 
     public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
-                    ExecuteChildren.class, NodeClass.class, NodeChild.class, NodeChildren.class, NodeId.class);
+                    NodeClass.class, NodeChild.class, NodeChildren.class, NodeId.class);
 
     private Map<String, NodeData> parsedNodes;
 
@@ -211,6 +211,7 @@
     private static List<NodeData> splitNodeData(NodeData node) {
         SortedMap<String, List<SpecializationData>> groupedSpecializations = groupByNodeId(node.getSpecializations());
         SortedMap<String, List<SpecializationListenerData>> groupedListeners = groupByNodeId(node.getSpecializationListeners());
+        SortedMap<String, List<CreateCastData>> groupedCasts = groupByNodeId(node.getCasts());
 
         Set<String> ids = new TreeSet<>();
         ids.addAll(groupedSpecializations.keySet());
@@ -220,6 +221,7 @@
         for (String id : ids) {
             List<SpecializationData> specializations = groupedSpecializations.get(id);
             List<SpecializationListenerData> listeners = groupedListeners.get(id);
+            List<CreateCastData> casts = groupedCasts.get(id);
 
             if (specializations == null) {
                 specializations = new ArrayList<>();
@@ -238,12 +240,14 @@
 
             copy.setSpecializations(specializations);
             copy.setSpecializationListeners(listeners);
+            copy.setCasts(casts);
 
             splitted.add(copy);
         }
 
         node.setSpecializations(new ArrayList<SpecializationData>());
         node.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
+        node.setCasts(new ArrayList<CreateCastData>());
 
         return splitted;
     }
@@ -266,6 +270,7 @@
         node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements));
         List<SpecializationData> generics = new GenericParser(context, node).parse(elements);
         List<SpecializationData> specializations = new SpecializationMethodParser(context, node).parse(elements);
+        node.setCasts(new CreateCastParser(context, node).parse(elements));
 
         List<SpecializationData> allSpecializations = new ArrayList<>();
         allSpecializations.addAll(generics);
@@ -736,6 +741,18 @@
                 shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
             }
         }
+        Map<String, TypeMirror> castNodeTypes = new HashMap<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class);
+            if (mirror != null) {
+                List<String> children = (Utils.getAnnotationValueList(String.class, mirror, "value"));
+                if (children != null) {
+                    for (String child : children) {
+                        castNodeTypes.put(child, method.getReturnType());
+                    }
+                }
+            }
+        }
 
         List<NodeChildData> parsedChildren = new ArrayList<>();
         List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
@@ -754,8 +771,12 @@
             }
 
             List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
+            int index = 0;
             for (AnnotationMirror childMirror : children) {
                 String name = Utils.getAnnotationValue(String.class, childMirror, "value");
+                if (name.equals("")) {
+                    name = "child" + index;
+                }
 
                 Cardinality cardinality = Cardinality.ONE;
 
@@ -764,6 +785,12 @@
                     cardinality = Cardinality.MANY;
                 }
 
+                TypeMirror originalChildType = childType;
+                TypeMirror castNodeType = castNodeTypes.get(name);
+                if (castNodeType != null) {
+                    childType = castNodeType;
+                }
+
                 Element getter = findGetter(elements, name, childType);
 
                 ExecutionKind kind = ExecutionKind.DEFAULT;
@@ -771,7 +798,7 @@
                     kind = ExecutionKind.SHORT_CIRCUIT;
                 }
 
-                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, getter, cardinality, kind);
+                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
 
                 parsedChildren.add(nodeChild);
 
@@ -785,7 +812,9 @@
                 if (fieldNodeData == null) {
                     nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType));
                 }
+
             }
+            index++;
         }
 
         List<NodeChildData> filteredChildren = new ArrayList<>();
@@ -877,7 +906,7 @@
         }
 
         for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.typeEquals(method.getReturnType(), type)) {
+            if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) {
                 return method;
             }
         }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Fri Jun 21 17:52:19 2013 +0200
@@ -74,6 +74,24 @@
         return sinks;
     }
 
+    public boolean isGenericSpecialization(ProcessorContext context) {
+        if (hasRewrite(context)) {
+            return false;
+        }
+
+        for (ActualParameter parameter : getParameters()) {
+            NodeChildData child = getNode().findChild(parameter.getSpecification().getName());
+            if (child == null) {
+                continue;
+            }
+            if (!parameter.getTypeSystemType().isGeneric()) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     public boolean hasRewrite(ProcessorContext context) {
         if (!getExceptions().isEmpty()) {
             return true;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java	Fri Jun 21 17:52:19 2013 +0200
@@ -28,19 +28,11 @@
 import javax.lang.model.util.*;
 
 import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.ext.*;
 
 public abstract class TemplateParser<M extends Template> extends AbstractParser<M> {
 
-    private final ExtensionParser extensionParser;
-
     public TemplateParser(ProcessorContext c) {
         super(c);
-        extensionParser = new ExtensionParser(c);
-    }
-
-    public ExtensionParser getExtensionParser() {
-        return extensionParser;
     }
 
     protected void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java	Fri Jun 21 17:52:19 2013 +0200
@@ -103,8 +103,6 @@
                 }
             }
 
-            clazz.getEnclosedElements().addAll(typeSystem.getExtensionElements());
-
             return clazz;
         }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Fri Jun 21 17:52:19 2013 +0200
@@ -84,10 +84,6 @@
         verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
 
         List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
-        typeSystem.setExtensionElements(getExtensionParser().parseAll(typeSystem, elements));
-        if (typeSystem.getExtensionElements() != null) {
-            elements.addAll(typeSystem.getExtensionElements());
-        }
 
         List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
         List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java	Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java	Fri Jun 21 17:52:19 2013 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.truffle.api.codegen.*;
 
-@NodeChild(value = "expression", type = TypedNode.class)
+@NodeChild(type = TypedNode.class)
 public abstract class PrintNode extends StatementNode {
 
     private final PrintStream output;
--- a/mx/commands.py	Fri Jun 21 17:52:08 2013 +0200
+++ b/mx/commands.py	Fri Jun 21 17:52:19 2013 +0200
@@ -54,6 +54,8 @@
 
 _jacoco = 'off'
 
+_workdir = None
+
 _native_dbg = None
 
 _make_eclipse_launch = False
@@ -645,6 +647,11 @@
     if vm is None:
         vm = _vm
 
+    if cwd is None:
+        cwd = _workdir
+    elif _workdir is not None:
+        mx.abort("conflicting working directories: do not set --workdir for this command")
+
     build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
     jdk = _jdk(build, vmToCheck=vm)
     mx.expand_project_in_args(args)
@@ -1267,7 +1274,6 @@
                     '--dot-output-base', 'projects'] + args)
 
 def mx_init():
-    _vmbuild = 'product'
     commands = {
         'build': [build, '[-options]'],
         'buildvars': [buildvars, ''],
@@ -1298,6 +1304,7 @@
     }
 
     mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append'])
+    mx.add_argument('--workdir', help='runs the VM in the given directory', default=None)
 
     if (_vmSourcesAvailable):
         mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=_vmChoices, help='the VM to build/run (default: ' + _vmChoices[0] + ')')
@@ -1330,6 +1337,8 @@
         _make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False)
     global _jacoco
     _jacoco = opts.jacoco
+    global _workdir
+    _workdir = opts.workdir
     global _native_dbg
     _native_dbg = opts.native_dbg
 
--- a/mx/projects	Fri Jun 21 17:52:08 2013 +0200
+++ b/mx/projects	Fri Jun 21 17:52:19 2013 +0200
@@ -141,7 +141,7 @@
 # graal.hotspot.test
 project@com.oracle.graal.hotspot.test@subDir=graal
 project@com.oracle.graal.hotspot.test@sourceDirs=src
-project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test
+project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test,com.oracle.graal.hotspot
 project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.test@javaCompliance=1.7
 project@com.oracle.graal.hotspot.test@workingSets=Graal,HotSpot,Test
@@ -260,7 +260,7 @@
 # graal.replacements.test
 project@com.oracle.graal.replacements.test@subDir=graal
 project@com.oracle.graal.replacements.test@sourceDirs=src
-project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test
+project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test,com.oracle.graal.replacements
 project@com.oracle.graal.replacements.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.replacements.test@javaCompliance=1.7
 project@com.oracle.graal.replacements.test@workingSets=Graal,Replacements,Test
@@ -404,7 +404,7 @@
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
 project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.hotspot
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.test@javaCompliance=1.7
 project@com.oracle.graal.compiler.test@workingSets=Graal,Test
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Jun 21 17:52:08 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Fri Jun 21 17:52:19 2013 +0200
@@ -871,6 +871,8 @@
   set_int("g1SATBQueueMarkingOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()));
   set_int("g1SATBQueueIndexOffset", in_bytes(JavaThread::satb_mark_queue_offset() +  PtrQueue::byte_offset_of_index()));
   set_int("g1SATBQueueBufferOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()));
+  set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre);
+  set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post);
 
   BarrierSet* bs = Universe::heap()->barrier_set();
   switch (bs->kind()) {
--- a/src/share/vm/graal/graalRuntime.cpp	Fri Jun 21 17:52:08 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Fri Jun 21 17:52:19 2013 +0200
@@ -358,6 +358,14 @@
   }
 JRT_END
 
+JRT_LEAF(void, GraalRuntime::write_barrier_pre(JavaThread* thread, oopDesc* obj))
+  thread->satb_mark_queue().enqueue(obj);
+JRT_END
+
+JRT_LEAF(void, GraalRuntime::write_barrier_post(JavaThread* thread, void* card_addr))
+  thread->dirty_card_queue().enqueue(card_addr);
+JRT_END
+
 JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oop where, oop format, jlong value))
   ResourceMark rm;
   assert(where == NULL || java_lang_String::is_instance(where), "must be");
--- a/src/share/vm/graal/graalRuntime.hpp	Fri Jun 21 17:52:08 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Fri Jun 21 17:52:19 2013 +0200
@@ -52,6 +52,8 @@
     LOG_OBJECT_ADDRESS = 0x04
   };
   static void log_object(JavaThread* thread, oop msg, jint flags);
+  static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
+  static void write_barrier_post(JavaThread* thread, void* card);
 };
 
 #endif // SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP