changeset 7267:a4b84ba6dc2e

Introduction of the Truffle API for efficient implementation of dynamic languages on top of the Graal VM. New projects com.oracle.truffle.api for the API definition and com.oracle.truffle.api.test for API tests and documentation.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 18 Dec 2012 15:33:55 +0100
parents 494d99e07614
children fac81ae4f513
files graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Arguments.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/DefaultTypeConversion.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameVersion.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/TypeConversion.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultPackedFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/ExactMath.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/TruffleIntrinsics.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java mx/projects
diffstat 44 files changed, 4369 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 15:33:55 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 14:29:04 2012 +0100
+++ b/mx/projects	Tue Dec 18 15:33:55 2012 +0100
@@ -247,3 +247,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
+