changeset 10484:0097fb11c16f

Add basic version of Graal's Truffle runtime.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 23 Jun 2013 21:44:15 +0200
parents 3e6f538829ce
children 181b729e5b77
files graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/InlinePrinterProcessor.java graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/CallStackElement.java graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/MethodHolder.java graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/TruffleMethodNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoadLocalTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/TestNodeFactory.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PackedFrameImpl.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/CompilationConstantNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameAccessNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameGetNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameSetNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/MaterializeFrameNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverInlineMacroNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverPartOfCompilationNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NewFrameNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/DefaultCallTargetSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/ExactMathSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java mx/projects
diffstat 65 files changed, 5290 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/InlinePrinterProcessor.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.printer;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.truffle.printer.method.*;
+
+public final class InlinePrinterProcessor {
+
+    private static final String IDENT = "   ";
+    private static InlinePrinterProcessor instance;
+
+    private final List<TruffleMethodNode> inlineTree = new ArrayList<>();
+
+    public static void initialize() {
+        if (instance == null) {
+            instance = new InlinePrinterProcessor();
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+
+    public static void addInlining(MethodHolder methodHolder) {
+        instance.addExecuteInline(methodHolder);
+    }
+
+    public static void printTree() {
+        instance.print();
+    }
+
+    public static void reset() {
+        instance = null;
+    }
+
+    private void addExecuteInline(MethodHolder executeMethod) {
+        if (inlineTree.isEmpty()) {
+            inlineTree.add(new TruffleMethodNode(null, executeMethod));
+        } else {
+            TruffleMethodNode newNode = null;
+            for (TruffleMethodNode node : inlineTree) {
+                newNode = node.addTruffleExecuteMethodNode(executeMethod);
+                if (newNode != null) {
+                    break;
+                }
+            }
+            if (newNode == null) {
+                throw new AssertionError("Not able to add " + executeMethod.getMethod().toString() + " to the inlineing tree");
+            }
+            inlineTree.add(newNode);
+        }
+    }
+
+    private TruffleMethodNode getInlineTree() {
+        TruffleMethodNode root = inlineTree.get(0);
+        while (root.getParent() != null) {
+            root = root.getParent();
+        }
+
+        // asserting:
+        for (TruffleMethodNode node : inlineTree) {
+            TruffleMethodNode nodeRoot = node;
+            while (nodeRoot.getParent() != null) {
+                nodeRoot = nodeRoot.getParent();
+            }
+            if (root != nodeRoot) {
+                throw new AssertionError("Different roots found");
+            }
+        }
+
+        return root;
+    }
+
+    private void print() {
+        String curIndent = "";
+        TruffleMethodNode root = getInlineTree();
+        String name = root.getJavaMethod().getDeclaringClass().getName();
+        TTY.print(name.substring(name.lastIndexOf('/') + 1, name.lastIndexOf(';')) + "::" + root.getJavaMethod().getName());
+        TTY.println();
+        recursivePrint(curIndent, root);
+    }
+
+    private void recursivePrint(String curIdent, TruffleMethodNode node) {
+        Map<Integer, List<TruffleMethodNode>> inlinings = node.getInlinings();
+        for (int l : inlinings.keySet()) {
+            for (TruffleMethodNode n : inlinings.get(l)) {
+                TTY.print(curIdent);
+                TTY.print("L" + l + " ");
+                String name = n.getJavaMethod().getDeclaringClass().getName();
+                TTY.print(name.substring(name.lastIndexOf('/') + 1, name.lastIndexOf(';')) + "::" + n.getJavaMethod().getName());
+                TTY.println();
+                recursivePrint(curIdent + IDENT, n);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/CallStackElement.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.printer.method;
+
+import com.oracle.graal.api.meta.*;
+
+public class CallStackElement {
+
+    private final int lineOfInvoke;
+    private final ResolvedJavaMethod callerMethod;
+
+    public CallStackElement(ResolvedJavaMethod callerMethod, int lineOfInvoke) {
+        this.lineOfInvoke = lineOfInvoke;
+        this.callerMethod = callerMethod;
+    }
+
+    public int getLineOfInvoke() {
+        return lineOfInvoke;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof CallStackElement) {
+            CallStackElement i = (CallStackElement) o;
+            if (i.getCallerMethod() == this.getCallerMethod()/*
+                                                              * && i.lineOfInvoke ==
+                                                              * this.lineOfInvoke
+                                                              */) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    public ResolvedJavaMethod getCallerMethod() {
+        return callerMethod;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/MethodHolder.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.printer.method;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+public final class MethodHolder {
+
+    private final List<CallStackElement> callStack;
+    private final ResolvedJavaMethod method;
+
+    public static MethodHolder getNewTruffleExecuteMethod(MethodCallTargetNode targetNode) {
+        return new MethodHolder(getCallStack(targetNode), targetNode.targetMethod());
+    }
+
+    private MethodHolder(List<CallStackElement> callStack, ResolvedJavaMethod callee) {
+        this.callStack = callStack;
+        this.method = callee;
+    }
+
+    public List<CallStackElement> getCallStack() {
+        return callStack;
+    }
+
+    public ResolvedJavaMethod getMethod() {
+        return method;
+    }
+
+    private static List<CallStackElement> getCallStack(MethodCallTargetNode targetNode) {
+        List<CallStackElement> callStack = new ArrayList<>();
+        FrameState state = targetNode.invoke().stateAfter();
+        while (state != null) {
+            ResolvedJavaMethod method = state.method();
+            LineNumberTable table = method.getLineNumberTable();
+            int lineNr = table.getLineNumber(state.bci - 1);
+            callStack.add(new CallStackElement(method, lineNr));
+            state = state.outerFrameState();
+        }
+        return callStack;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/TruffleMethodNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.printer.method;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+
+public final class TruffleMethodNode {
+
+    private final TruffleMethodNode parent;
+    private final MethodHolder truffleExecuteMethod;
+    private final Map<Integer, List<TruffleMethodNode>> inlinings;
+
+    public TruffleMethodNode(TruffleMethodNode parent, MethodHolder truffleExecuteMethod) {
+        this.parent = parent;
+        this.truffleExecuteMethod = truffleExecuteMethod;
+        this.inlinings = new HashMap<>();
+    }
+
+    public TruffleMethodNode getParent() {
+        return parent;
+    }
+
+    public ResolvedJavaMethod getJavaMethod() {
+        return truffleExecuteMethod.getMethod();
+    }
+
+    public Map<Integer, List<TruffleMethodNode>> getInlinings() {
+        return inlinings;
+    }
+
+    public void putInlineList(int lineOfInvoke, List<TruffleMethodNode> list) {
+        inlinings.put(lineOfInvoke, list);
+    }
+
+    public List<TruffleMethodNode> getInliningsAtLine(int line) {
+        return inlinings.get(line);
+    }
+
+    public MethodHolder getTruffleExecuteMethod() {
+        return truffleExecuteMethod;
+    }
+
+    public TruffleMethodNode addTruffleExecuteMethodNode(MethodHolder newMethod) {
+        int lineOfInvoke = newMethod.getCallStack().get(0).getLineOfInvoke();
+
+        if (!callStackMatch(newMethod.getCallStack())) {
+            return null;
+        } else {
+            TruffleMethodNode node = new TruffleMethodNode(this, newMethod);
+            if (getInliningsAtLine(lineOfInvoke) == null) {
+                List<TruffleMethodNode> list = new ArrayList<>();
+                list.add(node);
+                putInlineList(lineOfInvoke, list);
+            } else {
+                getInliningsAtLine(lineOfInvoke).add(node);
+            }
+            return node;
+        }
+    }
+
+    private boolean callStackMatch(List<CallStackElement> callStack) {
+        List<CallStackElement> curCallStack = truffleExecuteMethod.getCallStack();
+        if (curCallStack.size() == callStack.size() - 1) {
+            if (curCallStack.size() >= 1) {
+                if (curCallStack.get(0).getCallerMethod() != callStack.get(1).getCallerMethod()) {
+                    return false;
+                }
+            }
+            for (int i = 1; i < curCallStack.size(); i++) {
+                if (!curCallStack.get(i).equals(callStack.get(i + 1))) {
+                    return false;
+                }
+            }
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.truffle.test.nodes.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class AssumptionPartialEvaluationTest extends PartialEvaluationTest {
+
+    public static Object constant42() {
+        return 42;
+    }
+
+    @Test
+    public void constantValue() {
+        FrameDescriptor fd = new FrameDescriptor();
+        Assumption assumption = Truffle.getRuntime().createAssumption();
+        AbstractTestNode result = new ConstantWithAssumptionTestNode(assumption, 42);
+        RootTestNode rootNode = new RootTestNode("constantValue", result);
+        InstalledCode installedCode = assertPartialEvalEquals("constant42", rootNode, fd);
+        Assert.assertTrue(installedCode.isValid());
+        try {
+            assertEquals(42, installedCode.execute(null, null, null));
+        } catch (InvalidInstalledCodeException e) {
+            Assert.fail("Code must not have been invalidated.");
+        }
+        Assert.assertTrue(installedCode.isValid());
+        try {
+            assumption.check();
+        } catch (InvalidAssumptionException e) {
+            Assert.fail("Assumption must not have been invalidated.");
+        }
+        assumption.invalidate();
+        try {
+            assumption.check();
+            Assert.fail("Assumption must have been invalidated.");
+        } catch (InvalidAssumptionException e) {
+        }
+        Assert.assertFalse(installedCode.isValid());
+
+        try {
+            installedCode.execute(null, null, null);
+            Assert.fail("Code must have been invalidated.");
+        } catch (InvalidInstalledCodeException e) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.truffle.substitutions.*;
+import com.oracle.truffle.api.*;
+
+public class ExactMathTest extends GraalCompilerTest {
+
+    private static boolean substitutionsInstalled;
+
+    public ExactMathTest() {
+        if (!substitutionsInstalled) {
+            Graal.getRequiredCapability(Replacements.class).registerSubstitutions(ExactMathSubstitutions.class);
+            substitutionsInstalled = true;
+        }
+    }
+
+    @Test
+    public void testAdd() {
+        test("add", 1, 2);
+        test("add", Integer.MAX_VALUE, 2);
+    }
+
+    @Test
+    public void testMul() {
+        test("mul", 1, 2);
+        test("mul", Integer.MAX_VALUE, 2);
+    }
+
+    @Test
+    public void testSub() {
+        test("sub", 1, 2);
+        test("sub", Integer.MIN_VALUE, 2);
+    }
+
+    @Test
+    public void testLongAdd() {
+        test("longAdd", (long) Integer.MAX_VALUE, 2L);
+        test("longAdd", Long.MAX_VALUE, 2L);
+    }
+
+    @Test
+    public void testLongMul() {
+        test("longMul", (long) Integer.MAX_VALUE, 2L);
+        test("longMul", (long) Integer.MIN_VALUE, 2L);
+        test("longMul", Long.MAX_VALUE, 2L);
+    }
+
+    @Test
+    public void testLongSub() {
+        test("longSub", (long) Integer.MIN_VALUE, 2L);
+        test("longSub", Long.MIN_VALUE, 2L);
+    }
+
+    public static int add(int a, int b) {
+        return ExactMath.addExact(a, b);
+    }
+
+    public static int mul(int a, int b) {
+        return ExactMath.multiplyExact(a, b);
+    }
+
+    public static int sub(int a, int b) {
+        return ExactMath.subtractExact(a, b);
+    }
+
+    public static long longAdd(long a, long b) {
+        return ExactMath.addExact(a, b);
+    }
+
+    public static long longMul(long a, long b) {
+        return ExactMath.multiplyExact(a, b);
+    }
+
+    public static long longSub(long a, long b) {
+        return ExactMath.subtractExact(a, b);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test;
+
+import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.loop.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.printer.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.printer.*;
+import com.oracle.graal.virtual.phases.ea.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class PartialEvaluationTest extends GraalCompilerTest {
+
+    private static final long UNROLL_LIMIT = 100;
+    private final PartialEvaluator nodeCompiler;
+
+    public PartialEvaluationTest() {
+        // Make sure Truffle runtime is initialized.
+        Assert.assertTrue(Truffle.getRuntime() instanceof GraalTruffleRuntime);
+        this.nodeCompiler = new PartialEvaluator(runtime, runtime);
+
+        DebugEnvironment.initialize(System.out);
+    }
+
+    protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, FrameDescriptor descriptor) {
+        return assertPartialEvalEquals(methodName, root, descriptor, Arguments.EMPTY_ARGUMENTS);
+    }
+
+    protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, FrameDescriptor descriptor, Arguments arguments) {
+        Assumptions assumptions = new Assumptions(true);
+        StructuredGraph actual = partialEval(root, descriptor, arguments, assumptions, true);
+        InstalledCode result = new TruffleCompilerImpl().compileMethodHelper(actual, GraphBuilderConfiguration.getDefault(), assumptions);
+        StructuredGraph expected = parseForComparison(methodName);
+        removeFrameStates(actual);
+        Assert.assertEquals(getCanonicalGraphString(expected, true), getCanonicalGraphString(actual, true));
+        return result;
+    }
+
+    protected void assertPartialEvalNoInvokes(RootNode root, FrameDescriptor descriptor) {
+        assertPartialEvalNoInvokes(root, descriptor, Arguments.EMPTY_ARGUMENTS);
+    }
+
+    protected void assertPartialEvalNoInvokes(RootNode root, FrameDescriptor descriptor, Arguments arguments) {
+        Assumptions assumptions = new Assumptions(true);
+        StructuredGraph actual = partialEval(root, descriptor, arguments, assumptions, true);
+        removeFrameStates(actual);
+        for (MethodCallTargetNode node : actual.getNodes(MethodCallTargetNode.class)) {
+            Assert.fail("Found invalid method call target node: " + node);
+        }
+    }
+
+    protected StructuredGraph partialEval(RootNode root, FrameDescriptor descriptor, Arguments arguments, final Assumptions assumptions, final boolean canonicalizeReads) {
+        final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root, descriptor);
+
+        // Executed AST so that all classes are loaded and initialized.
+        do {
+            compilable.call(null, arguments);
+            compilable.call(null, arguments);
+            compilable.call(null, arguments);
+        } while (compilable.inline());
+
+        StructuredGraph graph = Debug.scope("Truffle", new DebugDumpScope("Truffle: " + compilable), new Callable<StructuredGraph>() {
+
+            @Override
+            public StructuredGraph call() {
+                StructuredGraph resultGraph = nodeCompiler.createGraph(compilable, assumptions);
+                CanonicalizerPhase canonicalizer = new CanonicalizerPhase(canonicalizeReads);
+                HighTierContext context = new HighTierContext(runtime, assumptions, replacements);
+
+                if (resultGraph.hasLoops()) {
+                    boolean unrolled;
+                    do {
+                        unrolled = false;
+                        LoopsData loopsData = new LoopsData(resultGraph);
+                        loopsData.detectedCountedLoops();
+                        for (LoopEx ex : innerLoopsFirst(loopsData.countedLoops())) {
+                            if (ex.counted().isConstantMaxTripCount()) {
+                                long constant = ex.counted().constantMaxTripCount();
+                                if (constant <= UNROLL_LIMIT) {
+                                    LoopTransformations.fullUnroll(ex, runtime, assumptions, canonicalizeReads);
+                                    Debug.dump(resultGraph, "After loop unrolling %d times", constant);
+
+                                    canonicalizer.apply(resultGraph, context);
+                                    unrolled = true;
+                                    break;
+                                }
+                            }
+                        }
+                    } while (unrolled);
+                }
+
+                new DeadCodeEliminationPhase().apply(resultGraph);
+                new PartialEscapePhase(true, canonicalizer).apply(resultGraph, context);
+
+                if (TruffleInlinePrinter.getValue()) {
+                    InlinePrinterProcessor.printTree();
+                }
+
+                return resultGraph;
+            }
+
+            private List<LoopEx> innerLoopsFirst(Collection<LoopEx> loops) {
+                ArrayList<LoopEx> sortedLoops = new ArrayList<>(loops);
+                Collections.sort(sortedLoops, new Comparator<LoopEx>() {
+
+                    @Override
+                    public int compare(LoopEx o1, LoopEx o2) {
+                        return o2.lirLoop().depth - o1.lirLoop().depth;
+                    }
+                });
+                return sortedLoops;
+            }
+        });
+
+        return graph;
+    }
+
+    protected void removeFrameStates(StructuredGraph graph) {
+        for (FrameState frameState : graph.getNodes(FrameState.class)) {
+            frameState.replaceAtUsages(null);
+            frameState.safeDelete();
+        }
+        new CanonicalizerPhase.Instance(runtime, new Assumptions(false), true).apply(graph);
+        new DeadCodeEliminationPhase().apply(graph);
+    }
+
+    protected StructuredGraph parseForComparison(final String methodName) {
+
+        StructuredGraph graphResult = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName), new Callable<StructuredGraph>() {
+
+            public StructuredGraph call() {
+                Assumptions assumptions = new Assumptions(false);
+                StructuredGraph graph = parse(methodName);
+                CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(runtime, assumptions, true);
+                canonicalizerPhase.apply(graph);
+
+                // Additional inlining.
+                final PhasePlan plan = new PhasePlan();
+                GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), TruffleCompilerImpl.Optimizations);
+                plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+                plan.addPhase(PhasePosition.AFTER_PARSING, canonicalizerPhase);
+                plan.addPhase(PhasePosition.AFTER_PARSING, new DeadCodeEliminationPhase());
+
+                new ConvertDeoptimizeToGuardPhase().apply(graph);
+                canonicalizerPhase.apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+
+                InliningPhase inliningPhase = new InliningPhase(runtime, null, replacements, assumptions, null, plan, OptimisticOptimizations.NONE);
+                inliningPhase.apply(graph);
+                removeFrameStates(graph);
+
+                new ConvertDeoptimizeToGuardPhase().apply(graph);
+                canonicalizerPhase.apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+
+                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, new PhaseContext(runtime, assumptions, replacements));
+                canonicalizerPhase.apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+                return graph;
+            }
+        });
+        return graphResult;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test;
+
+import org.junit.*;
+
+import com.oracle.graal.truffle.test.nodes.*;
+import com.oracle.truffle.api.frame.*;
+
+public class SimplePartialEvaluationTest extends PartialEvaluationTest {
+
+    public static Object constant42() {
+        return 42;
+    }
+
+    @Test
+    public void constantValue() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(42);
+        assertPartialEvalEquals("constant42", new RootTestNode("constantValue", result), fd);
+    }
+
+    @Test
+    public void addConstants() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new AddTestNode(new ConstantTestNode(40), new ConstantTestNode(2));
+        assertPartialEvalEquals("constant42", new RootTestNode("addConstants", result), fd);
+    }
+
+    @Test
+    public void sequenceConstants() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new ConstantTestNode(40), new ConstantTestNode(42)});
+        assertPartialEvalEquals("constant42", new RootTestNode("sequenceConstants", result), fd);
+    }
+
+    @Test
+    public void localVariable() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(42)), new LoadLocalTestNode("x", fd)});
+        assertPartialEvalEquals("constant42", new RootTestNode("localVariable", result), fd);
+    }
+
+    @Test
+    public void longSequenceConstants() {
+        FrameDescriptor fd = new FrameDescriptor();
+        int length = 40;
+        AbstractTestNode[] children = new AbstractTestNode[length];
+        for (int i = 0; i < children.length; ++i) {
+            children[i] = new ConstantTestNode(42);
+        }
+
+        AbstractTestNode result = new BlockTestNode(children);
+        assertPartialEvalEquals("constant42", new RootTestNode("longSequenceConstants", result), fd);
+    }
+
+    @Test
+    public void longAddConstants() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(2);
+        for (int i = 0; i < 20; ++i) {
+            result = new AddTestNode(result, new ConstantTestNode(2));
+        }
+        assertPartialEvalEquals("constant42", new RootTestNode("longAddConstants", result), fd);
+    }
+
+    @Test
+    public void mixLocalAndAdd() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(40)),
+                        new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(2))), new LoadLocalTestNode("x", fd)});
+        assertPartialEvalEquals("constant42", new RootTestNode("mixLocalAndAdd", result), fd);
+    }
+
+    @Test
+    public void loop() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(0)),
+                        new LoopTestNode(21, new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(2))))});
+        assertPartialEvalEquals("constant42", new RootTestNode("loop", result), fd);
+    }
+
+    @Test
+    public void longLoop() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(0)),
+                        new LoopTestNode(42, new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(1))))});
+        assertPartialEvalNoInvokes(new RootTestNode("loop", result), fd);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+
+public class TruffleRuntimeTest {
+
+    @Test
+    public void testGraalCapabilities() {
+        assertNotNull(Graal.getRuntime().getCapability(MetaAccessProvider.class));
+    }
+
+    @Test
+    public void testRuntimeAvailable() {
+        assertNotNull(Truffle.getRuntime());
+    }
+
+    @Test
+    public void testRuntimeIsGraalRuntime() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        assertEquals(GraalTruffleRuntime.class, runtime.getClass());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public abstract class AbstractTestNode extends Node {
+
+    public abstract int execute(VirtualFrame frame);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+public class AddTestNode extends AbstractTestNode {
+
+    @Child private AbstractTestNode left;
+    @Child private AbstractTestNode right;
+
+    public AddTestNode(AbstractTestNode left, AbstractTestNode right) {
+        this.left = adoptChild(left);
+        this.right = adoptChild(right);
+    }
+
+    @Override
+    public int execute(VirtualFrame frame) {
+        return left.execute(frame) + right.execute(frame);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class BlockTestNode extends AbstractTestNode {
+
+    @Children private final AbstractTestNode[] statements;
+
+    public BlockTestNode(AbstractTestNode[] statements) {
+        this.statements = adoptChildren(statements);
+    }
+
+    @ExplodeLoop
+    @Override
+    public int execute(VirtualFrame frame) {
+        int result = 0;
+        for (AbstractTestNode statement : statements) {
+            result = statement.execute(frame);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+public class ConstantTestNode extends AbstractTestNode {
+
+    private final int value;
+
+    public ConstantTestNode(int value) {
+        this.value = value;
+    }
+
+    @Override
+    public int execute(VirtualFrame frame) {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class ConstantWithAssumptionTestNode extends AbstractTestNode {
+
+    private final int value;
+    private final Assumption assumption;
+
+    public ConstantWithAssumptionTestNode(Assumption assumption, int value) {
+        this.value = value;
+        this.assumption = assumption;
+    }
+
+    @Override
+    public int execute(VirtualFrame frame) {
+        try {
+            assumption.check();
+            return value;
+        } catch (InvalidAssumptionException e) {
+            return this.replace(new ConstantTestNode(value + 1)).execute(frame);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoadLocalTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+public class LoadLocalTestNode extends AbstractTestNode {
+
+    private final FrameSlot slot;
+
+    public LoadLocalTestNode(String name, FrameDescriptor frameDescriptor) {
+        slot = frameDescriptor.findOrAddFrameSlot(name);
+    }
+
+    @Override
+    public int execute(VirtualFrame frame) {
+        try {
+            return frame.getInt(slot);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+public class LoopTestNode extends AbstractTestNode {
+
+    private final int numberOfIterations;
+    @Child private AbstractTestNode child;
+
+    public LoopTestNode(int numberOfIterations, AbstractTestNode child) {
+        this.numberOfIterations = numberOfIterations;
+        this.child = adoptChild(child);
+    }
+
+    @Override
+    public int execute(VirtualFrame frame) {
+        int lastValue = 0;
+        for (int i = 0; i < numberOfIterations; ++i) {
+            lastValue = child.execute(frame);
+        }
+        return lastValue;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class RootTestNode extends RootNode {
+
+    private final String name;
+    @Child AbstractTestNode node;
+
+    public RootTestNode(String name, AbstractTestNode node) {
+        this.name = name;
+        this.node = node;
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        return node.execute(frame);
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+public class StoreLocalTestNode extends AbstractTestNode {
+
+    private final FrameSlot slot;
+
+    @Child private AbstractTestNode valueNode;
+
+    public StoreLocalTestNode(String name, FrameDescriptor frameDescriptor, AbstractTestNode valueNode) {
+        this.slot = frameDescriptor.findOrAddFrameSlot(name);
+        this.valueNode = valueNode;
+    }
+
+    @Override
+    public int execute(VirtualFrame frame) {
+        int value = valueNode.execute(frame);
+        try {
+            frame.setInt(slot, value);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException(e);
+        }
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/TestNodeFactory.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+public class TestNodeFactory {
+
+    public AbstractTestNode createConstant(int value) {
+        return new ConstantTestNode(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import java.util.*;
+
+import sun.misc.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * More efficient implementation of the Truffle frame that has no safety checks for frame accesses
+ * and therefore is much faster. Should not be used during debugging as potential misuses of the
+ * frame object would show up very late and would be hard to identify.
+ */
+public final class FrameWithoutBoxing implements VirtualFrame, MaterializedFrame, PackedFrame {
+
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    private final FrameDescriptor descriptor;
+    private final PackedFrame caller;
+    private final Arguments arguments;
+    private Object[] locals;
+    private long[] primitiveLocals;
+    private byte[] tags;
+
+    public FrameWithoutBoxing(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) {
+        this.descriptor = descriptor;
+        this.caller = caller;
+        this.arguments = arguments;
+        this.locals = new Object[descriptor.getSize()];
+        this.primitiveLocals = new long[descriptor.getSize()];
+        this.tags = new byte[descriptor.getSize()];
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Arguments> T getArguments(Class<T> clazz) {
+        return (T) unsafeCast(arguments, clazz);
+    }
+
+    private static Object unsafeCast(Object value, @SuppressWarnings("unused") Class clazz) {
+        return value;
+    }
+
+    @Override
+    public PackedFrame getCaller() {
+        return caller;
+    }
+
+    @Override
+    public PackedFrame pack() {
+        return this;
+    }
+
+    @Override
+    public MaterializedFrame materialize() {
+        return this;
+    }
+
+    @Override
+    public VirtualFrame unpack() {
+        return this;
+    }
+
+    @Override
+    public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Object);
+        return getObjectUnsafe(slot);
+    }
+
+    private Object getObjectUnsafe(FrameSlot slot) {
+        return unsafe.getObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET);
+    }
+
+    @Override
+    public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException {
+        verifySet(slot, FrameSlotKind.Object);
+        setObjectUnsafe(slot, value);
+    }
+
+    private void setObjectUnsafe(FrameSlot slot, Object value) {
+        unsafe.putObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, value);
+    }
+
+    @Override
+    public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Boolean);
+        return getBooleanUnsafe(slot);
+    }
+
+    private boolean getBooleanUnsafe(FrameSlot slot) {
+        return unsafe.getBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
+    }
+
+    @Override
+    public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException {
+        verifySet(slot, FrameSlotKind.Boolean);
+        setBooleanUnsafe(slot, value);
+    }
+
+    private void setBooleanUnsafe(FrameSlot slot, boolean value) {
+        unsafe.putBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
+    }
+
+    @Override
+    public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Float);
+        return getFloatUnsafe(slot);
+    }
+
+    private float getFloatUnsafe(FrameSlot slot) {
+        return unsafe.getFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
+    }
+
+    @Override
+    public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException {
+        verifySet(slot, FrameSlotKind.Float);
+        setFloatUnsafe(slot, value);
+    }
+
+    private void setFloatUnsafe(FrameSlot slot, float value) {
+        unsafe.putFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
+    }
+
+    @Override
+    public long getLong(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Long);
+        return getLongUnsafe(slot);
+    }
+
+    private long getLongUnsafe(FrameSlot slot) {
+        return unsafe.getLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
+    }
+
+    @Override
+    public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException {
+        verifySet(slot, FrameSlotKind.Long);
+        setLongUnsafe(slot, value);
+    }
+
+    private void setLongUnsafe(FrameSlot slot, long value) {
+        unsafe.putLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
+    }
+
+    @Override
+    public int getInt(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Int);
+        return getIntUnsafe(slot);
+    }
+
+    private int getIntUnsafe(FrameSlot slot) {
+        return unsafe.getInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
+    }
+
+    @Override
+    public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException {
+        verifySet(slot, FrameSlotKind.Int);
+        setIntUnsafe(slot, value);
+    }
+
+    private void setIntUnsafe(FrameSlot slot, int value) {
+        unsafe.putInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
+    }
+
+    @Override
+    public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Double);
+        return getDoubleUnsafe(slot);
+    }
+
+    private double getDoubleUnsafe(FrameSlot slot) {
+        return unsafe.getDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
+    }
+
+    @Override
+    public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException {
+        verifySet(slot, FrameSlotKind.Double);
+        setDoubleUnsafe(slot, value);
+    }
+
+    private void setDoubleUnsafe(FrameSlot slot, double value) {
+        unsafe.putDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
+    }
+
+    @Override
+    public FrameDescriptor getFrameDescriptor() {
+        return this.descriptor;
+    }
+
+    private void verifySet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException {
+        FrameSlotKind slotKind = slot.getKind();
+        if (slotKind != accessKind) {
+            if (slotKind == FrameSlotKind.Illegal) {
+                slot.setKind(accessKind);
+            } else {
+                throw new FrameSlotTypeException();
+            }
+        }
+        int slotIndex = slot.getIndex();
+        if (slotIndex >= tags.length) {
+            resize();
+        }
+        tags[slotIndex] = (byte) accessKind.ordinal();
+    }
+
+    private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException {
+        FrameSlotKind slotKind = slot.getKind();
+        if (slotKind != accessKind) {
+            if (slotKind == FrameSlotKind.Illegal && accessKind == FrameSlotKind.Object) {
+                slot.setKind(FrameSlotKind.Object);
+                this.setObject(slot, descriptor.getTypeConversion().getDefaultValue());
+            } else {
+                throw new FrameSlotTypeException();
+            }
+        }
+        int slotIndex = slot.getIndex();
+        if (slotIndex >= tags.length) {
+            resize();
+        }
+        if (tags[slotIndex] != accessKind.ordinal()) {
+            descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot));
+            if (tags[slotIndex] != accessKind.ordinal()) {
+                throw new FrameSlotTypeException();
+            }
+        }
+    }
+
+    @Override
+    public Object getValue(FrameSlot slot) {
+        int index = slot.getIndex();
+        if (index >= tags.length) {
+            assert index >= 0 && index < descriptor.getSize();
+            return descriptor.getTypeConversion().getDefaultValue();
+        }
+        byte tag = tags[index];
+        if (tag == FrameSlotKind.Illegal.ordinal()) {
+            return descriptor.getTypeConversion().getDefaultValue();
+        } else if (tag == FrameSlotKind.Boolean.ordinal()) {
+            return getBooleanUnsafe(slot);
+        } else if (tag == FrameSlotKind.Int.ordinal()) {
+            return getIntUnsafe(slot);
+        } else if (tag == FrameSlotKind.Double.ordinal()) {
+            return getDoubleUnsafe(slot);
+        } else if (tag == FrameSlotKind.Long.ordinal()) {
+            return getLongUnsafe(slot);
+        } else if (tag == FrameSlotKind.Float.ordinal()) {
+            return getFloatUnsafe(slot);
+        } else {
+            return getObjectUnsafe(slot);
+        }
+    }
+
+    private void resize() {
+        int newSize = descriptor.getSize();
+        if (newSize > tags.length) {
+            locals = Arrays.copyOf(locals, newSize);
+            primitiveLocals = Arrays.copyOf(primitiveLocals, newSize);
+            tags = Arrays.copyOf(tags, newSize);
+        }
+    }
+
+    @Override
+    public boolean isInitialized(FrameSlot slot) {
+        return !(this.tags[slot.getIndex()] == FrameSlotKind.Illegal.ordinal());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.truffle.substitutions.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Implementation of the Truffle runtime when running on top of Graal.
+ */
+public final class GraalTruffleRuntime implements TruffleRuntime {
+
+    public static GraalTruffleRuntime makeInstance() {
+        return new GraalTruffleRuntime();
+    }
+
+    private TruffleCompiler truffleCompiler;
+    private ArrayList<String> includes;
+    private ArrayList<String> excludes;
+
+    private GraalTruffleRuntime() {
+        Replacements replacements = Graal.getRequiredCapability(Replacements.class);
+        replacements.registerSubstitutions(CompilerAssertsSubstitutions.class);
+        replacements.registerSubstitutions(CompilerDirectivesSubstitutions.class);
+        replacements.registerSubstitutions(ExactMathSubstitutions.class);
+        replacements.registerSubstitutions(UnexpectedResultExceptionSubstitutions.class);
+        replacements.registerSubstitutions(SlowPathExceptionSubstitutions.class);
+        replacements.registerSubstitutions(FrameWithoutBoxingSubstitutions.class);
+        replacements.registerSubstitutions(OptimizedAssumptionSubstitutions.class);
+        replacements.registerSubstitutions(OptimizedCallTargetSubstitutions.class);
+        replacements.registerSubstitutions(DefaultCallTargetSubstitutions.class);
+    }
+
+    public String getName() {
+        return "Graal Truffle Runtime";
+    }
+
+    public CallTarget createCallTarget(RootNode rootNode) {
+        return createCallTarget(rootNode, new FrameDescriptor());
+    }
+
+    @Override
+    public CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor) {
+        if (!acceptForCompilation(rootNode)) {
+            return new DefaultCallTarget(rootNode, frameDescriptor);
+        }
+        if (truffleCompiler == null) {
+            truffleCompiler = new TruffleCompilerImpl();
+        }
+        return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleCompilationThreshold.getValue(), TruffleInliningReprofileCount.getValue(),
+                        TruffleInvalidationReprofileCount.getValue());
+    }
+
+    @Override
+    public MaterializedFrame createMaterializedFrame(Arguments arguments) {
+        return createMaterializedFrame(arguments);
+    }
+
+    @Override
+    public MaterializedFrame createMaterializedFrame(Arguments arguments, FrameDescriptor frameDescriptor) {
+        return new FrameWithoutBoxing(frameDescriptor, null, arguments);
+    }
+
+    @Override
+    public Assumption createAssumption() {
+        return createAssumption(null);
+    }
+
+    @Override
+    public Assumption createAssumption(String name) {
+        return new OptimizedAssumption(name);
+    }
+
+    private boolean acceptForCompilation(RootNode rootNode) {
+        if (TruffleCompileOnly.getValue() != null) {
+            if (includes == null) {
+                parseCompileOnly();
+            }
+
+            String name = rootNode.toString();
+            boolean included = includes.isEmpty();
+            for (int i = 0; !included && i < includes.size(); i++) {
+                if (name.contains(includes.get(i))) {
+                    included = true;
+                }
+            }
+            if (!included) {
+                return false;
+            }
+            for (String exclude : excludes) {
+                if (name.contains(exclude)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private void parseCompileOnly() {
+        includes = new ArrayList<>();
+        excludes = new ArrayList<>();
+
+        String[] items = TruffleCompileOnly.getValue().split(",");
+        for (String item : items) {
+            if (item.startsWith("~")) {
+                excludes.add(item.substring(1));
+            } else {
+                includes.add(item);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import java.lang.ref.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.nodes.*;
+
+public final class OptimizedAssumption extends AbstractAssumption {
+
+    List<WeakReference<InstalledCode>> dependentInstalledCode;
+
+    public OptimizedAssumption(String name) {
+        super(name);
+    }
+
+    @Override
+    public void check() throws InvalidAssumptionException {
+        if (!isValid) {
+            throw new InvalidAssumptionException();
+        }
+    }
+
+    @Override
+    public synchronized void invalidate() {
+        if (isValid) {
+            if (dependentInstalledCode != null) {
+                for (WeakReference<InstalledCode> installedCodeReference : dependentInstalledCode) {
+                    InstalledCode installedCode = installedCodeReference.get();
+                    if (installedCode != null) {
+                        installedCode.invalidate();
+                    }
+                }
+                dependentInstalledCode = null;
+            }
+            isValid = false;
+        }
+    }
+
+    public synchronized void registerInstalledCode(InstalledCode installedCode) {
+        if (isValid) {
+            if (dependentInstalledCode == null) {
+                dependentInstalledCode = new ArrayList<>();
+            }
+            dependentInstalledCode.add(new WeakReference<>(installedCode));
+        } else {
+            installedCode.invalidate();
+        }
+    }
+
+    @Override
+    public boolean isValid() {
+        return isValid;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.debug.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
+ */
+public final class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, FrameFactory {
+
+    private static final PrintStream OUT = TTY.out().out();
+
+    private final int inliningReprofileCount;
+    private final int invalidationReprofileCount;
+
+    protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int compilationThreshold, int inliningReprofileCount, int invalidationReprofileCount) {
+        super(rootNode, descriptor);
+        this.compiler = compiler;
+        this.invokeCounter = compilationThreshold >> 7;
+        this.loopAndInvokeCounter = compilationThreshold;
+        this.originalInvokeCounter = compilationThreshold;
+        this.rootNode.setCallTarget(this);
+        this.inliningReprofileCount = inliningReprofileCount;
+        this.invalidationReprofileCount = invalidationReprofileCount;
+    }
+
+    private InstalledCode compiledMethod;
+    private final TruffleCompiler compiler;
+    private int invokeCounter;
+    private int originalInvokeCounter;
+    private int loopAndInvokeCounter;
+    private boolean disableCompilation;
+
+    long timeCompilationStarted;
+    long timePartialEvaluationFinished;
+    long timeCompilationFinished;
+    int codeSize;
+
+    @Override
+    public Object call(PackedFrame caller, Arguments args) {
+        for (;;) {
+            if (compiledMethod != null) {
+                try {
+                    return compiledMethod.execute(this, caller, args);
+                } catch (InvalidInstalledCodeException ex) {
+                    compiledMethod = null;
+                    invokeCounter = invalidationReprofileCount;
+                    if (TruffleFunctionInlining.getValue()) {
+                        originalInvokeCounter += invalidationReprofileCount;
+                    }
+                    if (TraceTruffleCompilation.getValue()) {
+                        OUT.printf("[truffle] invalidated %-48s |Alive %4.0fms\n", rootNode, (System.nanoTime() - timeCompilationFinished) / 1e6);
+                    }
+                }
+            } else {
+                invokeCounter--;
+                loopAndInvokeCounter--;
+                if (disableCompilation || loopAndInvokeCounter > 0 || invokeCounter > 0) {
+                    return executeHelper(caller, args);
+                } else {
+                    if (TruffleFunctionInlining.getValue()) {
+                        if (inline()) {
+                            invokeCounter = 2;
+                            loopAndInvokeCounter = inliningReprofileCount;
+                            originalInvokeCounter = inliningReprofileCount;
+                        } else {
+                            compile();
+                        }
+                    } else {
+                        compile();
+                    }
+                }
+            }
+        }
+    }
+
+    public boolean inline() {
+        return new InliningHelper(this).inline();
+    }
+
+    public void compile() {
+        try {
+            compiledMethod = compiler.compile(this);
+            if (compiledMethod == null) {
+                throw new BailoutException(String.format("code installation failed (codeSize=%s)", codeSize));
+            } else {
+                if (TraceTruffleCompilation.getValue()) {
+                    OUT.printf("[truffle] optimized %-50s |Total %5.0fms |PE %4.0fms |Graal %4.0fms |CodeSize %d\n", rootNode, (timeCompilationFinished - timeCompilationStarted) / 1e6,
+                                    (timePartialEvaluationFinished - timeCompilationStarted) / 1e6, (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, codeSize);
+                }
+            }
+        } catch (Throwable e) {
+            invokeCounter = Integer.MAX_VALUE;
+            loopAndInvokeCounter = Integer.MAX_VALUE;
+            if (TraceTruffleCompilation.getValue()) {
+                if (e instanceof BailoutException) {
+                    disableCompilation = true;
+                    BailoutException bailoutException = (BailoutException) e;
+                    OUT.printf("[truffle] opt bailout %-48s  %s\n", rootNode, bailoutException.getMessage());
+                } else {
+                    OUT.printf("[truffle] opt failed %-49s  %s\n", rootNode, e.toString());
+                    if (TraceTruffleCompilationExceptions.getValue()) {
+                        e.printStackTrace(OUT);
+                    }
+                    if (TruffleCompilationExceptionsAreFatal.getValue()) {
+                        System.exit(-1);
+                    }
+                }
+            }
+        }
+    }
+
+    public Object executeHelper(PackedFrame caller, Arguments args) {
+        VirtualFrame frame = createFrame(frameDescriptor, caller, args);
+        return rootNode.execute(frame);
+    }
+
+    private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments args) {
+        return new FrameWithoutBoxing(descriptor, caller, args);
+    }
+
+    @Override
+    public VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args) {
+        return createFrame(descriptor, caller, args);
+    }
+
+    @Override
+    public String toString() {
+        return "CallTarget " + rootNode;
+    }
+
+    @Override
+    public void reportLoopCount(int count) {
+        loopAndInvokeCounter -= count;
+    }
+
+    private class InliningHelper {
+
+        private static final int MAX_SIZE = 300;
+        private static final int MAX_INLINE_SIZE = 62;
+
+        private final OptimizedCallTarget target;
+
+        public InliningHelper(OptimizedCallTarget target) {
+            this.target = target;
+        }
+
+        public boolean inline() {
+            CallTargetProfile profile = new CallTargetProfile(target.getRootNode());
+
+            if (profile.inlinableCallSites.isEmpty()) {
+                return false;
+            }
+
+            if (profile.nodeCount > MAX_SIZE) {
+                return false;
+            }
+
+            double max = 0.0D;
+            ProfiledInlinableCallSite inliningDecision = null;
+            for (Node callNode : profile.inlinableCallSites) {
+                InlinableCallSite callSite = (InlinableCallSite) callNode;
+                Node inlineTree = callSite.getInlineTree();
+                if (inlineTree == null) {
+                    continue;
+                }
+                CallTargetProfile inlineProfile = new CallTargetProfile(inlineTree);
+                if (inlineProfile.nodeCount > MAX_INLINE_SIZE || inlineProfile.nodeCount + profile.nodeCount > MAX_SIZE) {
+                    continue;
+                }
+
+                ProfiledInlinableCallSite inlinable = new ProfiledInlinableCallSite(inlineProfile, callSite);
+                double metric = (inlinable.callCount / inlineProfile.nodeCount) + ((double) inlinable.callCount / (double) originalInvokeCounter);
+                if (metric >= max) {
+                    inliningDecision = inlinable;
+                    max = metric;
+                }
+            }
+
+            for (Node callSite : profile.inlinableCallSites) {
+                ((InlinableCallSite) callSite).resetCallCount();
+            }
+
+            if (inliningDecision != null) {
+                if (inliningDecision.callSite.inline(target)) {
+                    if (TraceTruffleCompilation.getValue()) {
+
+                        String calls = String.format("%4s/%4s", inliningDecision.callCount, originalInvokeCounter);
+                        String nodes = String.format("%3s/%3s", inliningDecision.profile.nodeCount, profile.nodeCount);
+
+                        OUT.printf("[truffle] inlined   %-50s |Nodes %6s |Calls %6s         |into %s\n", inliningDecision.callSite, nodes, calls, target.getRootNode());
+                    }
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private class ProfiledInlinableCallSite {
+
+            final CallTargetProfile profile;
+            final InlinableCallSite callSite;
+            final int callCount;
+
+            public ProfiledInlinableCallSite(CallTargetProfile profile, InlinableCallSite callSite) {
+                this.profile = profile;
+                this.callSite = callSite;
+                this.callCount = callSite.getCallCount();
+            }
+
+        }
+
+        private class CallTargetProfile {
+
+            final Node root;
+            final int nodeCount;
+            final List<Node> inlinableCallSites = new ArrayList<>();
+
+            public CallTargetProfile(Node rootNode) {
+                root = rootNode;
+
+                VisitorImpl impl = new VisitorImpl();
+                root.accept(impl);
+
+                this.nodeCount = impl.visitedCount;
+            }
+
+            private class VisitorImpl implements NodeVisitor {
+
+                int visitedCount;
+
+                @Override
+                public boolean visit(Node node) {
+                    if (node instanceof RootNode && node != root) {
+                        return false;
+                    }
+
+                    if (node instanceof InlinableCallSite) {
+                        inlinableCallSites.add(node);
+                    }
+                    visitedCount++;
+                    return true;
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PackedFrameImpl.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Implementation of a packed frame that contains only a raw pointer to the native stack. This
+ * packed frame is only handed out by Truffle compiled methods.
+ * 
+ */
+public class PackedFrameImpl implements PackedFrame {
+
+    private long stackPointer;
+
+    @Override
+    public VirtualFrame unpack() {
+        return unpackNative();
+    }
+
+    private native VirtualFrame unpackNative();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.loop.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.graal.truffle.nodes.NewFrameNode.VirtualOnlyInstanceNode;
+import com.oracle.graal.truffle.phases.*;
+import com.oracle.graal.truffle.printer.*;
+import com.oracle.graal.truffle.printer.method.*;
+import com.oracle.graal.virtual.phases.ea.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Class performing the partial evaluation starting from the root node of an AST.
+ */
+public class PartialEvaluator {
+
+    private final MetaAccessProvider metaAccessProvider;
+    private final ResolvedJavaType nodeClass;
+    private final ResolvedJavaMethod executeHelperMethod;
+    private final CustomCanonicalizer customCanonicalizer;
+    private final ResolvedJavaType[] skippedExceptionTypes;
+    private final Replacements replacements;
+    private Set<Constant> constantReceivers;
+    private final HotSpotGraphCache cache;
+
+    public PartialEvaluator(GraalCodeCacheProvider runtime, MetaAccessProvider metaAccessProvider) {
+        this.metaAccessProvider = metaAccessProvider;
+        this.nodeClass = runtime.lookupJavaType(com.oracle.truffle.api.nodes.Node.class);
+        this.customCanonicalizer = new PartialEvaluatorCanonicalizer(runtime, nodeClass);
+        this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(metaAccessProvider);
+        this.replacements = Graal.getRequiredCapability(Replacements.class);
+        this.cache = HotSpotGraalRuntime.graalRuntime().getCache();
+
+        try {
+            executeHelperMethod = runtime.lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("executeHelper", PackedFrame.class, Arguments.class));
+        } catch (NoSuchMethodException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public StructuredGraph createGraph(final OptimizedCallTarget node, final Assumptions assumptions) {
+        if (Dump.getValue() != null && Dump.getValue().contains("Truffle")) {
+            RootNode root = node.getRootNode();
+            if (root != null) {
+                new GraphPrintVisitor().beginGroup("TruffleGraph").beginGraph(node.toString()).visit(root).printToNetwork();
+            }
+        }
+
+        if (TraceTruffleCompilationDetails.getValue()) {
+            constantReceivers = new HashSet<>();
+        }
+
+        final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault();
+        config.setSkippedExceptionTypes(skippedExceptionTypes);
+
+        final StructuredGraph graph = new StructuredGraph(executeHelperMethod);
+
+        if (TruffleInlinePrinter.getValue()) {
+            InlinePrinterProcessor.initialize();
+        }
+
+        Debug.scope("createGraph", graph, new Runnable() {
+
+            @Override
+            public void run() {
+                new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations).apply(graph);
+
+                // Replace thisNode with constant.
+                LocalNode thisNode = graph.getLocal(0);
+                thisNode.replaceAndDelete(ConstantNode.forObject(node, metaAccessProvider, graph));
+
+                // Canonicalize / constant propagate.
+                CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), null, customCanonicalizer);
+                canonicalizerPhase.apply(graph);
+
+                // Intrinsify methods.
+                new ReplaceIntrinsicsPhase(replacements).apply(graph);
+
+                NewFrameNode newFrameNode = graph.getNodes(NewFrameNode.class).first();
+                if (newFrameNode == null) {
+                    throw GraalInternalError.shouldNotReachHere("frame not found");
+                }
+
+                Debug.dump(graph, "Before inlining");
+
+                // Make sure frame does not escape.
+                expandTree(config, graph, newFrameNode, assumptions);
+
+                if (TruffleInlinePrinter.getValue()) {
+                    InlinePrinterProcessor.printTree();
+                    InlinePrinterProcessor.reset();
+                }
+
+                if (TraceTruffleCompilationDetails.getValue() && constantReceivers != null) {
+                    DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes");
+                    for (Constant c : constantReceivers) {
+                        histogram.add(c.asObject().getClass().getSimpleName());
+                    }
+                    histogram.print(TTY.out().out());
+                }
+
+                // Additional inlining.
+                final PhasePlan plan = new PhasePlan();
+                GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations);
+                plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+                plan.addPhase(PhasePosition.AFTER_PARSING, canonicalizerPhase);
+                plan.addPhase(PhasePosition.AFTER_PARSING, new ReplaceIntrinsicsPhase(replacements));
+
+                new ConvertDeoptimizeToGuardPhase().apply(graph);
+                canonicalizerPhase.apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+
+                InliningPhase inliningPhase = new InliningPhase(metaAccessProvider, null, replacements, assumptions, cache, plan, OptimisticOptimizations.NONE);
+                inliningPhase.setCustomCanonicalizer(customCanonicalizer);
+                inliningPhase.apply(graph);
+
+                // Convert deopt to guards.
+                new ConvertDeoptimizeToGuardPhase().apply(graph);
+
+                // Canonicalize / constant propagate.
+                canonicalizerPhase.apply(graph);
+
+                for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) {
+                    Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage());
+                    throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception);
+                }
+
+                // EA frame and clean up.
+                new VerifyFrameDoesNotEscapePhase().apply(graph, false);
+                new PartialEscapePhase(false, new CanonicalizerPhase(!AOTCompilation.getValue())).apply(graph, new HighTierContext(metaAccessProvider, assumptions, replacements));
+                new VerifyNoIntrinsicsLeftPhase().apply(graph, false);
+                for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) {
+                    materializeNode.replaceAtUsages(materializeNode.getFrame());
+                    graph.removeFixed(materializeNode);
+                }
+                for (VirtualOnlyInstanceNode virtualOnlyNode : graph.getNodes(VirtualOnlyInstanceNode.class)) {
+                    virtualOnlyNode.setAllowMaterialization(true);
+                }
+
+                // Convert deopt to guards.
+                new ConvertDeoptimizeToGuardPhase().apply(graph);
+
+                // Canonicalize / constant propagate.
+                canonicalizerPhase.apply(graph);
+            }
+        });
+
+        return graph;
+    }
+
+    private void expandTree(GraphBuilderConfiguration config, StructuredGraph graph, NewFrameNode newFrameNode, Assumptions assumptions) {
+        for (Node usage : newFrameNode.usages().snapshot()) {
+            if (usage instanceof MethodCallTargetNode && !usage.isDeleted()) {
+                MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) usage;
+                InvokeKind kind = methodCallTargetNode.invokeKind();
+                if (kind == InvokeKind.Special || kind == InvokeKind.Static) {
+                    if (TruffleInlinePrinter.getValue()) {
+                        InlinePrinterProcessor.addInlining(MethodHolder.getNewTruffleExecuteMethod(methodCallTargetNode));
+                    }
+                    if (TraceTruffleCompilationDetails.getValue() && kind == InvokeKind.Special && methodCallTargetNode.arguments().first() instanceof ConstantNode) {
+                        ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first();
+                        constantReceivers.add(constantNode.asConstant());
+                    }
+                    StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
+                    NewFrameNode otherNewFrame = null;
+                    if (inlineGraph == null) {
+                        inlineGraph = parseGraph(config, methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, !AOTCompilation.getValue());
+                        otherNewFrame = inlineGraph.getNodes(NewFrameNode.class).first();
+                    }
+                    int mark = graph.getMark();
+                    Map<Node, Node> mapping = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false);
+                    if (Debug.isDumpEnabled()) {
+                        Debug.dump(graph, "After inlining %s +%d (%d)", methodCallTargetNode.targetMethod().toString(), graph.getNewNodes(mark).count(), graph.getNodeCount());
+                    }
+
+                    if (newFrameNode.isAlive() && newFrameNode.usages().isNotEmpty()) {
+                        expandTree(config, graph, newFrameNode, assumptions);
+                    }
+
+                    if (otherNewFrame != null) {
+                        otherNewFrame = (NewFrameNode) mapping.get(otherNewFrame);
+                        if (otherNewFrame.isAlive() && otherNewFrame.usages().isNotEmpty()) {
+                            expandTree(config, graph, otherNewFrame, assumptions);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private StructuredGraph parseGraph(final GraphBuilderConfiguration config, final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions,
+                    final boolean canonicalizeReads) {
+
+        final StructuredGraph graph = new StructuredGraph(targetMethod);
+        Debug.scope("parseGraph", targetMethod, new Runnable() {
+
+            @Override
+            public void run() {
+                new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations).apply(graph);
+                // Pass on constant arguments.
+                for (LocalNode local : graph.getNodes(LocalNode.class)) {
+                    ValueNode arg = arguments.get(local.index());
+                    if (arg instanceof NewFrameNode) {
+                        local.setStamp(arg.stamp());
+                    } else if (arg.isConstant()) {
+                        Constant constant = arg.asConstant();
+                        local.replaceAndDelete(ConstantNode.forConstant(constant, metaAccessProvider, graph));
+                    }
+                }
+
+                // Canonicalize / constant propagate.
+                new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph);
+
+                // Intrinsify methods.
+                new ReplaceIntrinsicsPhase(replacements).apply(graph);
+
+                // Inline trivial getter methods
+                new InlineTrivialGettersPhase(metaAccessProvider, assumptions, customCanonicalizer).apply(graph);
+
+                // Convert deopt to guards.
+                new ConvertDeoptimizeToGuardPhase().apply(graph);
+
+                if (graph.hasLoops()) {
+                    boolean unrolled;
+                    do {
+                        unrolled = false;
+                        LoopsData loopsData = new LoopsData(graph);
+                        loopsData.detectedCountedLoops();
+                        for (LoopEx ex : innerLoopsFirst(loopsData.countedLoops())) {
+                            if (ex.counted().isConstantMaxTripCount()) {
+                                long constant = ex.counted().constantMaxTripCount();
+                                if (constant <= TruffleConstantUnrollLimit.getValue() || targetMethod.getAnnotation(ExplodeLoop.class) != null) {
+                                    LoopTransformations.fullUnroll(ex, metaAccessProvider, assumptions, canonicalizeReads);
+                                    Debug.dump(graph, "After loop unrolling %d times", constant);
+                                    new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph);
+                                    unrolled = true;
+                                    break;
+                                }
+                            }
+                        }
+                    } while (unrolled);
+                }
+            }
+
+            private List<LoopEx> innerLoopsFirst(Collection<LoopEx> loops) {
+                ArrayList<LoopEx> sortedLoops = new ArrayList<>(loops);
+                Collections.sort(sortedLoops, new Comparator<LoopEx>() {
+
+                    @Override
+                    public int compare(LoopEx o1, LoopEx o2) {
+                        return o2.lirLoop().depth - o1.lirLoop().depth;
+                    }
+                });
+                return sortedLoops;
+            }
+        });
+
+        return graph;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.Node.Child;
+
+final class PartialEvaluatorCanonicalizer implements CanonicalizerPhase.CustomCanonicalizer {
+
+    private final MetaAccessProvider runtime;
+    private final ResolvedJavaType nodeClass;
+
+    PartialEvaluatorCanonicalizer(MetaAccessProvider runtime, ResolvedJavaType nodeClass) {
+        this.runtime = runtime;
+        this.nodeClass = nodeClass;
+    }
+
+    @Override
+    public ValueNode canonicalize(ValueNode node) {
+        if (node instanceof LoadFieldNode) {
+            LoadFieldNode loadFieldNode = (LoadFieldNode) node;
+            if (!loadFieldNode.isStatic() &&
+                            loadFieldNode.object().isConstant() &&
+                            !loadFieldNode.object().isNullConstant() &&
+                            ((loadFieldNode.kind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || Modifier.isFinal(loadFieldNode.field().getModifiers()) || loadFieldNode.field().getAnnotation(
+                                            CompilerDirectives.CompilationFinal.class) != null)) {
+                Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant());
+                return ConstantNode.forConstant(constant, this.runtime, node.graph());
+            }
+        } else if (node instanceof LoadIndexedNode) {
+            LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node;
+            Stamp stamp = loadIndexedNode.array().stamp();
+            if (stamp.kind() == Kind.Object && loadIndexedNode.array().isConstant() && !loadIndexedNode.array().isNullConstant() && loadIndexedNode.index().isConstant()) {
+                ObjectStamp objectStamp = (ObjectStamp) stamp;
+                ResolvedJavaType type = objectStamp.type();
+                if (type != null && type.isArray() && this.nodeClass.isAssignableFrom(type.getComponentType())) {
+                    Object array = loadIndexedNode.array().asConstant().asObject();
+                    int index = loadIndexedNode.index().asConstant().asInt();
+                    Object value = Array.get(array, index);
+                    return ConstantNode.forObject(value, this.runtime, node.graph());
+                }
+            }
+        } else if (node instanceof UnsafeLoadNode) {
+            UnsafeLoadNode unsafeLoadNode = (UnsafeLoadNode) node;
+            if (unsafeLoadNode.offset().isConstant()) {
+                long offset = unsafeLoadNode.offset().asConstant().asLong() + unsafeLoadNode.displacement();
+                ResolvedJavaType type = unsafeLoadNode.object().objectStamp().type();
+                ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset);
+                if (field != null) {
+                    return node.graph().add(new LoadFieldNode(unsafeLoadNode.object(), field));
+                }
+            }
+        } else if (node instanceof UnsafeStoreNode) {
+            UnsafeStoreNode unsafeStoreNode = (UnsafeStoreNode) node;
+            if (unsafeStoreNode.offset().isConstant()) {
+                long offset = unsafeStoreNode.offset().asConstant().asLong() + unsafeStoreNode.displacement();
+                ResolvedJavaType type = unsafeStoreNode.object().objectStamp().type();
+                ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset);
+                if (field != null) {
+                    StoreFieldNode storeFieldNode = node.graph().add(new StoreFieldNode(unsafeStoreNode.object(), field, unsafeStoreNode.value()));
+                    storeFieldNode.setStateAfter(unsafeStoreNode.stateAfter());
+                    return storeFieldNode;
+                }
+            }
+        }
+
+        return node;
+    }
+
+    private ResolvedJavaField recursiveFindFieldWithOffset(ResolvedJavaType type, long offset) {
+        if (type != null) {
+            ResolvedJavaField field = type.findInstanceFieldWithOffset(offset);
+            if (field != null) {
+                return field;
+            }
+            return recursiveFindFieldWithOffset(type.getSuperclass(), offset);
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import com.oracle.graal.api.code.*;
+
+/**
+ * Interface of the Truffle compiler producing an {@link InstalledCode} object from the partial
+ * evaluation starting with the AST represented by the given {@link OptimizedCallTarget} node.
+ */
+public interface TruffleCompiler {
+
+    InstalledCode compile(OptimizedCallTarget node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Assumptions.Assumption;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.printer.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Implementation of the Truffle compiler using Graal.
+ */
+public class TruffleCompilerImpl implements TruffleCompiler {
+
+    private final GraalCodeCacheProvider runtime;
+    private final Suites suites;
+    private final PartialEvaluator nodeCompiler;
+    private final MetaAccessProvider metaAccessProvider;
+    private final Replacements replacements;
+    private final Backend backend;
+    private final ResolvedJavaType[] skippedExceptionTypes;
+    private final HotSpotGraalRuntime graalRuntime;
+
+    private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class};
+
+    public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability,
+                    OptimisticOptimizations.Optimization.RemoveNeverExecutedCode);
+
+    public TruffleCompilerImpl() {
+        this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class);
+        this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
+        this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class);
+        this.backend = Graal.getRequiredCapability(Backend.class);
+        this.replacements = Graal.getRequiredCapability(Replacements.class);
+        this.graalRuntime = HotSpotGraalRuntime.graalRuntime();
+
+        this.nodeCompiler = new PartialEvaluator(runtime, metaAccessProvider);
+        this.skippedExceptionTypes = getSkippedExceptionTypes(metaAccessProvider);
+
+        if (DebugEnabled.getValue()) {
+            DebugEnvironment.initialize(System.out);
+        }
+    }
+
+    static ResolvedJavaType[] getSkippedExceptionTypes(MetaAccessProvider metaAccessProvider) {
+        ResolvedJavaType[] skippedExceptionTypes = new ResolvedJavaType[SKIPPED_EXCEPTION_CLASSES.length];
+        for (int i = 0; i < SKIPPED_EXCEPTION_CLASSES.length; i++) {
+            skippedExceptionTypes[i] = metaAccessProvider.lookupJavaType(SKIPPED_EXCEPTION_CLASSES[i]);
+        }
+        return skippedExceptionTypes;
+    }
+
+    public InstalledCode compile(final OptimizedCallTarget compilable) {
+        Object[] debug = new Object[]{new DebugDumpScope("Truffle: " + compilable)};
+        return Debug.scope("Truffle", debug, new Callable<InstalledCode>() {
+
+            @Override
+            public InstalledCode call() throws Exception {
+                return compileMethodImpl(compilable);
+            }
+        });
+    }
+
+    private InstalledCode compileMethodImpl(final OptimizedCallTarget compilable) {
+        final StructuredGraph graph;
+        final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault();
+        config.setSkippedExceptionTypes(skippedExceptionTypes);
+        graalRuntime.evictDeoptedGraphs();
+
+        compilable.timeCompilationStarted = System.nanoTime();
+        Assumptions assumptions = new Assumptions(true);
+        graph = nodeCompiler.createGraph(compilable, assumptions);
+        compilable.timePartialEvaluationFinished = System.nanoTime();
+        InstalledCode compiledMethod = compileMethodHelper(graph, config, compilable, assumptions);
+        compilable.timeCompilationFinished = System.nanoTime();
+        return compiledMethod;
+    }
+
+    public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final Assumptions assumptions) {
+        return compileMethodHelper(graph, config, null, assumptions);
+    }
+
+    public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final OptimizedCallTarget compilable, final Assumptions assumptions) {
+        final PhasePlan plan = createPhasePlan(config);
+
+        Debug.scope("TruffleFinal", graph, new Runnable() {
+
+            @Override
+            public void run() {
+                Debug.dump(graph, "After TruffleTier");
+            }
+        });
+
+        final Graph graphCopy = graph.copy();
+
+        final CompilationResult result = Debug.scope("TruffleGraal", new Callable<CompilationResult>() {
+
+            @Override
+            public CompilationResult call() {
+                CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+                return GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, plan, OptimisticOptimizations.ALL, new SpeculationLog(), suites);
+            }
+        });
+
+        List<AssumptionValidAssumption> validAssumptions = new ArrayList<>();
+        Assumptions newAssumptions = new Assumptions(true);
+        if (assumptions != null) {
+            for (Assumption assumption : assumptions.getAssumptions()) {
+                processAssumption(newAssumptions, assumption, validAssumptions);
+            }
+        }
+
+        if (result.getAssumptions() != null) {
+            for (Assumption assumption : result.getAssumptions().getAssumptions()) {
+                processAssumption(newAssumptions, assumption, validAssumptions);
+            }
+        }
+
+        result.setAssumptions(newAssumptions);
+
+        InstalledCode compiledMethod = Debug.scope("CodeInstall", new Object[]{graph.method()}, new Callable<InstalledCode>() {
+
+            @Override
+            public InstalledCode call() throws Exception {
+                InstalledCode installedCode = runtime.addMethod(graph.method(), result, graphCopy);
+                if (installedCode != null) {
+                    Debug.dump(new Object[]{result, installedCode}, "After code installation");
+                }
+                return installedCode;
+            }
+        });
+
+        for (AssumptionValidAssumption a : validAssumptions) {
+            a.getAssumption().registerInstalledCode(compiledMethod);
+        }
+
+        if (Debug.isLogEnabled()) {
+            Debug.log(runtime.disassemble(result, compiledMethod));
+        }
+        if (compilable != null) {
+            compilable.codeSize = result.getTargetCodeSize();
+        }
+        return compiledMethod;
+    }
+
+    private PhasePlan createPhasePlan(final GraphBuilderConfiguration config) {
+        final PhasePlan phasePlan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        return phasePlan;
+    }
+
+    public void processAssumption(Assumptions newAssumptions, Assumption assumption, List<AssumptionValidAssumption> manual) {
+        if (assumption != null) {
+            if (assumption instanceof AssumptionValidAssumption) {
+                AssumptionValidAssumption assumptionValidAssumption = (AssumptionValidAssumption) assumption;
+                manual.add(assumptionValidAssumption);
+            } else {
+                newAssumptions.record(assumption);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle;
+
+import com.oracle.graal.options.*;
+
+/**
+ * Options for the Truffle compiler.
+ */
+public class TruffleCompilerOptions {
+
+    // @formatter:off
+    // configuration
+    /**
+     * Instructs the Truffle Compiler to compile call targets only if their name contains at least one element of a comma-separated list of includes.
+     * Excludes are prefixed with a tilde (~).
+     * 
+     * The format in EBNF:
+     * <pre>
+     * CompileOnly = Element, { ',', Element } ;
+     * Element = Include | '~' Exclude ;
+     * </pre>
+     */
+    @Option(help = "")
+    public static final OptionValue<String> TruffleCompileOnly = new OptionValue<>(null);
+    @Option(help = "")
+    public static final OptionValue<Integer> TruffleCompilationThreshold = new OptionValue<>(1000);
+    @Option(help = "")
+    public static final OptionValue<Integer> TruffleInvalidationReprofileCount = new OptionValue<>(3);
+    @Option(help = "")
+    public static final OptionValue<Integer> TruffleInliningReprofileCount = new OptionValue<>(100);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleFunctionInlining = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> TruffleConstantUnrollLimit = new OptionValue<>(32);
+
+    // tracing
+    @Option(help = "")
+    public static final OptionValue<Boolean> TraceTruffleCompilation = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TraceTruffleCompilationDetails = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleInlinePrinter = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TraceTruffleCompilationExceptions = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleCompilationExceptionsAreFatal = new OptionValue<>(true);
+    // @formatter:on
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.truffle.*;
+
+public class AssumptionNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType, Simplifiable {
+
+    public AssumptionNode(Invoke invoke) {
+        super(invoke);
+        assert super.arguments.size() == 1;
+    }
+
+    private ValueNode getAssumption() {
+        return arguments.first();
+    }
+
+    public void simplify(SimplifierTool tool) {
+        ValueNode assumption = getAssumption();
+        if (tool.assumptions() != null && assumption.isConstant()) {
+            Constant c = assumption.asConstant();
+            assert c.getKind() == Kind.Object;
+            Object object = c.asObject();
+            OptimizedAssumption assumptionObject = (OptimizedAssumption) object;
+            StructuredGraph graph = graph();
+            if (assumptionObject.isValid()) {
+                tool.assumptions().record(new AssumptionValidAssumption(assumptionObject));
+                if (super.getReturnType().getKind() == Kind.Boolean) {
+                    graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(true, graph()));
+                } else {
+                    graph.removeFixed(this);
+                }
+            } else {
+                if (super.getReturnType().getKind() == Kind.Boolean) {
+                    graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(false, graph()));
+                } else {
+                    tool.deleteBranch(this.next());
+                    this.replaceAndDelete(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None)));
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.truffle.*;
+
+public class AssumptionValidAssumption extends Assumptions.Assumption {
+
+    private static final long serialVersionUID = 2010244979610891262L;
+
+    private OptimizedAssumption assumption;
+
+    public AssumptionValidAssumption(OptimizedAssumption assumption) {
+        this.assumption = assumption;
+    }
+
+    public OptimizedAssumption getAssumption() {
+        return assumption;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+public class BailoutNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType, Canonicalizable {
+
+    public BailoutNode(Invoke invoke) {
+        super(invoke);
+        assert arguments.size() == 1;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        ValueNode arg = arguments.get(0);
+        String message = "";
+        if (arg.isConstant()) {
+            message = (String) arg.asConstant().asObject();
+        }
+        throw new BailoutException(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/CompilationConstantNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+public class CompilationConstantNode extends NeverPartOfCompilationNode implements Canonicalizable {
+
+    public CompilationConstantNode(Invoke invoke) {
+        super(invoke, "The value could not be reduced to a compile time constant.");
+        assert arguments.size() == 1;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (arguments.get(0).isConstant()) {
+            return arguments.get(0);
+        }
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameAccessNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Base node class for the intrinsic nodes for read and write access to a Truffle frame.
+ */
+public abstract class FrameAccessNode extends FixedWithNextNode implements Simplifiable {
+
+    @Input private ValueNode frame;
+    @Input private ValueNode slot;
+    protected final ResolvedJavaField field;
+    protected final Kind slotKind;
+
+    public FrameAccessNode(Stamp stamp, Kind slotKind, ValueNode frame, ValueNode slot, ResolvedJavaField field) {
+        super(stamp);
+        this.slotKind = slotKind;
+        this.frame = frame;
+        this.slot = slot;
+        this.field = field;
+    }
+
+    public ValueNode getFrame() {
+        return frame;
+    }
+
+    public ValueNode getSlot() {
+        return slot;
+    }
+
+    public Kind getSlotKind() {
+        return slotKind;
+    }
+
+    protected int getSlotIndex() {
+        return getFrameSlot().getIndex();
+    }
+
+    protected boolean isFrameSlotConstant() {
+        return slot.isConstant();
+    }
+
+    protected FrameSlot getFrameSlot() {
+        assert isFrameSlotConstant() : slot;
+        return (FrameSlot) slot.asConstant().asObject();
+    }
+
+    protected final void insertDeoptimization(VirtualizerTool tool) {
+        LogicNode contradiction = LogicConstantNode.contradiction(graph());
+        FixedGuardNode fixedGuard = new FixedGuardNode(contradiction, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile);
+        tool.addNode(fixedGuard);
+    }
+
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name) {
+            return super.toString(verbosity) + getSlotKind().name() + (isFrameSlotConstant() ? " " + getFrameSlot() : "");
+        } else {
+            return super.toString(verbosity);
+        }
+    }
+
+    protected final ValueNode getSlotOffset(int scale, MetaAccessProvider metaAccessProvider) {
+        if (isFrameSlotConstant()) {
+            return ConstantNode.forInt(getSlotIndex() * scale, graph());
+        } else {
+            LoadFieldNode loadFrameSlotIndex = graph().add(new LoadFieldNode(getSlot(), metaAccessProvider.lookupJavaField(getFrameSlotIndexField())));
+            graph().addBeforeFixed(this, loadFrameSlotIndex);
+            return scale == 1 ? loadFrameSlotIndex : IntegerArithmeticNode.mul(loadFrameSlotIndex, ConstantNode.forInt(scale, graph()));
+        }
+    }
+
+    private static Field getFrameSlotIndexField() {
+        try {
+            return FrameSlotImpl.class.getDeclaredField("index");
+        } catch (NoSuchFieldException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected final boolean isValidAccessKind() {
+        if (getSlotKind() == Kind.Byte) {
+            // tag access
+            return true;
+        }
+
+        return getSlotKind() == getGraalKind(getFrameSlot().getKind());
+    }
+
+    private static Kind getGraalKind(FrameSlotKind kind) {
+        switch (kind) {
+            case Object:
+                return Kind.Object;
+            case Long:
+                return Kind.Long;
+            case Int:
+                return Kind.Int;
+            case Double:
+                return Kind.Double;
+            case Float:
+                return Kind.Float;
+            case Boolean:
+                return Kind.Boolean;
+            case Illegal:
+            default:
+                return Kind.Illegal;
+        }
+    }
+
+    @Override
+    public final void simplify(SimplifierTool tool) {
+        if (isFrameSlotConstant()) {
+            if (!isValidAccessKind()) {
+                tool.deleteBranch(this.next());
+                this.replaceAndDelete(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode)));
+            }
+        }
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> properties = super.getDebugProperties(map);
+        if (isFrameSlotConstant()) {
+            properties.put("frameSlot", getFrameSlot().toString());
+        }
+        return properties;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameGetNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Intrinsic node for read access to a Truffle frame.
+ */
+@NodeInfo(nameTemplate = "FrameGet{p#slotKind/s}{p#frameSlot/s}")
+public class FrameGetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable {
+
+    public FrameGetNode(Kind kind, ValueNode frame, ValueNode slot, ResolvedJavaField field) {
+        super(StampFactory.forKind(kind), kind, frame, slot, field);
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (!isFrameSlotConstant()) {
+            return;
+        }
+        assert isValidAccessKind();
+        State virtualFrame = tool.getObjectState(getFrame());
+        if (virtualFrame == null || virtualFrame.getState() != EscapeState.Virtual) {
+            return;
+        }
+        assert virtualFrame.getVirtualObject().type() == NewFrameNode.FRAME_TYPE : virtualFrame;
+        VirtualInstanceNode virtualFrameObject = (VirtualInstanceNode) virtualFrame.getVirtualObject();
+        int arrayFieldIndex = virtualFrameObject.fieldIndex(field);
+        State virtualArray = tool.getObjectState(virtualFrame.getEntry(arrayFieldIndex));
+        assert virtualArray != null;
+        ValueNode result = virtualArray.getEntry(getSlotIndex());
+        State virtualResult = tool.getObjectState(result);
+        if (virtualResult != null) {
+            tool.replaceWithVirtual(virtualResult.getVirtualObject());
+        } else {
+            tool.replaceWithValue(result);
+        }
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        assert !(getFrame() instanceof NewFrameNode);
+        StructuredGraph structuredGraph = graph();
+
+        LoadFieldNode loadFieldNode = graph().add(new LoadFieldNode(getFrame(), field));
+        structuredGraph.addBeforeFixed(this, loadFieldNode);
+        FixedWithNextNode loadNode;
+        if (!getSlotKind().isPrimitive()) {
+            ValueNode slotIndex = getSlotOffset(1, tool.getRuntime());
+            loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, Kind.Object));
+        } else if (getSlotKind() == Kind.Byte) {
+            ValueNode slotIndex = getSlotOffset(1, tool.getRuntime());
+            loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, Kind.Byte));
+        } else {
+            ValueNode slotOffset = getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getRuntime());
+            loadNode = graph().add(new UnsafeLoadNode(loadFieldNode, Unsafe.ARRAY_LONG_BASE_OFFSET, slotOffset, getSlotKind()));
+        }
+        structuredGraph.replaceFixedWithFixed(this, loadNode);
+    }
+
+    @NodeIntrinsic
+    public static native <T> T get(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, @ConstantNodeParameter ResolvedJavaField field);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameSetNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Intrinsic node for write access to a Truffle frame.
+ */
+@NodeInfo(nameTemplate = "FrameSet{p#slotKind/s}{p#frameSlot/s}")
+public class FrameSetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable {
+
+    @Input private ValueNode value;
+
+    public FrameSetNode(Kind kind, ValueNode frame, ValueNode frameSlot, ValueNode value, ResolvedJavaField field) {
+        super(StampFactory.forVoid(), kind, frame, frameSlot, field);
+        this.value = value;
+    }
+
+    public ValueNode getValue() {
+        return value;
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (!isFrameSlotConstant()) {
+            return;
+        }
+        assert isValidAccessKind();
+        State virtualFrame = tool.getObjectState(getFrame());
+        if (virtualFrame == null || virtualFrame.getState() != EscapeState.Virtual) {
+            return;
+        }
+        assert virtualFrame.getVirtualObject().type() == NewFrameNode.FRAME_TYPE : virtualFrame;
+        VirtualInstanceNode virtualFrameObject = (VirtualInstanceNode) virtualFrame.getVirtualObject();
+        int arrayFieldIndex = virtualFrameObject.fieldIndex(field);
+        State virtualArray = tool.getObjectState(virtualFrame.getEntry(arrayFieldIndex));
+        assert virtualArray != null;
+        ValueNode storedValue = value;
+        tool.setVirtualEntry(virtualArray, getSlotIndex(), storedValue);
+        tool.delete();
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        assert !(getFrame() instanceof NewFrameNode);
+        StructuredGraph structuredGraph = graph();
+
+        LoadFieldNode loadFieldNode = graph().add(new LoadFieldNode(getFrame(), field));
+        structuredGraph.addBeforeFixed(this, loadFieldNode);
+        FixedWithNextNode storeNode;
+        if (!getSlotKind().isPrimitive()) {
+            ValueNode slotIndex = getSlotOffset(1, tool.getRuntime());
+            storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Object, value));
+        } else if (getSlotKind() == Kind.Byte) {
+            ValueNode slotIndex = getSlotOffset(1, tool.getRuntime());
+            storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Byte, value));
+        } else {
+            ValueNode slotOffset = getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getRuntime());
+            storeNode = graph().add(new UnsafeStoreNode(loadFieldNode, Unsafe.ARRAY_LONG_BASE_OFFSET, slotOffset, value, getSlotKind()));
+        }
+        structuredGraph.replaceFixedWithFixed(this, storeNode);
+    }
+
+    @NodeIntrinsic
+    public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, Object value, @ConstantNodeParameter ResolvedJavaField field);
+
+    @NodeIntrinsic
+    public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, byte value, @ConstantNodeParameter ResolvedJavaField field);
+
+    @NodeIntrinsic
+    public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, boolean value, @ConstantNodeParameter ResolvedJavaField field);
+
+    @NodeIntrinsic
+    public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, int value, @ConstantNodeParameter ResolvedJavaField field);
+
+    @NodeIntrinsic
+    public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, long value, @ConstantNodeParameter ResolvedJavaField field);
+
+    @NodeIntrinsic
+    public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, double value, @ConstantNodeParameter ResolvedJavaField field);
+
+    @NodeIntrinsic
+    public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, float value, @ConstantNodeParameter ResolvedJavaField field);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.truffle.api.*;
+
+/**
+ * Node representing an exact integer addition that will throw an {@link ArithmeticException} in
+ * case the addition would overflow the 32 bit range.
+ */
+public class IntegerAddExactNode extends IntegerAddNode implements Canonicalizable, IntegerExactArithmeticNode {
+
+    public IntegerAddExactNode(ValueNode x, ValueNode y) {
+        super(x.kind(), x, y);
+        assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long);
+    }
+
+    @Override
+    public boolean inferStamp() {
+        // TODO Should probably use a specialised version which understands that it can't overflow
+        return updateStamp(StampTool.add(x().integerStamp(), y().integerStamp()));
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (x().isConstant() && !y().isConstant()) {
+            return graph().unique(new IntegerAddExactNode(y(), x()));
+        }
+        if (x().isConstant()) {
+            try {
+                if (kind() == Kind.Int) {
+                    return ConstantNode.forInt(ExactMath.addExact(x().asConstant().asInt(), y().asConstant().asInt()), graph());
+                } else {
+                    assert kind() == Kind.Long;
+                    return ConstantNode.forLong(ExactMath.addExact(x().asConstant().asLong(), y().asConstant().asLong()), graph());
+                }
+            } catch (ArithmeticException ex) {
+                // The operation will result in an overflow exception, so do not canonicalize.
+            }
+        } else if (y().isConstant()) {
+            long c = y().asConstant().asLong();
+            if (c == 0) {
+                return x();
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+        return graph().add(new IntegerAddExactSplitNode(stamp(), x(), y(), next, deopt));
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        IntegerExactArithmeticSplitNode.lower(tool, this);
+    }
+
+    @NodeIntrinsic
+    public static native int addExact(int a, int b);
+
+    @NodeIntrinsic
+    public static native long addExact(long a, long b);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactSplitNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode {
+
+    public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+        super(stamp, x, y, next, overflowSuccessor);
+    }
+
+    @Override
+    protected Value generateArithmetic(LIRGeneratorTool gen) {
+        return gen.emitAdd(gen.operand(getX()), gen.operand(getY()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+interface IntegerExactArithmeticNode extends Lowerable {
+
+    IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticSplitNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRGenLowerable {
+
+    @Successor private AbstractBeginNode overflowSuccessor;
+    @Successor private AbstractBeginNode next;
+    @Input private ValueNode x;
+    @Input private ValueNode y;
+
+    public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+        super(stamp);
+        this.x = x;
+        this.y = y;
+        this.overflowSuccessor = overflowSuccessor;
+        this.next = next;
+    }
+
+    @Override
+    public double probability(AbstractBeginNode successor) {
+        return successor == scheduledNext() ? 1 : 0;
+    }
+
+    @Override
+    public void setProbability(AbstractBeginNode successor, double value) {
+        assert probability(successor) == value;
+    }
+
+    public AbstractBeginNode getNext() {
+        return next;
+    }
+
+    public AbstractBeginNode getOverflowSuccessor() {
+        return overflowSuccessor;
+    }
+
+    public ValueNode getX() {
+        return x;
+    }
+
+    public ValueNode getY() {
+        return y;
+    }
+
+    @Override
+    public void generate(LIRGenerator generator) {
+        generator.setResult(this, generateArithmetic(generator));
+        generator.emitOverflowCheckBranch(generator.getLIRBlock(getNext()), generator.getLIRBlock(getOverflowSuccessor()));
+    }
+
+    protected abstract Value generateArithmetic(LIRGeneratorTool generator);
+
+    static void lower(LoweringTool tool, IntegerExactArithmeticNode node) {
+        FloatingNode floatingNode = (FloatingNode) node;
+        FixedWithNextNode previous = tool.lastFixedNode();
+        FixedNode next = previous.next();
+        previous.setNext(null);
+        DeoptimizeNode deopt = floatingNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException));
+        BeginNode normalBegin = floatingNode.graph().add(new BeginNode());
+        normalBegin.setNext(next);
+        IntegerExactArithmeticSplitNode split = node.createSplit(normalBegin, BeginNode.begin(deopt));
+        previous.setNext(split);
+        floatingNode.replaceAndDelete(split);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.truffle.api.*;
+
+/**
+ * Node representing an exact integer multiplication that will throw an {@link ArithmeticException}
+ * in case the addition would overflow the 32 bit range.
+ */
+public class IntegerMulExactNode extends IntegerMulNode implements Canonicalizable, IntegerExactArithmeticNode {
+
+    public IntegerMulExactNode(ValueNode x, ValueNode y) {
+        super(x.kind(), x, y);
+        assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long);
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (x().isConstant() && !y().isConstant()) {
+            return graph().unique(new IntegerMulExactNode(y(), x()));
+        }
+        if (x().isConstant()) {
+            try {
+                if (kind() == Kind.Int) {
+                    return ConstantNode.forInt(ExactMath.multiplyExact(x().asConstant().asInt(), y().asConstant().asInt()), graph());
+                } else {
+                    assert kind() == Kind.Long;
+                    return ConstantNode.forLong(ExactMath.multiplyExact(x().asConstant().asLong(), y().asConstant().asLong()), graph());
+                }
+            } catch (ArithmeticException ex) {
+                // The operation will result in an overflow exception, so do not canonicalize.
+            }
+        } else if (y().isConstant()) {
+            long c = y().asConstant().asLong();
+            if (c == 1) {
+                return x();
+            }
+            if (c == 0) {
+                return ConstantNode.defaultForKind(kind(), graph());
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+        return graph().add(new IntegerMulExactSplitNode(stamp(), x(), y(), next, deopt));
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        IntegerExactArithmeticSplitNode.lower(tool, this);
+    }
+
+    @NodeIntrinsic
+    public static native int multiplyExact(int a, int b);
+
+    @NodeIntrinsic
+    public static native long multiplyExact(long a, long b);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactSplitNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode {
+
+    public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+        super(stamp, x, y, next, overflowSuccessor);
+    }
+
+    @Override
+    protected Value generateArithmetic(LIRGeneratorTool gen) {
+        return gen.emitMul(gen.operand(getX()), gen.operand(getY()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.truffle.api.*;
+
+/**
+ * Node representing an exact integer substraction that will throw an {@link ArithmeticException} in
+ * case the addition would overflow the 32 bit range.
+ */
+public class IntegerSubExactNode extends IntegerSubNode implements Canonicalizable, IntegerExactArithmeticNode {
+
+    public IntegerSubExactNode(ValueNode x, ValueNode y) {
+        super(x.kind(), x, y);
+        assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long);
+    }
+
+    @Override
+    public boolean inferStamp() {
+        // TODO Should probably use a specialised version which understands that it can't overflow
+        return updateStamp(StampTool.sub(x().integerStamp(), y().integerStamp()));
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (x() == y()) {
+            return ConstantNode.forIntegerKind(kind(), 0, graph());
+        }
+        if (x().isConstant() && y().isConstant()) {
+            try {
+                if (kind() == Kind.Int) {
+                    return ConstantNode.forInt(ExactMath.subtractExact(x().asConstant().asInt(), y().asConstant().asInt()), graph());
+                } else {
+                    assert kind() == Kind.Long;
+                    return ConstantNode.forLong(ExactMath.subtractExact(x().asConstant().asLong(), y().asConstant().asLong()), graph());
+                }
+            } catch (ArithmeticException ex) {
+                // The operation will result in an overflow exception, so do not canonicalize.
+            }
+        } else if (y().isConstant()) {
+            long c = y().asConstant().asLong();
+            if (c == 0) {
+                return x();
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+        return graph().add(new IntegerSubExactSplitNode(stamp(), x(), y(), next, deopt));
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        IntegerExactArithmeticSplitNode.lower(tool, this);
+    }
+
+    @NodeIntrinsic
+    public static native int subtractExact(int a, int b);
+
+    @NodeIntrinsic
+    public static native long subtractExact(long a, long b);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactSplitNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode {
+
+    public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+        super(stamp, x, y, next, overflowSuccessor);
+    }
+
+    @Override
+    protected Value generateArithmetic(LIRGeneratorTool gen) {
+        return gen.emitSub(gen.operand(getX()), gen.operand(getY()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/MaterializeFrameNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.graph.Node.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.truffle.*;
+
+/**
+ * Intrinsic node for materializing a Truffle frame.
+ */
+@NodeInfo(nameTemplate = "MaterializeFrame{p#frame/s}")
+public class MaterializeFrameNode extends FixedWithNextNode implements IterableNodeType {
+
+    @Input private ValueNode frame;
+
+    public MaterializeFrameNode(ValueNode frame) {
+        super(frame.stamp());
+        this.frame = frame;
+    }
+
+    public ValueNode getFrame() {
+        return frame;
+    }
+
+    @NodeIntrinsic
+    public static native <T> T materialize(FrameWithoutBoxing frame);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverInlineMacroNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+public class NeverInlineMacroNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType {
+
+    public NeverInlineMacroNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        InvokeNode invoke = createInvoke();
+        graph().replaceFixedWithFixed(this, invoke);
+        invoke.setUseForInlining(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverPartOfCompilationNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+public class NeverPartOfCompilationNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType {
+
+    private final String message;
+
+    public NeverPartOfCompilationNode(Invoke invoke) {
+        this(invoke, "This code path should never be part of a compilation.");
+    }
+
+    public NeverPartOfCompilationNode(Invoke invoke, String message) {
+        super(invoke);
+        this.message = message;
+    }
+
+    public final String getMessage() {
+        return message;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NewFrameNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Intrinsic node representing the call for creating a frame in the {@link OptimizedCallTarget}
+ * class.
+ */
+public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable {
+
+    static final ResolvedJavaType FRAME_TYPE = Graal.getRequiredCapability(MetaAccessProvider.class).lookupJavaType(FrameWithoutBoxing.class);
+
+    @Input private ValueNode descriptor;
+    @Input private ValueNode caller;
+    @Input private ValueNode arguments;
+
+    public NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode caller, ValueNode arguments) {
+        super(stamp);
+        this.descriptor = descriptor;
+        this.caller = caller;
+        this.arguments = arguments;
+    }
+
+    public NewFrameNode(ValueNode descriptor, ValueNode caller, ValueNode arguments) {
+        this(StampFactory.declaredNonNull(FRAME_TYPE), descriptor, caller, arguments);
+    }
+
+    public ValueNode getDescriptor() {
+        return descriptor;
+    }
+
+    public ValueNode getCaller() {
+        return caller;
+    }
+
+    public ValueNode getArguments() {
+        return arguments;
+    }
+
+    private FrameDescriptor getConstantFrameDescriptor() {
+        assert descriptor.isConstant() && !descriptor.isNullConstant();
+        return (FrameDescriptor) descriptor.asConstant().asObject();
+    }
+
+    private int getFrameSize() {
+        return getConstantFrameDescriptor().getSize();
+    }
+
+    private static ResolvedJavaField findField(ResolvedJavaField[] fields, String fieldName) {
+        for (ResolvedJavaField field : fields) {
+            if (field.getName().equals(fieldName)) {
+                return field;
+            }
+        }
+        throw new RuntimeException("Frame field not found: " + fieldName);
+    }
+
+    public static class VirtualOnlyInstanceNode extends VirtualInstanceNode implements Node.IterableNodeType {
+
+        private boolean allowMaterialization;
+
+        public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
+            super(type, fields);
+        }
+
+        @Override
+        public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, int[] locks) {
+            if (allowMaterialization) {
+                return super.getMaterializedRepresentation(fixed, entries, locks);
+            }
+            return getMaterializedRepresentationHelper(this, fixed);
+        }
+
+        public void setAllowMaterialization(boolean b) {
+            this.allowMaterialization = b;
+        }
+    }
+
+    public static ValueNode getMaterializedRepresentationHelper(VirtualObjectNode virtualNode, FixedNode fixed) {
+        if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode) {
+            // We need to conservatively assume that a materialization of a virtual frame can also
+            // happen at a merge point.
+            return new AllocatedObjectNode(virtualNode);
+        }
+        String escapeReason;
+        if (fixed instanceof StoreFieldNode) {
+            escapeReason = "Must not store virtual frame object into a field.";
+        } else if (fixed instanceof Invoke) {
+            escapeReason = "Must not pass virtual frame object into an invoke that cannot be inlined.";
+        } else {
+            escapeReason = "Must not let virtual frame object escape at node " + fixed + ".";
+        }
+
+        Throwable exception = new GraalInternalError(escapeReason +
+                        " Insert a call to VirtualFrame.materialize() to convert the instance to a materialized frame object (source position of following stack trace is approximate)");
+        throw GraphUtil.approxSourceException(fixed, exception);
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        int frameSize = getFrameSize();
+
+        ResolvedJavaType frameType = stamp().javaType(tool.getMetaAccessProvider());
+        ResolvedJavaField[] frameFields = frameType.getInstanceFields(true);
+
+        ResolvedJavaField descriptorField = findField(frameFields, "descriptor");
+        ResolvedJavaField callerField = findField(frameFields, "caller");
+        ResolvedJavaField argumentsField = findField(frameFields, "arguments");
+        ResolvedJavaField localsField = findField(frameFields, "locals");
+        ResolvedJavaField primitiveLocalsField = findField(frameFields, "primitiveLocals");
+        ResolvedJavaField tagsField = findField(frameFields, "tags");
+
+        VirtualObjectNode virtualFrame = new VirtualOnlyInstanceNode(frameType, frameFields);
+        VirtualObjectNode virtualFrameObjectArray = new VirtualArrayNode((ResolvedJavaType) localsField.getType().getComponentType(), frameSize);
+        VirtualObjectNode virtualFramePrimitiveArray = new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize);
+        VirtualObjectNode virtualFrameTagArray = new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize);
+
+        ValueNode[] objectArrayEntryState = new ValueNode[frameSize];
+        ValueNode[] primitiveArrayEntryState = new ValueNode[frameSize];
+        ValueNode[] tagArrayEntryState = new ValueNode[frameSize];
+
+        if (frameSize > 0) {
+            FrameDescriptor frameDescriptor = getConstantFrameDescriptor();
+            ConstantNode objectDefault = ConstantNode.forObject(frameDescriptor.getTypeConversion().getDefaultValue(), tool.getMetaAccessProvider(), graph());
+            ConstantNode tagDefault = ConstantNode.forByte((byte) 0, graph());
+            for (int i = 0; i < frameSize; i++) {
+                objectArrayEntryState[i] = objectDefault;
+                primitiveArrayEntryState[i] = initialValue(frameDescriptor.getSlots().get(i).getKind());
+                tagArrayEntryState[i] = tagDefault;
+            }
+            tool.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion()));
+        }
+
+        tool.createVirtualObject(virtualFrameObjectArray, objectArrayEntryState, null);
+        tool.createVirtualObject(virtualFramePrimitiveArray, primitiveArrayEntryState, null);
+        tool.createVirtualObject(virtualFrameTagArray, tagArrayEntryState, null);
+
+        assert frameFields.length == 6;
+        ValueNode[] frameEntryState = new ValueNode[frameFields.length];
+        List<ResolvedJavaField> frameFieldList = Arrays.asList(frameFields);
+        frameEntryState[frameFieldList.indexOf(descriptorField)] = getDescriptor();
+        frameEntryState[frameFieldList.indexOf(callerField)] = getCaller();
+        frameEntryState[frameFieldList.indexOf(argumentsField)] = getArguments();
+        frameEntryState[frameFieldList.indexOf(localsField)] = virtualFrameObjectArray;
+        frameEntryState[frameFieldList.indexOf(primitiveLocalsField)] = virtualFramePrimitiveArray;
+        frameEntryState[frameFieldList.indexOf(tagsField)] = virtualFrameTagArray;
+        tool.createVirtualObject(virtualFrame, frameEntryState, null);
+        tool.replaceWithVirtual(virtualFrame);
+    }
+
+    private ValueNode initialValue(FrameSlotKind kind) {
+        Kind graalKind = Kind.Long;
+        switch (kind) {
+            case Int:
+                graalKind = Kind.Int;
+                break;
+            case Double:
+                graalKind = Kind.Double;
+                break;
+            case Float:
+                graalKind = Kind.Float;
+                break;
+            case Boolean:
+                graalKind = Kind.Boolean;
+                break;
+        }
+
+        return ConstantNode.defaultForKind(graalKind, graph());
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (usages().isEmpty()) {
+            return null;
+        } else {
+            return this;
+        }
+    }
+
+    @NodeIntrinsic
+    public static native FrameWithoutBoxing allocate(FrameDescriptor descriptor, PackedFrame caller, Arguments args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class UnsafeCastMacroNode extends NeverPartOfCompilationNode implements Canonicalizable {
+
+    public UnsafeCastMacroNode(Invoke invoke) {
+        super(invoke, "The class of the unsafe cast could not be reduced to a compile time constant.");
+        assert arguments.size() == 2;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (arguments.get(1).isConstant()) {
+            Class c = (Class) arguments.get(1).asConstant().asObject();
+            ResolvedJavaType lookupJavaType = tool.runtime().lookupJavaType(c);
+            Stamp s = StampFactory.declaredNonNull(lookupJavaType);
+            return graph().unique(new UnsafeCastNode(arguments.get(0), s));
+        }
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.phases;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
+import com.oracle.graal.truffle.*;
+
+/**
+ * Inline all trivial getters (i.e. simple field loads).
+ */
+public class InlineTrivialGettersPhase extends Phase {
+
+    private static final int TRIVIAL_GETTER_SIZE = 5;
+    private final MetaAccessProvider metaAccessProvider;
+    private final Assumptions assumptions;
+    private final CustomCanonicalizer customCanonicalizer;
+
+    public InlineTrivialGettersPhase(MetaAccessProvider metaAccessProvider, Assumptions assumptions, CustomCanonicalizer customCanonicalizer) {
+        this.metaAccessProvider = metaAccessProvider;
+        this.assumptions = assumptions;
+        this.customCanonicalizer = customCanonicalizer;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) {
+            if (methodCallTarget.isAlive()) {
+                InvokeKind invokeKind = methodCallTarget.invokeKind();
+                if (invokeKind == InvokeKind.Special) {
+                    ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod();
+                    if (methodCallTarget.receiver().isConstant() && !methodCallTarget.receiver().isNullConstant()) {
+                        if (targetMethod.getCodeSize() == TRIVIAL_GETTER_SIZE && targetMethod.getDeclaringClass().isInitialized() && targetMethod.getName().startsWith("get")) {
+                            StructuredGraph inlineGraph = new StructuredGraph(targetMethod);
+                            new GraphBuilderPhase(metaAccessProvider, GraphBuilderConfiguration.getDefault(), TruffleCompilerImpl.Optimizations).apply(inlineGraph);
+                            int mark = graph.getMark();
+                            InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, false);
+                            Debug.dump(graph, "After inlining trivial getter %s", targetMethod.toString());
+                            new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), mark, customCanonicalizer).apply(graph);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.phases;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+/**
+ * Compiler phase for intrinsifying the access to the Truffle virtual frame.
+ */
+public class ReplaceIntrinsicsPhase extends Phase {
+
+    private final Replacements replacements;
+
+    public ReplaceIntrinsicsPhase(Replacements replacements) {
+        this.replacements = replacements;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) {
+            if (methodCallTarget.isAlive()) {
+                InvokeKind invokeKind = methodCallTarget.invokeKind();
+                if (invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special) {
+                    StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTarget.targetMethod());
+                    if (inlineGraph != null) {
+                        InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, false);
+                        Debug.dump(graph, "After inlining %s", methodCallTarget.targetMethod().toString());
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.phases;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.truffle.nodes.*;
+
+/**
+ * Compiler phase for verifying that the Truffle virtual frame does not escape and can therefore be
+ * escape analyzed.
+ */
+public class VerifyFrameDoesNotEscapePhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        NewFrameNode frame = graph.getNodes(NewFrameNode.class).first();
+        if (frame != null) {
+            for (MethodCallTargetNode callTarget : frame.usages().filter(MethodCallTargetNode.class)) {
+                if (callTarget.invoke() != null) {
+                    Throwable exception = new VerificationError("Frame escapes at: %s#%s", callTarget, callTarget.targetMethod());
+                    throw GraphUtil.approxSourceException(callTarget, exception);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.phases;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.nodes.*;
+
+/**
+ * Verification phase for checking that no frame intrinsic nodes introduced by the
+ * {@link PartialEvaluator} are still in the graph.
+ */
+public class VerifyNoIntrinsicsLeftPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        verifyNoInstanceLeft(graph, NewFrameNode.class);
+    }
+
+    public static <T extends Node & IterableNodeType> void verifyNoInstanceLeft(StructuredGraph graph, Class<T> clazz) {
+        if (graph.getNodes(clazz).count() != 0) {
+            throw new VerificationError("Found unexpected node(s): %s", graph.getNodes(clazz));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.truffle.api.*;
+
+@ClassSubstitution(CompilerAsserts.class)
+public class CompilerAssertsSubstitutions {
+
+    @MacroSubstitution(macro = NeverPartOfCompilationNode.class, isStatic = true)
+    public static native void neverPartOfCompilation();
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native boolean compilationConstant(boolean value);
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native byte compilationConstant(byte value);
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native char compilationConstant(char value);
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native short compilationConstant(short value);
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native int compilationConstant(int value);
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native long compilationConstant(long value);
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native float compilationConstant(float value);
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native double compilationConstant(double value);
+
+    @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true)
+    public static native Object compilationConstant(Object value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.truffle.api.*;
+
+@ClassSubstitution(CompilerDirectives.class)
+public class CompilerDirectivesSubstitutions {
+
+    @MethodSubstitution
+    public static void transferToInterpreter() {
+        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
+    }
+
+    @MethodSubstitution
+    public static void interpreterOnly(@SuppressWarnings("unused") Runnable runnable) {
+    }
+
+    @MethodSubstitution
+    public static <T> T interpreterOnly(@SuppressWarnings("unused") Callable<T> callable) throws Exception {
+        return null;
+    }
+
+    @MethodSubstitution
+    public static boolean injectBranchProbability(double probability, boolean condition) {
+        return BranchProbabilityNode.probability(probability, condition);
+    }
+
+    @MacroSubstitution(macro = BailoutNode.class, isStatic = true)
+    public static native void bailout(String reason);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/DefaultCallTargetSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.impl.*;
+
+@ClassSubstitution(DefaultCallTarget.class)
+public class DefaultCallTargetSubstitutions {
+
+    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
+    public static native Object call(DefaultCallTarget target, PackedFrame caller, Arguments args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/ExactMathSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.truffle.api.*;
+
+/**
+ * Intrinsics for exact math operations that throw an exception in case the operation would overflow
+ * the allowed range.
+ */
+@ClassSubstitution(ExactMath.class)
+public class ExactMathSubstitutions {
+
+    @MethodSubstitution
+    public static int addExact(int x, int y) {
+        return IntegerAddExactNode.addExact(x, y);
+    }
+
+    @MethodSubstitution
+    public static long addExact(long x, long y) {
+        return IntegerAddExactNode.addExact(x, y);
+    }
+
+    @MethodSubstitution
+    public static int subtractExact(int x, int y) {
+        return IntegerSubExactNode.subtractExact(x, y);
+    }
+
+    @MethodSubstitution
+    public static long subtractExact(long x, long y) {
+        return IntegerSubExactNode.subtractExact(x, y);
+    }
+
+    @MethodSubstitution
+    public static int multiplyExact(int x, int y) {
+        return IntegerMulExactNode.multiplyExact(x, y);
+    }
+
+    @MethodSubstitution
+    public static long multiplyExact(long x, long y) {
+        return IntegerMulExactNode.multiplyExact(x, y);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.truffle.api.frame.*;
+
+@ClassSubstitution(FrameWithoutBoxing.class)
+public class FrameWithoutBoxingSubstitutions {
+
+    private static final ResolvedJavaField LOCALS_FIELD;
+    private static final ResolvedJavaField PRIMITIVELOCALS_FIELD;
+    private static final ResolvedJavaField TAGS_FIELD;
+
+    static {
+        try {
+            MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class);
+            LOCALS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("locals"));
+            PRIMITIVELOCALS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("primitiveLocals"));
+            TAGS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("tags"));
+        } catch (NoSuchFieldException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @MacroSubstitution(macro = UnsafeCastMacroNode.class, isStatic = true)
+    public static native Object unsafeCast(Object value, Class clazz);
+
+    @SuppressWarnings("unused")
+    @MethodSubstitution(isStatic = false)
+    public static Object pack(FrameWithoutBoxing frame) {
+        return null;
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static Object getObject(FrameWithoutBoxing frame, FrameSlot slot) {
+        verifyGet(frame, slot, FrameSlotKind.Object);
+        return getObjectUnsafe(frame, slot);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setObject(FrameWithoutBoxing frame, FrameSlot slot, Object value) {
+        verifySet(frame, slot, FrameSlotKind.Object);
+        setObjectUnsafe(frame, slot, value);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static boolean getBoolean(FrameWithoutBoxing frame, FrameSlot slot) {
+        verifyGet(frame, slot, FrameSlotKind.Boolean);
+        return getBooleanUnsafe(frame, slot);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setBoolean(FrameWithoutBoxing frame, FrameSlot slot, boolean value) {
+        verifySet(frame, slot, FrameSlotKind.Boolean);
+        setBooleanUnsafe(frame, slot, value);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static float getFloat(FrameWithoutBoxing frame, FrameSlot slot) {
+        verifyGet(frame, slot, FrameSlotKind.Float);
+        return getFloatUnsafe(frame, slot);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setFloat(FrameWithoutBoxing frame, FrameSlot slot, float value) {
+        verifySet(frame, slot, FrameSlotKind.Float);
+        setFloatUnsafe(frame, slot, value);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static long getLong(FrameWithoutBoxing frame, FrameSlot slot) {
+        verifyGet(frame, slot, FrameSlotKind.Long);
+        return getLongUnsafe(frame, slot);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setLong(FrameWithoutBoxing frame, FrameSlot slot, long value) {
+        verifySet(frame, slot, FrameSlotKind.Long);
+        setLongUnsafe(frame, slot, value);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static int getInt(FrameWithoutBoxing frame, FrameSlot slot) {
+        verifyGet(frame, slot, FrameSlotKind.Int);
+        return getIntUnsafe(frame, slot);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setInt(FrameWithoutBoxing frame, FrameSlot slot, int value) {
+        verifySet(frame, slot, FrameSlotKind.Int);
+        setIntUnsafe(frame, slot, value);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static double getDouble(FrameWithoutBoxing frame, FrameSlot slot) {
+        verifyGet(frame, slot, FrameSlotKind.Double);
+        return getDoubleUnsafe(frame, slot);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setDouble(FrameWithoutBoxing frame, FrameSlot slot, double value) {
+        verifySet(frame, slot, FrameSlotKind.Double);
+        setDoubleUnsafe(frame, slot, value);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static Object getObjectUnsafe(FrameWithoutBoxing frame, FrameSlot slot) {
+        return FrameGetNode.get(Kind.Object, frame, slot, LOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setObjectUnsafe(FrameWithoutBoxing frame, FrameSlot slot, Object value) {
+        FrameSetNode.set(Kind.Object, frame, slot, value, LOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static boolean getBooleanUnsafe(FrameWithoutBoxing frame, FrameSlot slot) {
+        return FrameGetNode.get(Kind.Boolean, frame, slot, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setBooleanUnsafe(FrameWithoutBoxing frame, FrameSlot slot, boolean value) {
+        FrameSetNode.set(Kind.Boolean, frame, slot, value, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static int getIntUnsafe(FrameWithoutBoxing frame, FrameSlot slot) {
+        return FrameGetNode.get(Kind.Int, frame, slot, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setIntUnsafe(FrameWithoutBoxing frame, FrameSlot slot, int value) {
+        FrameSetNode.set(Kind.Int, frame, slot, value, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static long getLongUnsafe(FrameWithoutBoxing frame, FrameSlot slot) {
+        return FrameGetNode.get(Kind.Long, frame, slot, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setLongUnsafe(FrameWithoutBoxing frame, FrameSlot slot, long value) {
+        FrameSetNode.set(Kind.Long, frame, slot, value, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static double getDoubleUnsafe(FrameWithoutBoxing frame, FrameSlot slot) {
+        return FrameGetNode.get(Kind.Double, frame, slot, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setDoubleUnsafe(FrameWithoutBoxing frame, FrameSlot slot, double value) {
+        FrameSetNode.set(Kind.Double, frame, slot, value, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static float getFloatUnsafe(FrameWithoutBoxing frame, FrameSlot slot) {
+        return FrameGetNode.get(Kind.Float, frame, slot, PRIMITIVELOCALS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void setFloatUnsafe(FrameWithoutBoxing frame, FrameSlot slot, float value) {
+        FrameSetNode.set(Kind.Float, frame, slot, value, PRIMITIVELOCALS_FIELD);
+    }
+
+    private static void verifySet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) {
+        setTag(frame, slot, (byte) accessType.ordinal());
+    }
+
+    private static void verifyGet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) {
+        if (getTag(frame, slot) != (byte) accessType.ordinal()) {
+            DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode);
+        }
+    }
+
+    private static byte getTag(FrameWithoutBoxing frame, FrameSlot slot) {
+        return FrameGetNode.get(Kind.Byte, frame, slot, TAGS_FIELD);
+    }
+
+    private static void setTag(FrameWithoutBoxing frame, FrameSlot slot, byte tag) {
+        FrameSetNode.set(Kind.Byte, frame, slot, tag, TAGS_FIELD);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static MaterializedFrame materialize(FrameWithoutBoxing frame) {
+        return MaterializeFrameNode.materialize(frame);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.nodes.*;
+
+@ClassSubstitution(OptimizedAssumption.class)
+public class OptimizedAssumptionSubstitutions {
+
+    @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true)
+    public static native void check(OptimizedAssumption assumption);
+
+    @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true)
+    public static native boolean isValid(OptimizedAssumption assumption);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+@ClassSubstitution(OptimizedCallTarget.class)
+public class OptimizedCallTargetSubstitutions {
+
+    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
+    public static native Object call(OptimizedCallTarget target, PackedFrame caller, Arguments args);
+
+    @MethodSubstitution
+    private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments args) {
+        return NewFrameNode.allocate(descriptor, caller, args);
+    }
+
+    @SuppressWarnings("unused")
+    @MethodSubstitution(isStatic = false)
+    private static VirtualFrame create(OptimizedCallTarget target, FrameDescriptor descriptor, PackedFrame caller, Arguments args) {
+        return createFrame(descriptor, caller, args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Deoptimize on creation of a new SlowPathException instance.
+ */
+@ClassSubstitution(SlowPathException.class)
+public class SlowPathExceptionSubstitutions {
+
+    @MethodSubstitution(value = "<init>")
+    public static void init() {
+        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
+    }
+
+    @SuppressWarnings("unused")
+    @MethodSubstitution(value = "<init>")
+    public static void init(String result, Throwable cause) {
+        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
+    }
+
+    @SuppressWarnings("unused")
+    @MethodSubstitution(value = "<init>")
+    public static void init(String result) {
+        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
+    }
+
+    @SuppressWarnings("unused")
+    @MethodSubstitution(value = "<init>")
+    public static void init(Throwable cause) {
+        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Deoptimize on creation of a new UnexpectedResultException instance.
+ */
+@ClassSubstitution(UnexpectedResultException.class)
+public class UnexpectedResultExceptionSubstitutions {
+
+    @SuppressWarnings("unused")
+    @MethodSubstitution(value = "<init>")
+    public static void init(Object result) {
+        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java	Sun Jun 23 21:44:15 2013 +0200
@@ -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.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+public interface FrameFactory {
+
+    VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java	Sun Jun 23 21:44:15 2013 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+public interface InlinableCallSite {
+
+    int getCallCount();
+
+    void resetCallCount();
+
+    Node getInlineTree();
+
+    boolean inline(FrameFactory factory);
+
+}
--- a/mx/projects	Sun Jun 23 21:36:00 2013 +0200
+++ b/mx/projects	Sun Jun 23 21:44:15 2013 +0200
@@ -25,7 +25,7 @@
 library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar
 
 distribution@GRAAL@path=graal.jar
-distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot
+distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.truffle,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot
 
 # graal.api.runtime
 project@com.oracle.graal.api.runtime@subDir=graal
@@ -404,7 +404,7 @@
 # graal.printer
 project@com.oracle.graal.printer@subDir=graal
 project@com.oracle.graal.printer@sourceDirs=src
-project@com.oracle.graal.printer@dependencies=com.oracle.graal.java,com.oracle.graal.compiler
+project@com.oracle.graal.printer@dependencies=com.oracle.graal.java.decompiler,com.oracle.graal.compiler
 project@com.oracle.graal.printer@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.printer@javaCompliance=1.7
 project@com.oracle.graal.printer@workingSets=Graal,Graph
@@ -539,5 +539,28 @@
 project@com.oracle.truffle.sl.test@javaCompliance=1.7
 project@com.oracle.truffle.sl.test@workingSets=Truffle,SimpleLanguage,Test
 
+# graal.truffle
+project@com.oracle.graal.truffle@subDir=graal
+project@com.oracle.graal.truffle@sourceDirs=src
+project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot
+project@com.oracle.graal.truffle@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.truffle@javaCompliance=1.7
+project@com.oracle.graal.truffle@workingSets=Graal,Truffle
+
+# graal.truffle.test
+project@com.oracle.graal.truffle.test@subDir=graal
+project@com.oracle.graal.truffle.test@sourceDirs=src
+project@com.oracle.graal.truffle.test@dependencies=com.oracle.graal.truffle,com.oracle.graal.compiler.test
+project@com.oracle.graal.truffle.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.truffle.test@javaCompliance=1.7
+project@com.oracle.graal.truffle.test@workingSets=Graal,Truffle,Test
+
+# graal.truffle.printer
+project@com.oracle.graal.truffle.printer@subDir=graal
+project@com.oracle.graal.truffle.printer@sourceDirs=src
+project@com.oracle.graal.truffle.printer@dependencies=com.oracle.graal.nodes
+project@com.oracle.graal.truffle.printer@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.truffle.printer@javaCompliance=1.7
+project@com.oracle.graal.truffle.printer@workingSets=Graal,Truffle