changeset 7274:19f5c9b96fa7

Merge.
author Doug Simon <doug.simon@oracle.com>
date Tue, 18 Dec 2012 17:59:32 +0100
parents 7f6bf286629c (current diff) 17e12b5a3386 (diff)
children 4f220c85044d
files
diffstat 45 files changed, 4382 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Dec 18 17:59:03 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Dec 18 17:59:32 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -34,8 +36,8 @@
     @Successor protected final NodeSuccessorList<BeginNode> successors;
     protected double[] successorProbabilities;
     @Input private ValueNode value;
-    private final double[] keyProbabilities;
-    private final int[] keySuccessors;
+    private double[] keyProbabilities;
+    private int[] keySuccessors;
 
     public ValueNode value() {
         return value;
@@ -139,4 +141,13 @@
         }
         return probability;
     }
+
+    @Override
+    public SwitchNode clone(Graph into) {
+        SwitchNode newSwitch = (SwitchNode) super.clone(into);
+        newSwitch.successorProbabilities = Arrays.copyOf(successorProbabilities, successorProbabilities.length);
+        newSwitch.keyProbabilities = Arrays.copyOf(keyProbabilities, keyProbabilities.length);
+        newSwitch.keySuccessors = Arrays.copyOf(keySuccessors, keySuccessors.length);
+        return newSwitch;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+
+/**
+ * <h3>Passing Arguments</h3>
+ *
+ * <p>
+ * A guest language can pass its own custom arguments when invoking a Truffle method by creating a subclass of
+ * {@link Arguments}. When invoking a call target with {@link CallTarget#call(Arguments)}, the arguments can be passed.
+ * A Truffle node can access the arguments passed into the Truffle method by using {@link VirtualFrame#getArguments()}.
+ * </p>
+ *
+ * <p>
+ * The arguments class should only contain fields that are declared as final. This allows the Truffle runtime to improve
+ * optimizations around guest language method calls. Also, the arguments object must never be stored into a field. It
+ * should be created immediately before invoking {@link CallTarget#call(Arguments)} and no longer be accessed
+ * afterwards.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.FrameTest}.
+ * </p>
+ */
+public class ArgumentsTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestRootNode rootNode = new TestRootNode(new TestArgumentNode[]{new TestArgumentNode(0), new TestArgumentNode(1)});
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call(new TestArguments(20, 22));
+        Assert.assertEquals(42, result);
+    }
+
+    class TestArguments extends Arguments {
+        final int[] values;
+        TestArguments(int... values) {
+            this.values = values;
+        }
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Children private TestArgumentNode[] children;
+
+        TestRootNode(TestArgumentNode[] children) {
+            this.children = adoptChildren(children);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].execute(frame);
+            }
+            return sum;
+        }
+    }
+
+    class TestArgumentNode extends Node {
+        private final int index;
+
+        TestArgumentNode(int index) {
+            this.index = index;
+        }
+
+        int execute(VirtualFrame frame) {
+            return ((TestArguments) frame.getArguments()).values[index];
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+
+/**
+ * <h3>Calling Another Tree</h3>
+ *
+ * <p>
+ * A guest language implementation can create multiple call targets using the {@link TruffleRuntime#createCallTarget(RootNode)} method.
+ * Those call targets can be passed around as normal Java objects and used for calling guest language methods.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ArgumentsTest}.
+ * </p>
+ */
+public class CallTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        CallTarget foo = runtime.createCallTarget(new ConstantRootNode(20));
+        CallTarget bar = runtime.createCallTarget(new ConstantRootNode(22));
+        CallTarget main = runtime.createCallTarget(new DualCallNode(foo, bar));
+        Object result = main.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class DualCallNode extends RootNode {
+
+        private final CallTarget firstTarget;
+        private final CallTarget secondTarget;
+
+        DualCallNode(CallTarget firstTarget, CallTarget secondTarget) {
+            this.firstTarget = firstTarget;
+            this.secondTarget = secondTarget;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return ((Integer) firstTarget.call()) + ((Integer) secondTarget.call());
+        }
+    }
+
+    class ConstantRootNode extends RootNode {
+        private final int value;
+
+        public ConstantRootNode(int value) {
+            this.value = value;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return value;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.Node.Child;
+
+/**
+ * <h3>Creating a Child Node</h3>
+ *
+ * <p>
+ * Child nodes are stored in the class of the parent node in fields that are marked with the {@link Child} annotation.
+ * Before such a field is assigned, {@link Node#adoptChild} must be called. This method automatically establishes a link
+ * from the child to the parent. The {@link Node#getParent()} method allows access to this field. Every node also
+ * provides the ability to iterate over its children using {@link Node#getChildren()}.</p>
+ *
+ * <p>A child node field must be declared private and non-final. It may only be assigned in the constructor of the parent
+ * node. For changing the structure of the tree at run time, the method {@link Node#replace(Node)} must be used (see
+ * {@link ReplaceTest}).
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ChildrenNodesTest}.
+ * </p>
+ */
+public class ChildNodeTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildNode leftChild = new TestChildNode();
+        TestChildNode rightChild = new TestChildNode();
+        TestRootNode rootNode = new TestRootNode(leftChild, rightChild);
+        Assert.assertEquals(rootNode, leftChild.getParent());
+        Assert.assertEquals(rootNode, rightChild.getParent());
+        Iterator<Node> iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(leftChild, iterator.next());
+        Assert.assertEquals(rightChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child private TestChildNode left;
+        @Child private TestChildNode right;
+
+        public TestRootNode(TestChildNode left, TestChildNode right) {
+            this.left = adoptChild(left);
+            this.right = adoptChild(right);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return left.execute() + right.execute();
+        }
+    }
+
+    class TestChildNode extends Node {
+
+        public int execute() {
+            return 21;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Creating an Array of Children Nodes</h3>
+ *
+ * <p>
+ * An array of children nodes can be used as a field in a parent node. The field has to be annotated with
+ * {@link com.oracle.truffle.api.nodes.Node.Children} and must be declared private and final. Before assigning the field
+ * in the parent node constructor, {@link Node#adoptChildren} must be called in order to update the parent pointers in
+ * the child nodes. After filling the array with its first values, it must never be changed. It is only possible to call
+ * {@link Node#replace} on a child node.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.FinalFieldTest}.
+ * </p>
+ */
+public class ChildrenNodesTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildNode firstChild = new TestChildNode();
+        TestChildNode secondChild = new TestChildNode();
+        TestRootNode rootNode = new TestRootNode(new TestChildNode[]{firstChild, secondChild});
+        Assert.assertEquals(rootNode, firstChild.getParent());
+        Assert.assertEquals(rootNode, secondChild.getParent());
+        Iterator<Node> iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(firstChild, iterator.next());
+        Assert.assertEquals(secondChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Children private final TestChildNode[] children;
+
+        public TestRootNode(TestChildNode[] children) {
+            this.children = adoptChildren(children);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].execute();
+            }
+            return sum;
+        }
+    }
+
+    class TestChildNode extends Node {
+        public int execute() {
+            return 21;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Using Final Fields in Node Classes</h3>
+ *
+ * <p>
+ * The usage of final fields in node classes is highly encouraged. It is beneficial for performance to declare every
+ * field that is not pointing to a child node as final. This gives the Truffle runtime an increased opportunity to
+ * optimize this node.
+ * </p>
+ *
+ * <p>
+ * If a node has a value which may change at run time, but will rarely do so, it is recommended to speculate on the
+ * field being final. This involves starting executing with a node where this field is final and only if this
+ * turns out to be no longer the case, the node is replaced with an alternative implementation of the operation (see
+ * {@link ReplaceTest}).
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ReplaceTest}.
+ * </p>
+ */
+public class FinalFieldTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestRootNode rootNode = new TestRootNode(new TestChildNode[]{new TestChildNode(20), new TestChildNode(22)});
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Children TestChildNode[] children;
+
+        public TestRootNode(TestChildNode[] children) {
+            this.children = adoptChildren(children);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].execute();
+            }
+            return sum;
+        }
+    }
+
+    class TestChildNode extends Node {
+        private final int value;
+
+        public TestChildNode(int value) {
+            this.value = value;
+        }
+
+        public int execute() {
+            return value;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+
+/**
+ * <h3>Specializing Frame Slot Types</h3>
+ *
+ * <p>
+ * Dynamically typed languages can speculate on the type of a frame slot and only fall back at run time to a more
+ * generic type if necessary. The new type of a frame slot can be set using the {@link FrameSlot#setType(Class)} method.
+ * It is the responsibility of the language implementor to update the content of currently active frames (using
+ * {@link Frame#updateToLatestVersion()}). Also, nodes that depend a specific type of a frame slot must be replaced.
+ * Such node can register a listener that implements {@link FrameSlotTypeListener} using
+ * {@link FrameSlot#registerOneShotTypeListener(FrameSlotTypeListener)}. The event of a type change on the frame slot
+ * will fire only once for the next upcoming change.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}.
+ * </p>
+ */
+public class FrameSlotTypeSpecializationTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        FrameDescriptor frameDescriptor = new FrameDescriptor();
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class);
+        TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
+        Assert.assertEquals(Integer.class, slot.getType());
+        Object result = target.call();
+        Assert.assertEquals("42", result);
+        Assert.assertEquals(Object.class, slot.getType());
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child TestChildNode left;
+        @Child TestChildNode right;
+
+        public TestRootNode(TestChildNode left, TestChildNode right) {
+            this.left = adoptChild(left);
+            this.right = adoptChild(right);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            left.execute(frame);
+            return right.execute(frame);
+        }
+    }
+
+    abstract class TestChildNode extends Node {
+        abstract Object execute(VirtualFrame frame);
+    }
+
+    abstract class FrameSlotNode extends TestChildNode {
+        protected final FrameSlot slot;
+
+        public FrameSlotNode(FrameSlot slot) {
+            this.slot = slot;
+        }
+    }
+
+    class StringTestChildNode extends TestChildNode {
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            return "42";
+        }
+
+    }
+
+    class IntAssignLocal extends FrameSlotNode implements FrameSlotTypeListener {
+        @Child private TestChildNode value;
+
+        IntAssignLocal(FrameSlot slot, TestChildNode value) {
+            super(slot);
+            this.value = adoptChild(value);
+            slot.registerOneShotTypeListener(this);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            Object o = value.execute(frame);
+            if (o instanceof Integer) {
+                frame.setInt(slot, (Integer) o);
+            } else {
+                slot.setType(Object.class);
+                frame.updateToLatestVersion();
+                frame.setObject(slot, o);
+            }
+            return null;
+        }
+
+        @Override
+        public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) {
+            if (changedSlot.getType() == Object.class) {
+                this.replace(new ObjectAssignLocal(changedSlot, value));
+            }
+        }
+    }
+
+    class ObjectAssignLocal extends FrameSlotNode {
+        @Child private TestChildNode value;
+
+        ObjectAssignLocal(FrameSlot slot, TestChildNode value) {
+            super(slot);
+            this.value = adoptChild(value);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            Object o = value.execute(frame);
+            frame.setObject(slot, o);
+            return null;
+        }
+    }
+
+    class IntReadLocal extends FrameSlotNode implements FrameSlotTypeListener {
+        IntReadLocal(FrameSlot slot) {
+            super(slot);
+            slot.registerOneShotTypeListener(this);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            return frame.getInt(slot);
+        }
+
+        @Override
+        public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) {
+            if (changedSlot.getType() == Object.class) {
+                this.replace(new ObjectReadLocal(changedSlot));
+            }
+        }
+    }
+
+    class ObjectReadLocal extends FrameSlotNode {
+        ObjectReadLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            return frame.getObject(slot);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Storing Values in Frame Slots</h3>
+ *
+ * <p>
+ * The frame is the preferred data structure for passing values between nodes. It can in particular be used for storing
+ * the values of local variables of the guest language. The {@link FrameDescriptor} represents the current structure of
+ * the frame. The method {@link FrameDescriptor#addFrameSlot(String, Class)} can be used to create predefined frame
+ * slots. The setter and getter methods in the {@link Frame} class can be used to access the current value of a
+ * particular frame slot.
+ * </p>
+ *
+ * <p>
+ * There are five primitive types for slots available: {@link java.lang.Boolean}, @{link java.lang.Integer},
+ * {@link java.lang.Long}, {@link java.lang.Float}, and {@link java.lang.Double}. It is encouraged to use those types
+ * whenever possible. Dynamically typed languages can speculate on the type of a value fitting into a primitive (see
+ * {@link FrameSlotTypeSpecializationTest}). When a frame slot is of one of those particular primitive types, its value
+ * may only be accessed with the repectively typed getter method ({@link Frame#getBoolean}, {@link Frame#getInt},
+ * {@link Frame#getLong}, {@link Frame#getFloat}, or {@link Frame#getDouble}) or setter method ({@link Frame#setBoolean},
+ * {@link Frame#setInt}, {@link Frame#setLong}, {@link Frame#setFloat}, or {@link Frame#setDouble}) in the
+ * {@link Frame} class.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}.
+ * </p>
+ */
+public class FrameTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        FrameDescriptor frameDescriptor = new FrameDescriptor();
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class);
+        TestRootNode rootNode = new TestRootNode(new AssignLocal(slot), new ReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child TestChildNode left;
+        @Child TestChildNode right;
+
+        public TestRootNode(TestChildNode left, TestChildNode right) {
+            this.left = adoptChild(left);
+            this.right = adoptChild(right);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return left.execute(frame) + right.execute(frame);
+        }
+    }
+
+    abstract class TestChildNode extends Node {
+        abstract int execute(VirtualFrame frame);
+    }
+
+    abstract class FrameSlotNode extends TestChildNode {
+        protected final FrameSlot slot;
+
+        public FrameSlotNode(FrameSlot slot) {
+            this.slot = slot;
+        }
+    }
+
+    class AssignLocal extends FrameSlotNode {
+        AssignLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            frame.setInt(slot, 42);
+            return 0;
+        }
+    }
+
+    class ReadLocal extends FrameSlotNode {
+        ReadLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            return frame.getInt(slot);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+
+/**
+ * <h3>Replacing Nodes at Run Time</h3>
+ *
+ * <p>
+ * The structure of the Truffle tree can be changed at run time by replacing nodes using the {@link Node#replace(Node)}
+ * method. This method will automatically change the child pointer in the parent of the node and replace it with a
+ * pointer to the new node.
+ * </p>
+ *
+ * <p>
+ * Replacing nodes is a costly operation, so it should not happen too often. The convention is that the implementation
+ * of the Truffle nodes should ensure that there are maximal a small (and constant) number of node replacements per
+ * Truffle node.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.CallTest}.
+ * </p>
+ */
+public class ReplaceTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        UnresolvedNode leftChild = new UnresolvedNode("20");
+        UnresolvedNode rightChild = new UnresolvedNode("22");
+        TestRootNode rootNode = new TestRootNode(new ValueNode[]{leftChild, rightChild});
+        assertEquals(rootNode, leftChild.getParent());
+        assertEquals(rootNode, rightChild.getParent());
+        Iterator<Node> iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(leftChild, iterator.next());
+        Assert.assertEquals(rightChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call();
+        assertEquals(42, result);
+        assertEquals(42, target.call());
+        iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(ResolvedNode.class, iterator.next().getClass());
+        Assert.assertEquals(ResolvedNode.class, iterator.next().getClass());
+        Assert.assertFalse(iterator.hasNext());
+        iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(rootNode, iterator.next().getParent());
+        Assert.assertEquals(rootNode, iterator.next().getParent());
+        Assert.assertFalse(iterator.hasNext());
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Children private ValueNode[] children;
+
+        public TestRootNode(ValueNode[] children) {
+            this.children = adoptChildren(children);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].execute();
+            }
+            return sum;
+        }
+    }
+
+    abstract class ValueNode extends Node {
+        abstract int execute();
+    }
+
+    class UnresolvedNode extends ValueNode {
+        private final String value;
+
+        public UnresolvedNode(String value) {
+            this.value = value;
+        }
+
+        @Override
+        int execute() {
+            int intValue = Integer.parseInt(value);
+            ResolvedNode newNode = this.replace(new ResolvedNode(intValue));
+            return newNode.execute();
+        }
+    }
+
+    class ResolvedNode extends ValueNode {
+        private final int value;
+
+        ResolvedNode(int value) {
+            this.value = value;
+        }
+
+        @Override
+        int execute() {
+            return value;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Specializing Return Types</h3>
+ *
+ * <p>
+ * In order to avoid boxing and/or type casts on the return value of a node, the return value the method for executing a
+ * node can have a specific type and need not be of type {@link java.lang.Object}. For dynamically typed languages, this
+ * return type is something that should be speculated on. When the speculation fails and the child node cannot return
+ * the appropriate type of value, it can use an {@link UnexpectedResultException} to still pass the result to the
+ * caller. In such a case, the caller must rewrite itself to a more general version in oder to avoid future failures of
+ * this kind.
+ * </p>
+ */
+public class ReturnTypeSpecializationTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        FrameDescriptor frameDescriptor = new FrameDescriptor();
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class);
+        TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
+        Assert.assertEquals(Integer.class, slot.getType());
+        Object result = target.call();
+        Assert.assertEquals("42", result);
+        Assert.assertEquals(Object.class, slot.getType());
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child TestChildNode left;
+        @Child TestChildNode right;
+
+        public TestRootNode(TestChildNode left, TestChildNode right) {
+            this.left = adoptChild(left);
+            this.right = adoptChild(right);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            left.execute(frame);
+            return right.execute(frame);
+        }
+    }
+
+    abstract class TestChildNode extends Node {
+        abstract Object execute(VirtualFrame frame);
+
+        int executeInt(VirtualFrame frame) throws UnexpectedResultException {
+            Object result = execute(frame);
+            if (result instanceof Integer) {
+                return (Integer) result;
+            }
+            throw new UnexpectedResultException(result);
+        }
+    }
+
+    abstract class FrameSlotNode extends TestChildNode {
+        protected final FrameSlot slot;
+
+        public FrameSlotNode(FrameSlot slot) {
+            this.slot = slot;
+        }
+    }
+
+    class StringTestChildNode extends TestChildNode {
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            return "42";
+        }
+
+    }
+
+    class IntAssignLocal extends FrameSlotNode implements FrameSlotTypeListener {
+        @Child private TestChildNode value;
+
+        IntAssignLocal(FrameSlot slot, TestChildNode value) {
+            super(slot);
+            this.value = adoptChild(value);
+            slot.registerOneShotTypeListener(this);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            try {
+                frame.setInt(slot, value.executeInt(frame));
+            } catch (UnexpectedResultException e) {
+                slot.setType(Object.class);
+                frame.updateToLatestVersion();
+                frame.setObject(slot, e.getResult());
+            }
+            return null;
+        }
+
+        @Override
+        public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) {
+            if (changedSlot.getType() == Object.class) {
+                this.replace(new ObjectAssignLocal(changedSlot, value));
+            }
+        }
+    }
+
+    class ObjectAssignLocal extends FrameSlotNode {
+        @Child private TestChildNode value;
+
+        ObjectAssignLocal(FrameSlot slot, TestChildNode value) {
+            super(slot);
+            this.value = adoptChild(value);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            Object o = value.execute(frame);
+            frame.setObject(slot, o);
+            return null;
+        }
+    }
+
+    class IntReadLocal extends FrameSlotNode implements FrameSlotTypeListener {
+        IntReadLocal(FrameSlot slot) {
+            super(slot);
+            slot.registerOneShotTypeListener(this);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            return executeInt(frame);
+        }
+
+        @Override
+        int executeInt(VirtualFrame frame) {
+            return frame.getInt(slot);
+        }
+
+        @Override
+        public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) {
+            if (changedSlot.getType() == Object.class) {
+                this.replace(new ObjectReadLocal(changedSlot));
+            }
+        }
+    }
+
+    class ObjectReadLocal extends FrameSlotNode {
+        ObjectReadLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            return frame.getObject(slot);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Creating a Root Node</h3>
+ *
+ * <p>
+ * A Truffle root node is the entry point into a Truffle tree that represents a guest language method. It contains a
+ * {@link RootNode#execute(VirtualFrame)} method that can return a {@link java.lang.Object} value as the result of the
+ * guest language method invocation. This method must however never be called directly. Instead, the Truffle runtime
+ * must be used to create a {@link CallTarget} object from a root node using the
+ * {@link TruffleRuntime#createCallTarget(RootNode)} method. This call target object can then be executed using the
+ * {@link CallTarget#call()} method or one of its overloads.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ChildNodeTest}.
+ * </p>
+ */
+public class RootNodeTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestRootNode rootNode = new TestRootNode();
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return 42;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * <h3>Accessing the Truffle Runtime</h3>
+ *
+ * <p>
+ * The Truffle runtime can be accessed at any point in time globally using the static method
+ * {@link Truffle#getRuntime()}. This method is guaranteed to return a non-null Truffle runtime object with an
+ * identifying name. A Java Virtual Machine implementation can chose to replace the default implementation of the
+ * {@link TruffleRuntime} interface with its own implementation for providing improved performance.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.RootNodeTest}.
+ * </p>
+ */
+public class TruffleRuntimeTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        Assert.assertNotNull(runtime);
+        Assert.assertNotNull(runtime.getName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+/**
+ * <p>This package contains basic tests of the Truffle API and serves at the same
+ * time as an introduction to the Truffle API for language implementors. Every test gives an example on how to use the construct explained in the class description.</p>
+ *
+ * <p>
+ * Truffle is a language implementation framework. A guest language method is represented as a tree of executable nodes.
+ * The framework provides mechanisms for those trees to call each other. Additionally it contains dedicated data structures for storing data local to a tree invocation.
+ * </p>
+ *
+ * <p>
+ * This introduction to Truffle contains items in the following recommended order:
+ *
+ * <ul>
+ * <li>How to get access to the Truffle runtime? {@link com.oracle.truffle.api.test.TruffleRuntimeTest}</li>
+ * <li>How to create a root node? {@link com.oracle.truffle.api.test.RootNodeTest}</li>
+ * <li>How to create a child node and link it with its parent? {@link com.oracle.truffle.api.test.ChildNodeTest}</li>
+ * <li>How to create an array of child nodes? {@link com.oracle.truffle.api.test.ChildrenNodesTest}</li>
+ * <li>Why are final fields in node classes important? {@link com.oracle.truffle.api.test.FinalFieldTest}</li>
+ * <li>How to replace one node with another node and what for? {@link com.oracle.truffle.api.test.ReplaceTest}</li>
+ * <li>How to let one Truffle tree invoke another one? {@link com.oracle.truffle.api.test.CallTest}</li>
+ * <li>How to pass arguments when executing a tree? {@link com.oracle.truffle.api.test.ArgumentsTest}</li>
+ * <li>How to use frames and frame slots to store values local to an activation? {@link com.oracle.truffle.api.test.FrameTest}</li>
+ * <li>How to use type specialization and speculation for frame slots? {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}</li>
+ * <li>How to use type specialization and speculation for node return values? {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}</li>
+ * </ul>
+ *
+ * </p>
+ *
+ */
+package com.oracle.truffle.api.test;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Arguments.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+/**
+ * Base class for arguments passed to guest language methods via the
+ * {@link CallTarget#call(com.oracle.truffle.api.frame.PackedFrame, Arguments)} method. A guest language create a
+ * subclass with immutable fields representing the arguments passed to a guest language method. The {@link Arguments}
+ * object must be created immediately before a method call and it must not be stored in a field or cast to
+ * {@link java.lang.Object}.
+ */
+public class Arguments {
+
+    /**
+     * Constant that can be used as an argument to
+     * {@link CallTarget#call(com.oracle.truffle.api.frame.PackedFrame, Arguments)} in case no arguments should be
+     * supplied.
+     */
+    public static final Arguments EMPTY_ARGUMENTS = new Arguments();
+
+    /**
+     * Constructs an empty {@link Arguments} instance. Guest languages should create a subclass to specify their own arguments.
+     */
+    protected Arguments() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Represents the target of a call. Instances of this interface can be created using the
+ * {@link TruffleRuntime#createCallTarget(com.oracle.truffle.api.nodes.RootNode, FrameDescriptor)} method.
+ */
+public abstract class CallTarget {
+
+    /**
+     * Calls this target as a root method and without arguments.
+     * @return the return result of the call
+     */
+    public final Object call() {
+        return call(null, Arguments.EMPTY_ARGUMENTS);
+    }
+
+    /**
+     * Calls this target with a caller frame and no arguments.
+     * @param caller the caller frame
+     * @return the return result of the call
+     */
+    public final Object call(PackedFrame caller) {
+        return call(caller, Arguments.EMPTY_ARGUMENTS);
+    }
+
+    /**
+     * Calls this target as a root method passing arguments.
+     * @param arguments the arguments that should be passed to the callee
+     * @return the return result of the call
+     */
+    public final Object call(Arguments arguments) {
+        return call(null, arguments);
+    }
+
+    /**
+     * Calls this target passing a caller frame and arguments.
+     * @param caller the caller frame
+     * @param arguments the arguments that should be passed to the callee
+     * @return the return result of the call
+     */
+    public abstract Object call(PackedFrame caller, Arguments arguments);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+import com.oracle.truffle.api.impl.*;
+
+/**
+ * Class for obtaining the Truffle runtime singleton object of this virtual machine.
+ */
+public class Truffle {
+
+    private static TruffleRuntime runtime;
+
+    private static native TruffleRuntime initializeRuntime();
+
+    public static TruffleRuntime getRuntime() {
+        return runtime;
+    }
+
+    static {
+        try {
+            runtime = initializeRuntime();
+        } catch (UnsatisfiedLinkError e) {
+            runtime = new DefaultTruffleRuntime();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Interface representing a Truffle runtime object. The runtime is responsible for creating call targets and performing optimizations for them.
+ */
+public interface TruffleRuntime {
+    /**
+     * Name describing this runtime implementation for debugging purposes.
+     * @return the name as a String
+     */
+    String getName();
+
+    /**
+     * Creates a new call target for a given root node.
+     * @param rootNode the root node whose {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method represents the entry point
+     * @return the new call target object
+     */
+    CallTarget createCallTarget(RootNode rootNode);
+
+    /**
+     * Creates a new call target for a given root node and a given frame descriptor.
+     * @param rootNode the root node whose {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method represents the entry point
+     * @param frameDescriptor the descriptor used for creating a new frame at each invocation
+     * @return the new call target object
+     */
+    CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/DefaultTypeConversion.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Default type conversion semantics where a conversion is without changing any data.
+ */
+public final class DefaultTypeConversion implements TypeConversion {
+
+    private static DefaultTypeConversion instance = new DefaultTypeConversion();
+
+    public static TypeConversion getInstance() {
+        return instance;
+    }
+
+    private DefaultTypeConversion() {
+
+    }
+
+    @Override
+    public Class< ? > getTopType() {
+        return Object.class;
+    }
+
+    @Override
+    public Object convertTo(Class< ? > targetType, Object value) {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Represents a frame containing values of local variables of the guest language. Instances of this type must not be
+ * stored in a field or cast to {@link java.lang.Object}.
+ */
+public interface Frame {
+
+    /**
+     * @return the arguments used when calling this method
+     */
+    Arguments getArguments();
+
+    /**
+     * Read access to a local variable of type {@link Object}.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    Object getObject(FrameSlot slot);
+
+    /**
+     * Write access to a local variable of type {@link Object}.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setObject(FrameSlot slot, Object value);
+
+    /**
+     * Read access to a local variable of type boolean.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    boolean getBoolean(FrameSlot slot);
+
+    /**
+     * Write access to a local variable of type boolean.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setBoolean(FrameSlot slot, boolean value);
+
+    /**
+     * Read access to a local variable of type int.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    int getInt(FrameSlot slot);
+
+    /**
+     * Write access to a local variable of type int.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setInt(FrameSlot slot, int value);
+
+    /**
+     * Read access to a local variable of type long.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    long getLong(FrameSlot slot);
+
+    /**
+     * Write access to a local variable of type long.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setLong(FrameSlot slot, long value);
+
+    /**
+     * Read access to a local variable of type float.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    float getFloat(FrameSlot slot);
+
+    /**
+     * Write access to a local variable of type float.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setFloat(FrameSlot slot, float value);
+
+    /**
+     * Read access to a local variable of type double.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    double getDouble(FrameSlot slot);
+
+    /**
+     * Write access to a local variable of type double.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setDouble(FrameSlot slot, double value);
+
+    void updateToLatestVersion();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import java.util.*;
+
+/**
+ * Descriptor of the slots of frame objects. Multiple frame instances are associated with one such descriptor.
+ */
+public final class FrameDescriptor {
+
+    protected final TypeConversion typeConversion;
+    private final ArrayList<FrameSlotImpl> slots;
+    private FrameVersionImpl lastVersion;
+    private final HashMap<String, FrameSlotImpl> nameToSlotMap;
+
+    public FrameDescriptor() {
+        this(DefaultTypeConversion.getInstance());
+    }
+
+    public FrameDescriptor(TypeConversion typeConversion) {
+        this.typeConversion = typeConversion;
+        slots = new ArrayList<>();
+        nameToSlotMap = new HashMap<>();
+        lastVersion = new FrameVersionImpl();
+    }
+
+    public FrameSlot addFrameSlot(String name) {
+        return addFrameSlot(name, typeConversion.getTopType());
+    }
+
+    public FrameSlot addFrameSlot(String name, Class<?> type) {
+        assert !nameToSlotMap.containsKey(name);
+        FrameSlotImpl slot = new FrameSlotImpl(this, name, slots.size(), type);
+        slots.add(slot);
+        nameToSlotMap.put(name, slot);
+        return slot;
+    }
+
+    public FrameSlot findFrameSlot(String name) {
+        return nameToSlotMap.get(name);
+    }
+
+    public FrameSlot findOrAddFrameSlot(String name) {
+        FrameSlot result = findFrameSlot(name);
+        if (result != null) {
+            return result;
+        }
+        return addFrameSlot(name);
+    }
+
+    public FrameVersion getCurrentVersion() {
+        return lastVersion;
+    }
+
+    public int getSize() {
+        return slots.size();
+    }
+
+    public List< ? extends FrameSlot> getSlots() {
+        return Collections.unmodifiableList(slots);
+    }
+
+    protected void appendVersion(FrameVersionImpl newVersion) {
+        lastVersion.next = newVersion;
+        lastVersion = newVersion;
+    }
+}
+
+class FrameVersionImpl implements FrameVersion {
+
+    protected FrameVersionImpl next;
+
+    @Override
+    public final FrameVersion getNext() {
+        return next;
+    }
+}
+
+class TypeChangeFrameVersionImpl extends FrameVersionImpl implements FrameVersion.TypeChange {
+
+    private final FrameSlotImpl slot;
+    private final Class< ? > oldType;
+    private final Class< ? > newType;
+
+    protected TypeChangeFrameVersionImpl(FrameSlotImpl slot, Class< ? > oldType, Class< ? > newType) {
+        this.slot = slot;
+        this.oldType = oldType;
+        this.newType = newType;
+    }
+
+    @Override
+    public final void applyTransformation(Frame frame) {
+        Object value = slot.getValue(oldType, frame);
+        slot.setValue(newType, frame, value);
+    }
+}
+
+class FrameSlotImpl implements FrameSlot {
+
+    private final FrameDescriptor descriptor;
+    private final String name;
+    private final int index;
+    private Class< ? > type;
+    private ArrayList<FrameSlotTypeListener> listeners;
+
+    protected FrameSlotImpl(FrameDescriptor descriptor, String name, int index, Class< ? > type) {
+        this.descriptor = descriptor;
+        this.name = name;
+        this.index = index;
+        this.type = type;
+        assert type != null;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public Class< ? > getType() {
+        return type;
+    }
+
+    protected Object getValue(Class< ? > accessType, Frame frame) {
+        if (accessType == Integer.class) {
+            return frame.getInt(this);
+        } else if (accessType == Long.class) {
+            return frame.getLong(this);
+        } else if (accessType == Float.class) {
+            return frame.getFloat(this);
+        } else if (accessType == Double.class) {
+            return frame.getDouble(this);
+        } else {
+            return frame.getObject(this);
+        }
+    }
+
+    protected void setValue(Class< ? > accessType, Frame frame, Object value) {
+        Object newValue = descriptor.typeConversion.convertTo(accessType, value);
+        if (accessType == Integer.class) {
+            frame.setInt(this, (Integer) newValue);
+        } else if (accessType == Long.class) {
+            frame.setLong(this, (Long) newValue);
+        } else if (accessType == Float.class) {
+            frame.setFloat(this, (Float) newValue);
+        } else if (accessType == Double.class) {
+            frame.setDouble(this, (Double) newValue);
+        } else {
+            frame.setObject(this, newValue);
+        }
+    }
+
+    public void setType(final Class< ? > type) {
+        final Class< ? > oldType = this.type;
+        this.type = type;
+        ArrayList<FrameSlotTypeListener> oldListeners = this.listeners;
+        this.listeners = null;
+        if (oldListeners != null) {
+            for (FrameSlotTypeListener listener : oldListeners) {
+                listener.typeChanged(this, oldType);
+            }
+        }
+        descriptor.appendVersion(new TypeChangeFrameVersionImpl(this, oldType, type));
+    }
+
+    @Override
+    public String toString() {
+        return "[" + index + "," + name + "]";
+    }
+
+    @Override
+    public void registerOneShotTypeListener(FrameSlotTypeListener listener) {
+        if (listeners == null) {
+            listeners = new ArrayList<>();
+        }
+        listeners.add(listener);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * A slot in a frame that can store a value of a given type.
+ */
+public interface FrameSlot {
+    String getName();
+    int getIndex();
+    Class< ? > getType();
+    void setType(Class< ? > type);
+    void registerOneShotTypeListener(FrameSlotTypeListener listener);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeListener.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Listener for the event of a type change of a frame slot.
+ */
+public interface FrameSlotTypeListener {
+    void typeChanged(FrameSlot slot, Class< ? > oldType);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameVersion.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Represents a specific version of a frame.
+ */
+public interface FrameVersion {
+
+    FrameVersion getNext();
+
+    public interface Resize {
+
+        int getNewSize();
+    }
+
+    public interface TypeChange {
+
+        void applyTransformation(Frame frame);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Represents a materialized frame containing values of local variables of the guest language. It can be created using
+ * the {@link VirtualFrame#materialize()} method. Instances of this type are the only frame instances that may be stored
+ * in fields or cast to {@link java.lang.Object}. In contrast to a {@link VirtualFrame}, a {@link MaterializedFrame} can
+ * no longer be packed and it also does not provide access to the caller frame.
+ */
+public interface MaterializedFrame extends Frame {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Represents a native frame without any local variables. Instances of this type must not be stored in a field or cast
+ * to {@link java.lang.Object}.
+ */
+public class NativeFrame implements VirtualFrame, PackedFrame {
+
+    private PackedFrame caller;
+    private Arguments arguments;
+
+    public NativeFrame(PackedFrame caller, Arguments arguments) {
+        this.caller = caller;
+        this.arguments = arguments;
+    }
+
+    @Override
+    public Arguments getArguments() {
+        return arguments;
+    }
+
+    @Override
+    public Object getObject(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public void setObject(FrameSlot slot, Object value) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public boolean getBoolean(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public void setBoolean(FrameSlot slot, boolean value) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public int getInt(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public void setInt(FrameSlot slot, int value) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public long getLong(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public void setLong(FrameSlot slot, long value) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public float getFloat(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public void setFloat(FrameSlot slot, float value) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public double getDouble(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public void setDouble(FrameSlot slot, double value) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public PackedFrame pack() {
+        return this;
+    }
+
+    @Override
+    public PackedFrame getCaller() {
+        return caller;
+    }
+
+    @Override
+    public MaterializedFrame materialize() {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
+    public VirtualFrame unpack() {
+        return this;
+    }
+
+    @Override
+    public void updateToLatestVersion() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Represents a packed frame that represents a virtual frame. A packed frame instance can be retrieved with the
+ * {@link VirtualFrame#pack()} method. It can be converted back into a virtual frame using {@link PackedFrame#unpack()}.
+ * Instances of this type must not be stored in a field or cast to {@link java.lang.Object}.
+ */
+public interface PackedFrame {
+
+    /**
+     * Unpacks this frame and converts it back to a virtual frame.
+     * @return the virtual frame that was the content of this packed frame
+     */
+    VirtualFrame unpack();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/TypeConversion.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Interface for defining type conversions for frame slot values.
+ */
+public interface TypeConversion {
+    Class<?> getTopType();
+
+    Object convertTo(Class<?> targetType, Object value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Represents a frame containing values of local variables of the guest language. Instances of this type must not be
+ * stored in a field or cast to {@link java.lang.Object}. If this is necessary, the frame must be explicitly converted
+ * into a materialized frame using the {@link VirtualFrame#materialize()} method. Whenever fast access to the local
+ * variables of a frame is no longer necessary, a virtual frame should be converted into a packed frame using the
+ * {@link VirtualFrame#pack()} method.
+ */
+public interface VirtualFrame extends Frame {
+
+    /**
+     * Converts this virtual frame into a packed frame that has no longer direct access to the local variables. This
+     * packing is an important hint to the Truffle optimizer and therefore passing around a {@link PackedFrame} should
+     * be preferred over passing around a {@link VirtualFrame} when the probability that an unpacking will occur is low.
+     *
+     * @return the packed frame
+     */
+    PackedFrame pack();
+
+    /**
+     * Accesses the caller frame passed in via {@link CallTarget#call}. To get full access, it must be first unpacked
+     * using {@link PackedFrame#unpack()}.
+     *
+     * @return the caller frame or null if this was a root method call
+     */
+    PackedFrame getCaller();
+
+    /**
+     * Materializes this frame, which allows it to be stored in a field or cast to {@link java.lang.Object}. The frame
+     * however looses the ability to be packed or to access the caller frame.
+     *
+     * @return the new materialized frame
+     */
+    MaterializedFrame materialize();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+final class DefaultCallTarget extends CallTarget {
+
+    protected final RootNode rootNode;
+    protected final FrameDescriptor frameDescriptor;
+
+    DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) {
+        this.rootNode = function;
+        this.frameDescriptor = frameDescriptor;
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultCallTarget " + rootNode;
+    }
+
+    @Override
+    public Object call(PackedFrame caller, Arguments args) {
+        VirtualFrame frame = new DefaultVirtualFrame(frameDescriptor, caller, args);
+        return rootNode.execute(frame);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+final class DefaultMaterializedFrame implements MaterializedFrame {
+    private final DefaultVirtualFrame wrapped;
+
+    protected DefaultMaterializedFrame(DefaultVirtualFrame wrapped) {
+        this.wrapped = wrapped;
+    }
+
+    @Override
+    public Arguments getArguments() {
+        return wrapped.getArguments();
+    }
+
+    @Override
+    public Object getObject(FrameSlot slot) {
+        return wrapped.getObject(slot);
+    }
+
+    @Override
+    public void setObject(FrameSlot slot, Object value) {
+        wrapped.setObject(slot, value);
+    }
+
+    @Override
+    public boolean getBoolean(FrameSlot slot) {
+        return wrapped.getBoolean(slot);
+    }
+
+    @Override
+    public void setBoolean(FrameSlot slot, boolean value) {
+        wrapped.setBoolean(slot, value);
+    }
+
+    @Override
+    public int getInt(FrameSlot slot) {
+        return wrapped.getInt(slot);
+    }
+
+    @Override
+    public void setInt(FrameSlot slot, int value) {
+        wrapped.setInt(slot, value);
+    }
+
+    @Override
+    public long getLong(FrameSlot slot) {
+        return wrapped.getLong(slot);
+    }
+
+    @Override
+    public void setLong(FrameSlot slot, long value) {
+        wrapped.setLong(slot, value);
+    }
+
+    @Override
+    public float getFloat(FrameSlot slot) {
+        return wrapped.getFloat(slot);
+    }
+
+    @Override
+    public void setFloat(FrameSlot slot, float value) {
+        wrapped.setFloat(slot, value);
+    }
+
+    @Override
+    public double getDouble(FrameSlot slot) {
+        return wrapped.getDouble(slot);
+    }
+
+    @Override
+    public void setDouble(FrameSlot slot, double value) {
+        wrapped.setDouble(slot, value);
+    }
+
+    @Override
+    public void updateToLatestVersion() {
+        wrapped.updateToLatestVersion();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultPackedFrame.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.frame.*;
+
+final class DefaultPackedFrame implements PackedFrame {
+    private final DefaultVirtualFrame wrapped;
+
+    protected DefaultPackedFrame(DefaultVirtualFrame wrapped) {
+        this.wrapped = wrapped;
+    }
+
+    @Override
+    public VirtualFrame unpack() {
+        return wrapped;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Default implementation of the Truffle runtime if the virtual machine does not provide a better performing alternative.
+ */
+public final class DefaultTruffleRuntime implements TruffleRuntime {
+
+    @Override
+    public String getName() {
+        return "Default Truffle Runtime";
+    }
+
+    @Override
+    public CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor) {
+        return new DefaultCallTarget(rootNode, frameDescriptor);
+    }
+
+    @Override
+    public CallTarget createCallTarget(RootNode rootNode) {
+        return createCallTarget(rootNode, new FrameDescriptor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+final class DefaultVirtualFrame implements VirtualFrame {
+
+    private static final Object UNDEFINED_OBJECT = null;
+    private static final Boolean UNDEFINED_BOOLEAN = false;
+    private static final Integer UNDEFINED_INTEGER = 0;
+    private static final Float UNDEFINED_FLOAT = 0.0f;
+    private static final Long UNDEFINED_LONG = 0L;
+    private static final Double UNDEFINED_DOUBLE = 0.0d;
+
+    private final FrameDescriptor descriptor;
+    private final PackedFrame caller;
+    private final Arguments arguments;
+    private FrameVersion currentVersion;
+    protected Object[] locals;
+    protected Class[] tags;
+
+    DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) {
+        this.descriptor = descriptor;
+        this.caller = caller;
+        this.arguments = arguments;
+        this.currentVersion = descriptor.getCurrentVersion();
+        this.locals = new Object[descriptor.getSize()];
+        // The tags are only needed for assertion checking, so initialize the field only when assertions are enabled
+        assert (this.tags = new Class[descriptor.getSize()]) != null;
+    }
+
+    @Override
+    public Arguments getArguments() {
+        return arguments;
+    }
+
+    @Override
+    public PackedFrame getCaller() {
+        return caller;
+    }
+
+    @Override
+    public PackedFrame pack() {
+        return new DefaultPackedFrame(this);
+    }
+
+    @Override
+    public MaterializedFrame materialize() {
+        return new DefaultMaterializedFrame(this);
+    }
+
+    @Override
+    public Object getObject(FrameSlot slot) {
+        return get(slot, Object.class, UNDEFINED_OBJECT);
+    }
+
+    @Override
+    public void setObject(FrameSlot slot, Object value) {
+        set(slot, Object.class, value);
+    }
+
+    @Override
+    public boolean getBoolean(FrameSlot slot) {
+        return (Boolean) get(slot, Float.class, UNDEFINED_BOOLEAN);
+    }
+
+    @Override
+    public void setBoolean(FrameSlot slot, boolean value) {
+        set(slot, Float.class, value);
+    }
+
+    @Override
+    public int getInt(FrameSlot slot) {
+        return (Integer) get(slot, Integer.class, UNDEFINED_INTEGER);
+    }
+
+    @Override
+    public void setInt(FrameSlot slot, int value) {
+        set(slot, Integer.class, value);
+    }
+
+    @Override
+    public long getLong(FrameSlot slot) {
+        return (Long) get(slot, Long.class, UNDEFINED_LONG);
+    }
+
+    @Override
+    public void setLong(FrameSlot slot, long value) {
+        set(slot, Long.class, value);
+    }
+
+    @Override
+    public float getFloat(FrameSlot slot) {
+        return (Float) get(slot, Float.class, UNDEFINED_FLOAT);
+    }
+
+    @Override
+    public void setFloat(FrameSlot slot, float value) {
+        set(slot, Float.class, value);
+    }
+
+    @Override
+    public double getDouble(FrameSlot slot) {
+        return (Double) get(slot, Double.class, UNDEFINED_DOUBLE);
+    }
+
+    @Override
+    public void setDouble(FrameSlot slot, double value) {
+        set(slot, Double.class, value);
+    }
+
+    private Object get(FrameSlot slot, Class< ? > accessType, Object defaultValue) {
+        Object value = locals[slot.getIndex()];
+        assert verifyGet(slot, accessType, value);
+        if (value == null) {
+            return defaultValue;
+        } else {
+            return value;
+        }
+    }
+
+    private boolean verifyGet(FrameSlot slot, Class< ? > accessType, Object value) {
+        assert descriptor.getSlots().get(slot.getIndex()) == slot;
+        Class< ? > tag = tags[slot.getIndex()];
+        if (value == null) {
+            assert tag == null || tag == Object.class;
+        } else {
+            assert tag == accessType : "Local variable " + slot + " was written with set" + tag.getSimpleName() + ", but is read with get" + accessType.getSimpleName();
+        }
+        return true;
+    }
+
+    private void set(FrameSlot slot, Class< ? > accessType, Object value) {
+        assert verifySet(slot, accessType, value);
+        locals[slot.getIndex()] = value;
+    }
+
+    private boolean verifySet(FrameSlot slot, Class< ? > accessType, Object value) {
+        assert descriptor.getSlots().get(slot.getIndex()) == slot;
+        tags[slot.getIndex()] = accessType;
+        assert accessType.isAssignableFrom(slot.getType()) : "Local variable " + slot + ": " + accessType + " is not assignable from " + slot.getType();
+        if (value == null) {
+            assert accessType == Object.class;
+        } else {
+            assert slot.getType().isAssignableFrom(value.getClass()) : "Local variable " + slot + ": " + slot.getType() + " is not assignable from " + value.getClass();
+        }
+        return true;
+    }
+
+    @Override
+    public void updateToLatestVersion() {
+        if (currentVersion.getNext() != null) {
+            doUpdateToLatestVersion();
+        }
+    }
+
+    private void doUpdateToLatestVersion() {
+        FrameVersion version = currentVersion;
+        while (version.getNext() != null) {
+            version = version.getNext();
+            if (version instanceof FrameVersion.TypeChange) {
+                ((FrameVersion.TypeChange) version).applyTransformation(this);
+            } else if (version instanceof FrameVersion.Resize) {
+                int newSize = ((FrameVersion.Resize) version).getNewSize();
+                locals = Arrays.copyOf(locals, newSize);
+            }
+        }
+        currentVersion = version;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/ExactMath.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.intrinsics;
+
+/**
+ * This class contains methods that will be part of java.lang.Math starting with JDK 8. Until JDK 8 is release, we
+ * duplicate them here because they are generally useful for dynamic language implementations.
+ */
+public class ExactMath {
+
+    public static int addExact(int x, int y) {
+        int r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    public static long addExact(long x, long y) {
+        long r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    public static int subtractExact(int x, int y) {
+        int r = x - y;
+        // HD 2-12 Overflow iff the arguments have different signs and
+        // the sign of the result is different than the sign of x
+        if (((x ^ y) & (x ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    public static long subtractExact(long x, long y) {
+        long r = x - y;
+        // HD 2-12 Overflow iff the arguments have different signs and
+        // the sign of the result is different than the sign of x
+        if (((x ^ y) & (x ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    public static int multiplyExact(int x, int y) {
+        long r = (long) x * (long) y;
+        if ((int) r != r) {
+            throw new ArithmeticException("long overflow");
+        }
+        return (int) r;
+    }
+
+    public static long multiplyExact(long x, long y) {
+        long r = x * y;
+        long ax = Math.abs(x);
+        long ay = Math.abs(y);
+        if (((ax | ay) >>> 31 != 0)) {
+            // Some bits greater than 2^31 that might cause overflow
+            // Check the result using the divide operator
+            // and check for the special case of Long.MIN_VALUE * -1
+            if (((y != 0) && (r / y != x)) || (x == Long.MIN_VALUE && y == -1)) {
+                throw new ArithmeticException("long overflow");
+            }
+        }
+        return r;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/TruffleIntrinsics.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.intrinsics;
+
+/**
+ * Predefined Truffle intrinsics that allow direct influence of the generated machine code.
+ */
+public final class TruffleIntrinsics {
+
+    /**
+     * Specifies that the compiler should put a deoptimization point at this position that will continue execution in the interpreter.
+     * Should be used to cut off cold paths that should not be part of the compiled machine code.
+     */
+    public static void deoptimize() {
+    }
+
+    /**
+     * Checks whether the Thread has been interrupted in the interpreter in order to avoid endless loops. The compiled code may choose a more efficient implementation.
+     */
+    public static void checkThreadInterrupted() {
+        if (Thread.currentThread().isInterrupted()) {
+            throw new RuntimeException("Timeout");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.lang.annotation.*;
+
+/**
+ * Specifies for a method that the loops with constant number of invocations should be fully unrolled.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface ExplodeLoop {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.*;
+
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+
+import org.w3c.dom.*;
+
+/**
+ * Utility class for creating output for the ideal graph visualizer.
+ */
+public class GraphPrintVisitor {
+
+    public static final String GraphVisualizerAddress = "127.0.0.1";
+    public static final int GraphVisualizerPort = 4444;
+
+    private Document dom;
+    private Map<Object, Element> nodeMap;
+    private List<Element> edgeList;
+    private Map<Object, Element> prevNodeMap;
+    private int id;
+    private Element graphDocument;
+    private Element groupElement;
+    private Element graphElement;
+    private Element nodesElement;
+    private Element edgesElement;
+
+    public GraphPrintVisitor() {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        try {
+            DocumentBuilder db = dbf.newDocumentBuilder();
+
+            dom = db.newDocument();
+        } catch (ParserConfigurationException ex) {
+            System.out.println("Error while trying to instantiate DocumentBuilder " + ex);
+        }
+
+        graphDocument = dom.createElement("graphDocument");
+        dom.appendChild(graphDocument);
+    }
+
+    public GraphPrintVisitor beginGroup(String groupName) {
+        groupElement = dom.createElement("group");
+        graphDocument.appendChild(groupElement);
+        Element properties = dom.createElement("properties");
+        groupElement.appendChild(properties);
+
+        if (!groupName.isEmpty()) {
+            // set group name
+            Element propName = dom.createElement("p");
+            propName.setAttribute("name", "name");
+            propName.setTextContent(groupName);
+            properties.appendChild(propName);
+        }
+
+        // forget old nodes
+        nodeMap = prevNodeMap = null;
+        edgeList = null;
+
+        return this;
+    }
+
+    public GraphPrintVisitor beginGraph(String graphName) {
+        if (null == groupElement) {
+            beginGroup("");
+        } else if (null != prevNodeMap) {
+            // TODO: difference (create removeNode,removeEdge elements)
+        }
+
+        graphElement = dom.createElement("graph");
+        groupElement.appendChild(graphElement);
+        Element properties = dom.createElement("properties");
+        graphElement.appendChild(properties);
+        nodesElement = dom.createElement("nodes");
+        graphElement.appendChild(nodesElement);
+        edgesElement = dom.createElement("edges");
+        graphElement.appendChild(edgesElement);
+
+        // set graph name
+        Element propName = dom.createElement("p");
+        propName.setAttribute("name", "name");
+        propName.setTextContent(graphName);
+        properties.appendChild(propName);
+
+        // save old nodes
+        prevNodeMap = nodeMap;
+        nodeMap = new HashMap<>();
+        edgeList = new ArrayList<>();
+
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        if (null != dom) {
+            try {
+                Transformer tr = TransformerFactory.newInstance().newTransformer();
+                tr.setOutputProperty(OutputKeys.INDENT, "yes");
+                tr.setOutputProperty(OutputKeys.METHOD, "xml");
+                tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+
+                StringWriter strWriter = new StringWriter();
+                tr.transform(new DOMSource(dom), new StreamResult(strWriter));
+                return strWriter.toString();
+            } catch (TransformerException e) {
+                e.printStackTrace();
+            }
+        }
+        return "";
+    }
+
+    public void printToFile(File f) {
+        try {
+            Transformer tr = TransformerFactory.newInstance().newTransformer();
+            tr.setOutputProperty(OutputKeys.INDENT, "yes");
+            tr.setOutputProperty(OutputKeys.METHOD, "xml");
+            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+
+            tr.transform(new DOMSource(dom), new StreamResult(new FileOutputStream(f)));
+        } catch (TransformerException | FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void printToSysout() {
+        try {
+            Transformer tr = TransformerFactory.newInstance().newTransformer();
+            tr.setOutputProperty(OutputKeys.INDENT, "yes");
+            tr.setOutputProperty(OutputKeys.METHOD, "xml");
+            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+
+            tr.transform(new DOMSource(dom), new StreamResult(System.out));
+        } catch (TransformerException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void printToNetwork() {
+        try {
+            Transformer tr = TransformerFactory.newInstance().newTransformer();
+            tr.setOutputProperty(OutputKeys.METHOD, "xml");
+
+            Socket socket = new Socket(GraphVisualizerAddress, GraphVisualizerPort);
+            BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000);
+            tr.transform(new DOMSource(dom), new StreamResult(stream));
+        } catch (TransformerException | IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private String nextId() {
+        return String.valueOf(id++);
+    }
+
+    private String oldOrNextId(Object node) {
+        if (null != prevNodeMap && prevNodeMap.containsKey(node)) {
+            Element nodeElem = prevNodeMap.get(node);
+            return nodeElem.getAttribute("id");
+        } else {
+            return nextId();
+        }
+    }
+
+    protected Element getElementByObject(Object op) {
+        return nodeMap.get(op);
+    }
+
+    protected void createElementForNode(Object node) {
+        boolean exists = nodeMap.containsKey(node);
+        if (!exists || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) {
+            Element nodeElem = dom.createElement("node");
+            nodeElem.setAttribute("id", !exists ? oldOrNextId(node) : nextId());
+            nodeMap.put(node, nodeElem);
+            Element properties = dom.createElement("properties");
+            nodeElem.appendChild(properties);
+            nodesElement.appendChild(nodeElem);
+
+            setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", ""));
+            NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class);
+            if (nodeInfo != null && !nodeInfo.shortName().isEmpty()) {
+                setNodeProperty(node, "shortName", nodeInfo.shortName());
+            }
+            setNodeProperty(node, "nodeType", (Node.class.isAssignableFrom(node.getClass()) ? Node.class.getSimpleName() : "other"));
+            setNodeProperty(node, "nodeClass", node.getClass().getSimpleName());
+            copyDebugProperties(node); // TODO: may overwrite property "name"? (currently allowed)
+            readNodeProperties(node);
+        }
+    }
+
+    private Element getPropertyElement(Object node, String propertyName) {
+        Element nodeElem = getElementByObject(node);
+        Element propertiesElem = (Element) nodeElem.getElementsByTagName("properties").item(0);
+        if (propertiesElem == null) {
+            return null;
+        }
+
+        NodeList propList = propertiesElem.getElementsByTagName("p");
+        for (int i = 0; i < propList.getLength(); i++) {
+            Element p = (Element) propList.item(i);
+            if (propertyName.equals(p.getAttribute("name"))) {
+                return p;
+            }
+        }
+        return null;
+    }
+
+    protected void setNodeProperty(Object node, String propertyName, Object value) {
+        Element nodeElem = getElementByObject(node);
+        Element propElem = getPropertyElement(node, propertyName); // if property exists, replace its value
+        if (null == propElem) { // if property doesn't exist, create one
+            propElem = dom.createElement("p");
+            propElem.setAttribute("name", propertyName);
+            nodeElem.getElementsByTagName("properties").item(0).appendChild(propElem);
+        }
+        propElem.setTextContent(String.valueOf(value));
+    }
+
+    private void copyDebugProperties(Object node) {
+        if (node instanceof Node) {
+            Map<String, Object> debugProperties = ((Node) node).getDebugProperties();
+            for (Map.Entry<String, Object> property : debugProperties.entrySet()) {
+                setNodeProperty(node, property.getKey(), property.getValue());
+            }
+        }
+    }
+
+    private void readNodeProperties(Object node) {
+        Field[] fields = NodeUtil.getAllFields(node.getClass());
+        for (Field field : fields) {
+            if (Modifier.isStatic(field.getModifiers())) {
+                continue;
+            }
+            if (Node.class.isAssignableFrom(field.getType()) || (field.getType().getComponentType() != null && Node.class.isAssignableFrom(field.getType()))) {
+                continue;
+            }
+            String key = field.getName();
+            if (field.getAnnotation(HiddenField.class) == null && getPropertyElement(node, key) == null) {
+                try {
+                    field.setAccessible(true);
+                    Object value = field.get(node);
+                    setNodeProperty(node, key, value);
+                } catch (IllegalArgumentException | IllegalAccessException e) {
+                    assert false : e;
+                }
+            }
+        }
+    }
+
+    protected void connectNodes(Object a, Object b) {
+        if (nodeMap.get(a) == null || nodeMap.get(b) == null) {
+            return;
+        }
+
+        String fromId = nodeMap.get(a).getAttribute("id");
+        String toId = nodeMap.get(b).getAttribute("id");
+
+        // count existing to-edges
+        int count = 0;
+        for (Element e : edgeList) {
+            if (e.getAttribute("to").equals(toId)) {
+                ++count;
+            }
+        }
+
+        Element edgeElem = dom.createElement("edge");
+        edgeElem.setAttribute("from", fromId);
+        edgeElem.setAttribute("to", toId);
+        edgeElem.setAttribute("index", String.valueOf(count));
+        edgesElement.appendChild(edgeElem);
+        edgeList.add(edgeElem);
+    }
+
+    public GraphPrintVisitor visit(Object node) {
+        if (null == graphElement) {
+            beginGraph("truffle tree");
+        }
+
+        // if node is visited once again, skip
+        if (getElementByObject(node) == null || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) {
+            visitAny(node);
+        }
+
+        return this;
+    }
+
+    private void visitAny(Object node) {
+        // respect node's custom handler
+        if (NodeUtil.findAnnotation(node.getClass(), NullGraphPrintHandler.class) != null) {
+            return;
+        }
+        if (NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) {
+            Class<? extends GraphPrintHandler> gpHandlerClass = NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler();
+            try {
+                GraphPrintHandler gpHandler = gpHandlerClass.newInstance();
+                gpHandler.visit(node, new GraphPrintAdapter());
+            } catch (InstantiationException e) {
+                assert false;
+            } catch (IllegalAccessException e) {
+                assert false;
+            }
+            return;
+        }
+
+        // default handler
+        createElementForNode(node);
+
+        List<Object> children = NodeUtil.findNodeChildren(node);
+        for (Object child : children) {
+            if (child == null) {
+                continue;
+            } else if (child instanceof Node) {
+                visit(child);
+            } else {
+                continue;
+            }
+            connectNodes(node, child);
+        }
+    }
+
+    public class GraphPrintAdapter {
+        public void createElementForNode(Object node) {
+            GraphPrintVisitor.this.createElementForNode(node);
+        }
+        public void visit(Object node) {
+            GraphPrintVisitor.this.visit(node);
+        }
+        public void connectNodes(Object node, Object child) {
+            GraphPrintVisitor.this.connectNodes(node, child);
+        }
+        public void setNodeProperty(Object node, String propertyName, Object value) {
+            GraphPrintVisitor.this.setNodeProperty(node, propertyName, value);
+        }
+    }
+
+    public interface GraphPrintHandler {
+        void visit(Object node, GraphPrintAdapter gPrinter);
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE)
+    public @interface CustomGraphPrintHandler {
+        Class<? extends GraphPrintHandler> handler();
+    }
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE)
+    public @interface NullGraphPrintHandler {
+    }
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE)
+    public @interface GraphDuplicate {
+    }
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public @interface HiddenField {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+/**
+ * Abstract base class for all Truffle nodes.
+ */
+public abstract class Node implements Cloneable {
+
+    /**
+     * Utility constant representing an empty node array.
+     */
+    public static final Node[] EMPTY_ARRAY = new Node[0];
+
+    private Node parent;
+
+    /**
+     * Marks array fields that are children of this node.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    public @interface Children {
+    }
+
+    /**
+     * Marks fields that represent child nodes of this node.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    public @interface Child {
+    }
+
+    /**
+     * Method that updates the link to the parent in the array of specified new child nodes to this node.
+     *
+     * @param newChildren the array of new children whose parent should be updated
+     * @return the array of new children
+     */
+    protected final <T extends Node> T[] adoptChildren(T[] newChildren) {
+        if (newChildren != null) {
+            for (T n : newChildren) {
+                adoptChild(n);
+            }
+        }
+        return newChildren;
+    }
+
+    /**
+     * Method that updates the link to the parent in the specified new child node to this node.
+     *
+     * @param newChild the new child whose parent should be updated
+     * @return the new child
+     */
+    protected final <T extends Node> T adoptChild(T newChild) {
+        if (newChild != null) {
+            ((Node) newChild).parent = this;
+        }
+        return newChild;
+    }
+
+    /**
+     * Returns properties of this node interesting for debugging and can be overwritten by subclasses to add their own
+     * custom properties.
+     *
+     * @return the properties as a key/value hash map
+     */
+    public Map<String, Object> getDebugProperties() {
+        Map<String, Object> properties = new HashMap<>();
+        return properties;
+    }
+
+    /**
+     * The current parent node of this node.
+     *
+     * @return the parent node
+     */
+    public final Node getParent() {
+        return parent;
+    }
+
+    /**
+     * Replaces one child of this node with another node.
+     *
+     * @param oldChild the old child
+     * @param newChild the new child that should replace the old child
+     * @return the new child
+     */
+    public final <T extends Node> T replaceChild(T oldChild, T newChild) {
+        NodeUtil.replaceChild(this, oldChild, newChild);
+        adoptChild(newChild);
+        return newChild;
+    }
+
+    /**
+     * Replaces this node with another node.
+     *
+     * @param newNode the new node that is the replacement
+     * @param reason a description of the reason for the replacement
+     * @return the new node
+     */
+    @SuppressWarnings({"unchecked"})
+    public <T extends Node> T replace(T newNode, String reason) {
+        assert this.getParent() != null;
+        return (T) this.getParent().replaceChild(this, newNode);
+    }
+
+    /**
+     * Replaces this node with another node.
+     *
+     * @param newNode the new node that is the replacement
+     * @return the new node
+     */
+    public <T extends Node> T replace(T newNode) {
+        return replace(newNode, "");
+    }
+
+    /**
+     * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all child nodes.
+     *
+     * @param nodeVisitor the visitor
+     */
+    public final void accept(NodeVisitor nodeVisitor) {
+        if (nodeVisitor.visit(this)) {
+            for (Node child : this.getChildren()) {
+                if (child != null) {
+                    child.accept(nodeVisitor);
+                }
+            }
+        }
+    }
+
+    /**
+     * Iterator over the children of this node.
+     *
+     * @return the iterator
+     */
+    public final Iterable<Node> getChildren() {
+        final Node node = this;
+        return new Iterable<Node>() {
+
+            public Iterator<Node> iterator() {
+                return new NodeUtil.NodeIterator(node);
+            }
+        };
+    }
+
+    /**
+     * Creates a shallow copy of this node.
+     *
+     * @return the new copy
+     */
+    public Node copy() {
+        try {
+            return (Node) super.clone();
+        } catch (CloneNotSupportedException e) {
+            return null;
+        }
+    }
+
+    /**
+     * This method must never be called. It enforces that {@link Object#clone} is not directly called by subclasses.
+     * Use the {@link #copy()} method instead.
+     */
+    @Override
+    @Deprecated
+    protected final Object clone() throws CloneNotSupportedException {
+        throw new IllegalStateException("This method should never be called, use the copy method instead!");
+    }
+
+    /**
+     * Converts this node to a textual representation useful for debugging.
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(getClass().getSimpleName());
+        Map<String, Object> properties = getDebugProperties();
+        boolean hasProperties = false;
+        for (Map.Entry<String, Object> entry : properties.entrySet()) {
+            sb.append(hasProperties ? "," : "<");
+            hasProperties = true;
+            sb.append(entry.getKey()).append("=").append(entry.getValue());
+        }
+        if (hasProperties) {
+            sb.append(">");
+        }
+        sb.append("@").append(Integer.toHexString(hashCode()));
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation for providing additional information on nodes.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface NodeInfo {
+
+    /**
+     * Short name representing the node that can be used for debugging.
+     * @return the short name
+     */
+    String shortName() default "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,702 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import sun.misc.*;
+
+/**
+ * Utility class that manages the special access methods for node instances.
+ */
+public class NodeUtil {
+
+    public static final class NodeClass {
+
+        private final Class parentClass;
+        private final long[] nodeFieldOffsets;
+        private final Class[] nodeFieldClasses;
+        private final long[] nodeArrayFieldOffsets;
+        private final Class[] nodeArrayFieldClasses;
+        private final long parentOffset;
+        private final long[] nodeDataFieldOffsets;
+        private final Class< ? >[] nodeDataFieldClasses;
+
+        private static final Map<Class< ? >, NodeClass> nodeClasses = new IdentityHashMap<>();
+
+        public static NodeClass get(Class< ? > clazz) {
+            NodeClass nodeClass = nodeClasses.get(clazz);
+            if (nodeClass == null) {
+                nodeClass = new NodeClass(clazz);
+                nodeClasses.put(clazz, nodeClass);
+            }
+            return nodeClass;
+        }
+
+        private NodeClass(Class< ? > clazz) {
+            // scan object fields
+            Class< ? > parentClassTmp = null;
+            List<Long> nodeFieldOffsetsList = new ArrayList<>();
+            List<Class< ? >> nodeFieldClassesList = new ArrayList<>();
+            List<Long> nodeArrayFieldOffsetsList = new ArrayList<>();
+            List<Class< ? >> nodeArrayFieldClassesList = new ArrayList<>();
+            List<Long> nodeDataFieldOffsetList = new ArrayList<>();
+            List<Class< ? >> nodeDataFieldClassList = new ArrayList<>();
+            Field[] fields = getAllFields(clazz);
+            long parentOffsetTemp = -1;
+            for (Field field : fields) {
+                if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
+                    continue;
+                }
+
+                // Node fields
+                if (Node.class.isAssignableFrom(field.getType())) {
+                    if (!field.getName().equals("parent")) {
+                        nodeFieldOffsetsList.add(unsafe.objectFieldOffset(field));
+                        nodeFieldClassesList.add(field.getType());
+                    } else {
+                        parentOffsetTemp = unsafe.objectFieldOffset(field);
+                        parentClassTmp = field.getType();
+                    }
+                } else if (field.getType().getComponentType() != null && Node.class.isAssignableFrom(field.getType().getComponentType())) {
+                    nodeArrayFieldOffsetsList.add(unsafe.objectFieldOffset(field));
+                    nodeArrayFieldClassesList.add(field.getType());
+                } else {
+                    nodeDataFieldOffsetList.add(unsafe.objectFieldOffset(field));
+                    nodeDataFieldClassList.add(field.getType());
+                }
+            }
+            this.parentClass = parentClassTmp;
+            this.nodeFieldOffsets = toLongArray(nodeFieldOffsetsList);
+            this.nodeFieldClasses = nodeFieldClassesList.toArray(new Class[nodeFieldClassesList.size()]);
+            this.nodeArrayFieldOffsets = toLongArray(nodeArrayFieldOffsetsList);
+            this.nodeArrayFieldClasses = nodeArrayFieldClassesList.toArray(new Class[nodeArrayFieldClassesList.size()]);
+            this.nodeDataFieldOffsets = toLongArray(nodeDataFieldOffsetList);
+            this.nodeDataFieldClasses = nodeDataFieldClassList.toArray(new Class< ? >[nodeDataFieldClassList.size()]);
+
+            this.parentOffset = parentOffsetTemp;
+        }
+    }
+
+    public static class NodeIterator implements Iterator<Node> {
+
+        private final Node node;
+        private final NodeClass nodeClass;
+        private final int childrenCount;
+        private int index;
+
+        public NodeIterator(Node node) {
+            this(node, 0);
+        }
+
+        public NodeIterator(Node node, int index) {
+            this.node = node;
+            this.index = index;
+            this.nodeClass = NodeClass.get(node.getClass());
+            this.childrenCount = childrenCount();
+        }
+
+        private int childrenCount() {
+            int nodeCount = nodeClass.nodeFieldOffsets.length;
+            for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) {
+                Node[] children = ((Node[]) unsafe.getObject(node, fieldOffset));
+                if (children != null) {
+                    nodeCount += children.length;
+                }
+            }
+            return nodeCount;
+        }
+
+        private Node nodeAt(int idx) {
+            int nodeCount = nodeClass.nodeFieldOffsets.length;
+            if (idx < nodeCount) {
+                return (Node) unsafe.getObject(node, nodeClass.nodeFieldOffsets[idx]);
+            } else {
+                for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) {
+                    Node[] nodeArray = (Node[]) unsafe.getObject(node, fieldOffset);
+                    if (idx < nodeCount + nodeArray.length) {
+                        return nodeArray[idx - nodeCount];
+                    }
+                    nodeCount += nodeArray.length;
+                }
+            }
+            return null;
+        }
+
+        private void forward() {
+            if (index < childrenCount) {
+                index++;
+            }
+        }
+
+        @Override
+        public boolean hasNext() {
+            return index < childrenCount;
+        }
+
+        @Override
+        public Node next() {
+            try {
+                return nodeAt(index);
+            } finally {
+                forward();
+            }
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private static long[] toLongArray(List<Long> list) {
+        long[] array = new long[list.size()];
+        for (int i = 0; i < list.size(); i++) {
+            array[i] = list.get(i);
+        }
+        return array;
+    }
+
+    private static final Unsafe unsafe = getUnsafe();
+
+    private static Unsafe getUnsafe() {
+        try {
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends Node> T cloneNode(T orig) {
+        Class< ? extends Node> clazz = orig.getClass();
+        NodeClass nodeClass = NodeClass.get(clazz);
+        Node clone = orig.copy();
+        if (clone == null) {
+            return null;
+        }
+
+        unsafe.putObject(clone, nodeClass.parentOffset, null);
+
+        for (long fieldOffset : nodeClass.nodeFieldOffsets) {
+            Node child = (Node) unsafe.getObject(orig, fieldOffset);
+            if (child != null) {
+                Node clonedChild = cloneNode(child);
+                if (clonedChild == null) {
+                    return null;
+                }
+
+                unsafe.putObject(clonedChild, nodeClass.parentOffset, clone);
+                unsafe.putObject(clone, fieldOffset, clonedChild);
+            }
+        }
+        for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) {
+            Node[] children = (Node[]) unsafe.getObject(orig, fieldOffset);
+            if (children != null) {
+                Node[] clonedChildren = new Node[children.length];
+                for (int i = 0; i < children.length; i++) {
+                    Node clonedChild = cloneNode(children[i]);
+                    if (clonedChild == null) {
+                        return null;
+                    }
+
+                    clonedChildren[i] = clonedChild;
+                    unsafe.putObject(clonedChild, nodeClass.parentOffset, clone);
+                }
+                unsafe.putObject(clone, fieldOffset, clonedChildren);
+            }
+        }
+        return (T) clone;
+    }
+
+    public static List<Object> findNodeChildren(Object node) {
+        List<Object> nodes = new ArrayList<>();
+        NodeClass nodeClass = NodeClass.get(node.getClass());
+
+        for (long fieldOffset : nodeClass.nodeFieldOffsets) {
+            Object child = unsafe.getObject(node, fieldOffset);
+            if (child != null) {
+                nodes.add(child);
+            }
+        }
+        for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) {
+            Object[] children = (Object[]) unsafe.getObject(node, fieldOffset);
+            if (children != null) {
+                nodes.addAll(Arrays.asList(children));
+            }
+        }
+
+        return nodes;
+    }
+
+    public static void replaceChild(Node parent, Node oldChild, Node newChild) {
+        NodeClass nodeClass = NodeClass.get(parent.getClass());
+
+        for (long fieldOffset : nodeClass.nodeFieldOffsets) {
+            if (unsafe.getObject(parent, fieldOffset) == oldChild) {
+                unsafe.putObject(parent, fieldOffset, newChild);
+            }
+        }
+        for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) {
+            Node[] array = (Node[]) unsafe.getObject(parent, fieldOffset);
+            if (array != null) {
+                for (int i = 0; i < array.length; i++) {
+                    if (array[i] == oldChild) {
+                        array[i] = newChild;
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    public static long[] getNodeDataFieldOffsets(Class< ? > nodeClass) {
+        NodeClass clazz = NodeClass.get(nodeClass);
+        return Arrays.copyOf(clazz.nodeDataFieldOffsets, clazz.nodeDataFieldClasses.length);
+    }
+
+    public static Class[] getNodeDataFieldClasses(Class< ? > nodeClass) {
+        NodeClass clazz = NodeClass.get(nodeClass);
+        return Arrays.copyOf(clazz.nodeDataFieldClasses, clazz.nodeDataFieldClasses.length);
+    }
+
+    public static long getNodeParentOffset(Class< ? > nodeClass) {
+        NodeClass clazz = NodeClass.get(nodeClass);
+        return clazz.parentOffset;
+    }
+
+    /** Returns the number of Node field declarations in the class hierarchy. */
+    public static long[] getNodeFieldOffsets(Class< ? > nodeClass) {
+        NodeClass clazz = NodeClass.get(nodeClass);
+        return Arrays.copyOf(clazz.nodeFieldOffsets, clazz.nodeFieldOffsets.length);
+    }
+
+    /** Returns the number of Node[] declaration in the class hierarchy. */
+    public static long[] getNodeFieldArrayOffsets(Class< ? > nodeClass) {
+        NodeClass clazz = NodeClass.get(nodeClass);
+        return Arrays.copyOf(clazz.nodeArrayFieldOffsets, clazz.nodeArrayFieldOffsets.length);
+    }
+
+    public static Class[] getNodeFieldArrayClasses(Class< ? > nodeClass) {
+        NodeClass clazz = NodeClass.get(nodeClass);
+        return Arrays.copyOf(clazz.nodeArrayFieldClasses, clazz.nodeArrayFieldClasses.length);
+    }
+
+    public static Class getNodeParentClass(Class< ? > nodeClass) {
+        return NodeClass.get(nodeClass).parentClass;
+    }
+
+    public static Class[] getNodeFieldClasses(Class< ? > nodeClass) {
+        NodeClass clazz = NodeClass.get(nodeClass);
+        return Arrays.copyOf(clazz.nodeFieldClasses, clazz.nodeFieldClasses.length);
+    }
+
+    /** Returns all declared fields in the class hierarchy. */
+    public static Field[] getAllFields(Class< ? extends Object> clazz) {
+        Field[] declaredFields = clazz.getDeclaredFields();
+        if (clazz.getSuperclass() != null) {
+            return concat(getAllFields(clazz.getSuperclass()), declaredFields);
+        }
+        return declaredFields;
+    }
+
+    public static <T> T[] concat(T[] first, T[] second) {
+        T[] result = Arrays.copyOf(first, first.length + second.length);
+        System.arraycopy(second, 0, result, first.length, second.length);
+        return result;
+    }
+
+    /** find annotation in class/interface hierarchy. */
+    public static <T extends Annotation> T findAnnotation(Class< ? > clazz, Class<T> annotationClass) {
+        if (clazz.getAnnotation(annotationClass) != null) {
+            return clazz.getAnnotation(annotationClass);
+        } else {
+            for (Class< ? > intf : clazz.getInterfaces()) {
+                if (intf.getAnnotation(annotationClass) != null) {
+                    return intf.getAnnotation(annotationClass);
+                }
+            }
+            if (clazz.getSuperclass() != null) {
+                return findAnnotation(clazz.getSuperclass(), annotationClass);
+            }
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends Node> T findParent(final Node start, final Class<T> clazz) {
+        assert start != null;
+        if (clazz.isInstance(start.getParent())) {
+            return (T) start.getParent();
+        } else {
+            return start.getParent() != null ? findParent(start.getParent(), clazz) : null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <I> I findParentInterface(final Node start, final Class<I> clazz) {
+        assert start != null;
+        if (clazz.isInstance(start.getParent())) {
+            return (I) start.getParent();
+        } else {
+            return (start.getParent() != null ? findParentInterface(start.getParent(), clazz) : null);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T findFirstNodeInstance(Object root, Class<T> clazz) {
+        List<Object> childNodes = findNodeChildren(root);
+
+        for (Object childNode : childNodes) {
+            if (clazz.isInstance(childNode)) {
+                return (T) childNode;
+            } else {
+                return findFirstNodeInstance(childNode, clazz);
+            }
+        }
+        return null;
+    }
+
+    public static <T extends Node> List<T> findAllNodeInstances(final Node root, final Class<T> clazz) {
+        final List<T> nodeList = new ArrayList<>();
+        root.accept(new NodeVisitor() {
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public boolean visit(Node node) {
+                if (clazz.isInstance(node)) {
+                    nodeList.add((T) node);
+                }
+                return true;
+            }
+        });
+        return nodeList;
+    }
+
+    // Don't visit found node instances.
+    public static <T extends Node> List<T> findNodeInstancesShallow(final Node root, final Class<T> clazz) {
+        final List<T> nodeList = new ArrayList<>();
+        root.accept(new NodeVisitor() {
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public boolean visit(Node node) {
+                if (clazz.isInstance(node)) {
+                    nodeList.add((T) node);
+                    return false;
+                }
+                return true;
+            }
+        });
+        return nodeList;
+    }
+
+    /** Find node instances within current function only (not in nested functions). */
+    public static <T extends Node> List<T> findNodeInstancesInFunction(final Node root, final Class<T> clazz) {
+        final List<T> nodeList = new ArrayList<>();
+        root.accept(new NodeVisitor() {
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public boolean visit(Node node) {
+                if (clazz.isInstance(node)) {
+                    nodeList.add((T) node);
+                } else if (node instanceof RootNode && node != root) {
+                    return false;
+                }
+                return true;
+            }
+        });
+        return nodeList;
+    }
+
+    public static <I> List<I> findNodeInstancesInFunctionInterface(final Node root, final Class<I> clazz) {
+        final List<I> nodeList = new ArrayList<>();
+        root.accept(new NodeVisitor() {
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public boolean visit(Node node) {
+                if (clazz.isInstance(node)) {
+                    nodeList.add((I) node);
+                } else if (node instanceof RootNode && node != root) {
+                    return false;
+                }
+                return true;
+            }
+        });
+        return nodeList;
+    }
+
+    public static String printTreeToString(Node node) {
+        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+        printTree(new PrintStream(byteOut), node);
+        try {
+            byteOut.flush();
+        } catch (IOException e) {
+        }
+        return new String(byteOut.toByteArray());
+    }
+
+    /**
+     * Prints a human readable form of a {@link Node} AST to the given {@link PrintStream}. This print method does not
+     * check for cycles in the node structure.
+     *
+     * @param p the {@link PrintStream} to print to.
+     * @param node the root node to write
+     */
+    public static void printTree(PrintStream p, Node node) {
+        printTree(p, node, new NodeTreeResolver());
+    }
+
+    /**
+     * Prints a human readable form of a tree to the given {@link PrintStream}. The {@link TreeResolver} interface needs
+     * to be implemented to specify how the method can read the tree from plain a object.
+     *
+     * @param p the {@link PrintStream} to print to.
+     * @param o the root object to be printed.
+     * @param resolver an implementation of a tree resolver
+     */
+    public static void printTree(PrintStream p, Object o, TreeResolver resolver) {
+        printTree(p, o, resolver, 1);
+        p.println();
+    }
+
+    private static void printTree(PrintStream p, Object node, TreeResolver resolver, int level) {
+        if (node == null) {
+            p.print("null");
+            return;
+        }
+
+        p.print(node.getClass().getSimpleName());
+
+        Field[] fields = NodeUtil.getAllFields(node.getClass());
+        p.print("(");
+
+        ArrayList<Field> childFields = new ArrayList<>();
+
+        boolean first = true;
+        for (int i = 0; i < fields.length; i++) {
+            Field field = fields[i];
+            if (Modifier.isStatic(field.getModifiers()) || resolver.isFiltered(field)) {
+                continue;
+            }
+            if (resolver.isChildObject(field) || resolver.isChildArrayObject(field)) {
+                childFields.add(field);
+            }
+            if (!resolver.isDataField(field)) {
+                continue;
+            }
+            if (!first) {
+                p.print(", ");
+            } else {
+                first = false;
+            }
+
+            Object value = getObjectValue(node, field.getType(), unsafe.objectFieldOffset(field));
+
+            p.print(field.getName());
+            p.print(" = ");
+            p.print(resolver.toString(value));
+        }
+        p.print(")");
+
+        if (childFields.size() != 0) {
+            p.print(" {");
+        }
+
+        // I refetch the fields to get declaration order.
+        for (int i = 0; i < childFields.size(); i++) {
+            Field field = childFields.get(i);
+            Class< ? > fieldClass = field.getType();
+            String name = field.getName();
+
+            long offset = unsafe.objectFieldOffset(field);
+
+            Object value = getObjectValue(node, fieldClass, offset);
+
+            printNewLine(p, level);
+            p.print(name);
+            if (value == null) {
+                p.print(" = null ");
+            } else if (resolver.isChildObject(field)) {
+                p.print(" = ");
+                printTree(p, value, resolver, level + 1);
+            } else if (resolver.isChildArrayObject(field)) {
+                Object[] objectArray = resolver.convertToArray(field, value);
+                if (objectArray.length == 0) {
+                    p.print(" = []");
+                } else {
+                    p.print(" = [");
+                    for (int j = 0; j < objectArray.length; j++) {
+                        printTree(p, objectArray[j], resolver, level + 1);
+                        if (j < objectArray.length - 1) {
+                            p.print(", ");
+                        }
+                    }
+                    p.print("]");
+                }
+            } else {
+                assert false;
+            }
+        }
+
+        if (childFields.size() != 0) {
+            printNewLine(p, level - 1);
+            p.print("}");
+        }
+    }
+
+    private static Object getObjectValue(Object base, Class< ? > fieldClass, long offset) {
+        if (fieldClass == boolean.class) {
+            return unsafe.getBoolean(base, offset);
+        } else if (fieldClass == byte.class) {
+            return unsafe.getByte(base, offset);
+        } else if (fieldClass == short.class) {
+            return unsafe.getShort(base, offset);
+        } else if (fieldClass == char.class) {
+            return unsafe.getChar(base, offset);
+        } else if (fieldClass == int.class) {
+            return unsafe.getInt(base, offset);
+        } else if (fieldClass == long.class) {
+            return unsafe.getLong(base, offset);
+        } else if (fieldClass == float.class) {
+            return unsafe.getFloat(base, offset);
+        } else if (fieldClass == double.class) {
+            return unsafe.getDouble(base, offset);
+        } else {
+            return unsafe.getObject(base, offset);
+        }
+    }
+
+    private static void printNewLine(PrintStream p, int level) {
+        p.println();
+        for (int i = 0; i < level; i++) {
+            p.print("    ");
+        }
+    }
+
+    private static class NodeTreeResolver implements TreeResolver {
+
+        @Override
+        public boolean isFiltered(Field f) {
+            if (f.getName().equals("parent")) {
+                return true;
+            }
+            return f.isSynthetic();
+        }
+
+        @Override
+        public boolean isDataField(Field f) {
+            return !isChildArrayObject(f) && !isChildObject(f);
+        }
+
+        @Override
+        public boolean isChildObject(Field f) {
+            return Node.class.isAssignableFrom(f.getType());
+        }
+
+        @Override
+        public boolean isChildArrayObject(Field f) {
+            return f.getType().getComponentType() != null && Node.class.isAssignableFrom(f.getType().getComponentType());
+        }
+
+        @Override
+        public Object[] convertToArray(Field f, Object data) {
+            return (Object[]) data;
+        }
+
+        @Override
+        public String toString(Object o) {
+            return o == null ? "null" : o.toString();
+        }
+    }
+
+    /**
+     * Specifies how a tree can be built from plain objects.
+     */
+    public interface TreeResolver {
+
+        /**
+         * Returns true if a {@link Field} is filtered from the tree.
+         *
+         * @param f the field to check
+         */
+        boolean isFiltered(Field f);
+
+        /**
+         * Returns true if a {@link Field} is a field that contains a data value which should not be traversed
+         * recursively.
+         *
+         * @param f the field to check
+         * @return true if a the given field is a data field else false.
+         */
+        boolean isDataField(Field f);
+
+        /**
+         * Returns true if a {@link Field} is a field that contains an {@link Object} which should be recursively
+         * visited.
+         *
+         * @param f the field to check
+         * @return true if a the given field is a child field else false.
+         */
+        boolean isChildObject(Field f);
+
+        /**
+         * Returns true if a {@link Field} is a field that contains any kind of list/array structure which itself holds
+         * values that should be recursively visited.
+         *
+         * @param f the field to check
+         * @return true if a the given field is a child array/list field else false.
+         */
+        boolean isChildArrayObject(Field f);
+
+        /**
+         * Converts an given child array object to array which can be traversed. This is especially useful to convert
+         * any kind of list structure to a traversable array.
+         *
+         * @param f the field for meta data needed to convert the data {@link Object}.
+         * @param value the actual value of the child array/list object.
+         * @return the converted {@link Object} array.
+         */
+        Object[] convertToArray(Field f, Object value);
+
+        /**
+         * Returns a human readable string for any data field object in the tree.
+         *
+         * @param o the object to convert to string.
+         * @return the converted string
+         */
+        String toString(Object o);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+/**
+ * Visitor for trees of nodes.
+ */
+public interface NodeVisitor {
+
+    /**
+     * This visitor method is called for every node in the tree. Its return value determines if the children of this
+     * node should be excluded in the iteration.
+     *
+     * @param node the node that is currently visited
+     * @return {@code true} if the children should be visited too, {@code false} otherwise
+     */
+    boolean visit(Node node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * A root node is a node with a method to execute it given only a frame as a parameter. Therefore, a root node can be used to create a call target using {@link TruffleRuntime#createCallTarget(RootNode, FrameDescriptor)}.
+ */
+public abstract class RootNode extends Node {
+
+    /**
+     * Executes this function using the specified frame and returns the result value.
+     * @param frame the frame of the currently executing guest language method
+     * @return the value of the execution
+     */
+    public abstract Object execute(VirtualFrame frame);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+/**
+ * An exception thrown to enter a slow path. The Truffle optimizer has special knowledge of this exception class and
+ * will never compile a catch block that catches this exception type.
+ */
+public class SlowPathException extends Exception {
+
+    private static final long serialVersionUID = 3676602078425211386L;
+
+    /**
+     * Creates an exception thrown to enter a slow path.
+     */
+    public SlowPathException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java	Tue Dec 18 17:59:32 2012 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+/**
+ * An exception that should be thrown if the return value cannot be represented as a value of the return type. The
+ * Truffle optimizer has special knowledge of this exception class and will never compile a catch block that catches this
+ * exception type.
+ */
+public final class UnexpectedResultException extends SlowPathException {
+
+    private static final long serialVersionUID = 3676602078425211386L;
+    private final Object result;
+
+    /**
+     * Creates the exception with the alternative result that cannot be respresented as a value of the return type.
+     * @param result the alternative result
+     */
+    public UnexpectedResultException(Object result) {
+        super(null, null);
+        assert !(result instanceof Throwable);
+        this.result = result;
+    }
+
+    /**
+     * @return the unexpected result
+     */
+    public Object getResult() {
+        return result;
+    }
+
+    /**
+     * For performance reasons, this exception does not record any stack trace information.
+     */
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return null;
+    }
+}
--- a/mx/projects	Tue Dec 18 17:59:03 2012 +0100
+++ b/mx/projects	Tue Dec 18 17:59:32 2012 +0100
@@ -254,3 +254,18 @@
 project@com.oracle.graal.asm.amd64@dependencies=com.oracle.graal.asm,com.oracle.graal.amd64
 project@com.oracle.graal.asm.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.amd64@javaCompliance=1.7
+
+# truffle.api
+project@com.oracle.truffle.api@subDir=graal
+project@com.oracle.truffle.api@sourceDirs=src
+project@com.oracle.truffle.api@dependencies=
+project@com.oracle.truffle.api@checkstyle=com.oracle.graal.graph
+project@com.oracle.truffle.api@javaCompliance=1.7
+
+# truffle.api.test
+project@com.oracle.truffle.api.test@subDir=graal
+project@com.oracle.truffle.api.test@sourceDirs=src
+project@com.oracle.truffle.api.test@dependencies=com.oracle.truffle.api,JUNIT
+project@com.oracle.truffle.api.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.truffle.api.test@javaCompliance=1.7
+