changeset 10505:5db21405c6a4

Merge
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Mon, 24 Jun 2013 10:25:41 +0200
parents 0eeb9f8dab9b (current diff) dcbdf71c4507 (diff)
children 329c22feda1f 0c144cdc1acb
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java
diffstat 122 files changed, 7275 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java	Mon Jun 24 10:25:41 2013 +0200
@@ -42,7 +42,7 @@
         Assert.assertTrue(nmethod.isValid());
         Object result;
         try {
-            result = nmethod.execute("a", "b", "c");
+            result = nmethod.execute(null, "b", "c");
             assertEquals(43, result);
         } catch (InvalidInstalledCodeException e) {
             Assert.fail("Code was invalidated");
@@ -59,6 +59,21 @@
     }
 
     @Test
+    public void testInstallCodeInvalidationWhileRunning() {
+        final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo"));
+        final StructuredGraph graph = parse("otherFoo");
+        final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, graph);
+        Object result;
+        try {
+            result = nmethod.execute(nmethod, null, null);
+            assertEquals(43, result);
+        } catch (InvalidInstalledCodeException e) {
+            Assert.fail("Code was invalidated");
+        }
+        Assert.assertFalse(nmethod.isValid());
+    }
+
+    @Test
     public void testInstalledCodeCalledFromCompiledCode() {
         final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo"));
         final StructuredGraph graph = parse("otherFoo");
@@ -66,7 +81,7 @@
         Assert.assertTrue(nmethod.isValid());
         try {
             for (int i = 0; i < ITERATION_COUNT; ++i) {
-                nmethod.execute("a", "b", "c");
+                nmethod.execute(null, "b", "c");
             }
         } catch (InvalidInstalledCodeException e) {
             Assert.fail("Code was invalidated");
@@ -74,12 +89,15 @@
     }
 
     @SuppressWarnings("unused")
-    public static Object foo(Object a1, Object a2, Object a3) {
+    public static Object foo(HotSpotNmethod method, Object a2, Object a3) {
         return 42;
     }
 
     @SuppressWarnings("unused")
-    public static Object otherFoo(Object a1, Object a2, Object a3) {
+    public static Object otherFoo(HotSpotNmethod method, Object a2, Object a3) {
+        if (method != null) {
+            method.invalidate();
+        }
         return 43;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Jun 24 10:25:41 2013 +0200
@@ -206,9 +206,9 @@
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
-    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nmethod) throws InvalidInstalledCodeException;
+    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
-    Object executeCompiledMethodVarargs(Object[] args, long nmethod) throws InvalidInstalledCodeException;
+    Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
     int getVtableEntryOffset(long metaspaceMethod);
 
@@ -229,7 +229,5 @@
      */
     void reprofile(long metaspaceMethod);
 
-    void invalidateInstalledCode(long nativeMethod);
-
-    boolean isInstalledCodeValid(long nativeMethod);
+    void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Jun 24 10:25:41 2013 +0200
@@ -143,7 +143,7 @@
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
     @Override
-    public native Object executeCompiledMethodVarargs(Object[] args, long nmethod);
+    public native Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode);
 
     @Override
     public native int getVtableEntryOffset(long metaspaceMethod);
@@ -170,14 +170,11 @@
     public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
 
     @Override
-    public native void invalidateInstalledCode(long nativeMethod);
+    public native void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
 
     @Override
-    public native boolean isInstalledCodeValid(long nativeMethod);
-
-    @Override
-    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nmethod) throws InvalidInstalledCodeException {
-        return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nmethod);
+    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
+        return executeCompiledMethodIntrinsic(arg1, arg2, arg3, hotspotInstalledCode);
     }
 
     /**
@@ -187,5 +184,5 @@
      * stub that does the necessary argument shuffling and a tail call via an indirect jump to the
      * verified entry point of the given native method.
      */
-    private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nmethod);
+    private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Mon Jun 24 10:25:41 2013 +0200
@@ -68,12 +68,12 @@
 
     @Override
     public boolean isValid() {
-        return graalRuntime().getCompilerToVM().isInstalledCodeValid(codeBlob);
+        return codeBlob != 0;
     }
 
     @Override
     public void invalidate() {
-        graalRuntime().getCompilerToVM().invalidateInstalledCode(codeBlob);
+        graalRuntime().getCompilerToVM().invalidateInstalledCode(this);
     }
 
     @Override
@@ -87,7 +87,7 @@
         assert method.getSignature().getParameterKind(0) == Kind.Object;
         assert method.getSignature().getParameterKind(1) == Kind.Object;
         assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object;
-        return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, codeBlob);
+        return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, this);
     }
 
     private boolean checkArgs(Object... args) {
@@ -107,7 +107,7 @@
     @Override
     public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
         assert checkArgs(args);
-        return graalRuntime().getCompilerToVM().executeCompiledMethodVarargs(args, codeBlob);
+        return graalRuntime().getCompilerToVM().executeCompiledMethodVarargs(args, this);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Jun 24 10:25:41 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
@@ -40,14 +41,20 @@
 
 public class WriteBarrierSnippets implements Snippets {
 
+    private static final SnippetCounter.Group countersWriteBarriers = SnippetCounters.getValue() ? new SnippetCounter.Group("WriteBarriers") : null;
+    private static final SnippetCounter serialFieldWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialFieldWriteBarrier", "Number of Serial Field Write Barriers");
+    private static final SnippetCounter serialArrayWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialArrayWriteBarrier", "Number of Serial Array Write Barriers");
+
     @Snippet
     public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) {
         Object object = FixedValueAnchorNode.getObject(obj);
         Pointer oop;
         if (usePrecise) {
             oop = Word.fromArray(object, location);
+            serialArrayWriteBarrierCounter.inc();
         } else {
             oop = Word.fromObject(object);
+            serialFieldWriteBarrierCounter.inc();
         }
         Word base = (Word) oop.unsignedShiftRight(cardTableShift());
         long startAddress = cardTableStart();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/BootstrapTest.java	Mon Jun 24 10:25:41 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.java.decompiler.test;
+
+public class BootstrapTest {
+
+    public static void main(String[] args) {
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java	Mon Jun 24 10:25:41 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.java.decompiler.test;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.java.decompiler.test.example.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.printer.*;
+
+public class Test {
+
+    /**
+     * @param args
+     * @throws SecurityException
+     * @throws NoSuchMethodException
+     */
+    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
+        DebugEnvironment.initialize(System.out);
+        GraalCodeCacheProvider runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class);
+        Method method = Example.class.getDeclaredMethod("loop7", new Class[]{int.class, int.class});
+        final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        TestUtil.compileMethod(javaMethod);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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.java.decompiler.test;
+
+import static com.oracle.graal.api.code.CodeUtil.*;
+
+import com.oracle.graal.api.code.*;
+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.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.*;
+
+public class TestUtil {
+
+    public static void compileMethod(ResolvedJavaMethod method) {
+        GraalCodeCacheProvider runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class);
+        Replacements replacements = Graal.getRequiredCapability(Replacements.class);
+        Suites suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
+        StructuredGraph graph = new StructuredGraph(method);
+        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+        PhasePlan phasePlan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        Backend backend = Graal.getRequiredCapability(Backend.class);
+        GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime.getTarget(), null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog(), suites);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/example/Example.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,200 @@
+/*
+ * 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.java.decompiler.test.example;
+
+public class Example {
+
+    static int if0(int a, int b) {
+        if (a > b) {
+            return a - b;
+        }
+        return 0;
+
+    }
+
+    static int if1(int a, int b) {
+        if (a > b) {
+            return a - b;
+        } else {
+            return a + b;
+        }
+    }
+
+    static int if2(int a, int b) {
+        int c;
+        if (a > b) {
+            c = 1;
+        } else {
+            c = 2;
+        }
+        return c;
+    }
+
+    static int if3(int a, int b) {
+        int c = 0;
+        int s = 3;
+        if (a > b) {
+            if (a == 4) {
+                c = 2 + b;
+            } else {
+                c = 4 + b;
+            }
+            s = a + b;
+        } else {
+            c = 2;
+            s = a - b;
+        }
+        return c + s;
+    }
+
+    static int if4(int a, @SuppressWarnings("unused") int b) {
+        if (a > 10) {
+            if (a > 100) {
+                if (a > 1000) {
+                    return 1;
+                }
+                return 2;
+            }
+            return 3;
+        }
+        return 4;
+    }
+
+    static int loop(int a, int b) {
+        int i = 0;
+        int s = 0;
+
+        while (i < a) {
+            s += b;
+            i++;
+        }
+        return s;
+    }
+
+    static int loop2(int a, int b) {
+        int i = 0;
+        int s = 0;
+
+        while (i < a) {
+            if (a > b) {
+                s += a;
+            } else {
+                s += b;
+            }
+            i++;
+        }
+        return s;
+    }
+
+    static int loop3(int a, int b) {
+        int i = 0;
+        int s = 0;
+
+        while (i < a) {
+            if (a > b) {
+                s += a;
+            } else {
+                s += b;
+            }
+            i++;
+        }
+        if (s > 1000) {
+            return -1;
+        } else {
+            return s;
+        }
+    }
+
+    static int loop4(int a, int b) {
+        int s = 0;
+
+        if (a < 1000) {
+            int i = 0;
+            while (i < 123) {
+                if (a > b) {
+                    s += a;
+                } else {
+                    s += b;
+                }
+                i = i + ret1(i);
+            }
+            return -1;
+        } else {
+            return s;
+        }
+    }
+
+    static int ret1(int i) {
+        if (i % 2 == 0) {
+            return 1;
+        } else {
+            return 3;
+        }
+    }
+
+    static int loop5(int a, int b) {
+        int i = 0;
+        int sum = 0;
+        while (i < 1000) {
+            if (a < b) {
+                sum = sum + a;
+            }
+            sum = sum + i;
+            if (sum < a) {
+                sum = sum + b;
+            }
+            i++;
+        }
+        if (sum < a + b) {
+            sum = sum * 2;
+        }
+        return sum;
+    }
+
+    static int loop6(int a, int b) {
+        int s = 0;
+        for (int i = 0; i < a; i++) {
+            s += b;
+        }
+        return s;
+    }
+
+    static int loop7(int a, int b) {
+        int s = 0;
+        for (int i = 0; i < a; i++) {
+            for (int j = 0; j < b; j++) {
+                if (a > 400) {
+                    for (int k = 0; k < a + b; k++) {
+                        s += if4(a, b);
+                    }
+                } else {
+                    for (int k = 0; k < a - b; k++) {
+                        s += b;
+                    }
+                }
+            }
+            s += b;
+        }
+        return s;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.java.decompiler;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.schedule.*;
+
+public class Decompiler {
+
+    private List<DecompilerBlock> blocks = new ArrayList<>();
+    private List<Block> cfgBlocks = new ArrayList<>();
+    private SchedulePhase schedule;
+    private ControlFlowGraph cfg;
+
+    private final PrintStream stream;
+    private final PrintStream infoStream;
+
+    private static final String IDENT = "  ";
+    private String curIdent = "";
+
+    public final String contexInformation;
+
+    public Decompiler(StructuredGraph graph, SchedulePhase schedulePhase, PrintStream stream, PrintStream infoPrintStream, String contextInformation) {
+        this.stream = stream;
+        this.infoStream = infoPrintStream;
+        this.contexInformation = contextInformation;
+        schedule = schedulePhase;
+        if (schedule == null) {
+            try {
+                schedule = new SchedulePhase();
+                schedule.apply(graph);
+            } catch (Throwable t) {
+            }
+        }
+
+        cfg = schedule.getCFG();
+    }
+
+    public void decompile() {
+
+        for (Block b : getCfg().getBlocks()) {
+            cfgBlocks.add(b);
+        }
+
+        for (int i = 0; i < getCfg().getBlocks().length - 1; i++) {
+            if (cfg.getBlocks()[i].getId() >= cfg.getBlocks()[i + 1].getId()) {
+                throw new AssertionError();
+            }
+        }
+
+        blocks = new DecompilerLoopSimplify(this, infoStream).apply(cfgBlocks);
+        blocks = new DecompilerIfSimplify(this, infoStream).apply(blocks);
+
+        DecompilerPhiRemover.apply(cfg, blocks);
+
+        printDebugOutput();
+    }
+
+    private void printDebugOutput() {
+        for (int i = 0; i < blocks.size(); i++) {
+            if (i < blocks.size() - 1) {
+                blocks.get(i).printBlock(stream, blocks.get(i + 1).getBlock());
+            } else {
+                blocks.get(i).printBlock(stream, null);
+            }
+        }
+    }
+
+    public List<DecompilerBlock> getBlocks() {
+        return blocks;
+    }
+
+    public void ident() {
+        curIdent += IDENT;
+    }
+
+    public void undent() {
+        curIdent = curIdent.substring(0, curIdent.length() - IDENT.length());
+    }
+
+    public String getIdent() {
+        return curIdent;
+    }
+
+    public List<Block> getCfgBlocks() {
+        return cfgBlocks;
+    }
+
+    public SchedulePhase getSchedule() {
+        return schedule;
+    }
+
+    public ControlFlowGraph getCfg() {
+        return cfg;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerIfSimplify.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,124 @@
+/*
+ * 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.java.decompiler;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.java.decompiler.lines.*;
+import com.oracle.graal.nodes.cfg.*;
+
+public class DecompilerIfSimplify {
+
+    private final Decompiler decompiler;
+    private final PrintStream infoStream;
+
+    public DecompilerIfSimplify(Decompiler decompiler, PrintStream infoStream) {
+        this.decompiler = decompiler;
+        this.infoStream = infoStream;
+    }
+
+    public List<DecompilerBlock> apply(List<DecompilerBlock> decompilerBlocks) {
+        return detectIfs(decompilerBlocks);
+    }
+
+    private List<DecompilerBlock> detectIfs(List<DecompilerBlock> decompilerBlocks) {
+        List<DecompilerBlock> blocks = new ArrayList<>();
+        while (!decompilerBlocks.isEmpty()) {
+            if (decompilerBlocks.get(0) instanceof DecompilerBasicBlock) {
+                DecompilerBasicBlock block = (DecompilerBasicBlock) decompilerBlocks.remove(0);
+                if (block.getSuccessorCount() <= 1) {
+                    blocks.add(block);
+                } else if (block.getSuccessorCount() == 2 && block.getCode().get(block.getCode().size() - 1) instanceof DecompilerIfLine) {
+                    Block firstThenBlock = block.getBlock().getSuccessors().get(0);
+                    Block firstElseBlock = block.getBlock().getSuccessors().get(1);
+                    List<DecompilerBlock> thenBlocks = getReachableDecompilerBlocks(firstThenBlock, decompilerBlocks);
+                    List<DecompilerBlock> elseBlocks = getReachableDecompilerBlocks(firstElseBlock, decompilerBlocks);
+                    removeIntersection(thenBlocks, elseBlocks);
+                    if (thenBlocks.size() == 0 && elseBlocks.size() == 0) {
+                        blocks.add(block);
+                    } else {
+                        for (DecompilerBlock b : thenBlocks) {
+                            decompilerBlocks.remove(b);
+                        }
+                        for (DecompilerBlock b : elseBlocks) {
+                            decompilerBlocks.remove(b);
+                        }
+                        // TODO(mg)
+                        // thenBlocks and elseBlocks can be both empty --> causes an AssertionError
+                        DecompilerIfBlock ifBlock = new DecompilerIfBlock(block.getBlock(), decompiler, thenBlocks, elseBlocks, infoStream);
+                        if (thenBlocks.contains(block.getBlock()) || elseBlocks.contains(block.getBlock())) {
+                            throw new AssertionError();
+                        }
+                        blocks.add(ifBlock);
+                        ifBlock.detectIfs();
+                    }
+                } else {
+                    blocks.add(block);
+                }
+            } else {
+                if (decompilerBlocks.get(0) instanceof DecompilerLoopBlock) {
+                    DecompilerLoopBlock loop = (DecompilerLoopBlock) decompilerBlocks.get(0);
+                    loop.detectIfs();
+                }
+                blocks.add(decompilerBlocks.remove(0));
+            }
+        }
+
+        return blocks;
+    }
+
+    private static List<DecompilerBlock> getReachableDecompilerBlocks(Block b, List<DecompilerBlock> decompilerBlocks) {
+        List<DecompilerBlock> result = new ArrayList<>();
+        for (DecompilerBlock block : decompilerBlocks) {
+            if (isReachable(b, block.getBlock(), new ArrayList<Block>())) {
+                result.add(block);
+            }
+        }
+        return result;
+    }
+
+    private static boolean isReachable(Block from, Block to, ArrayList<Block> visited) {
+        if (from == to) {
+            return true;
+        }
+        for (Block b : from.getSuccessors()) {
+            if (b != from && visited.contains(b) == false && b.getId() > from.getId()) {
+                visited.add(b);
+                if (isReachable(b, to, visited)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static void removeIntersection(List<DecompilerBlock> list1, List<DecompilerBlock> list2) {
+        List<DecompilerBlock> list1Copy = new ArrayList<>(list1);
+        List<DecompilerBlock> list2Copy = new ArrayList<>(list2);
+
+        list1.removeAll(list2Copy);
+        list2.removeAll(list1Copy);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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.java.decompiler;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.nodes.cfg.*;
+
+public class DecompilerLoopSimplify {
+
+    private final Decompiler decompiler;
+    private final PrintStream infoStream;
+
+    public DecompilerLoopSimplify(Decompiler decompiler, PrintStream infoStream) {
+        this.decompiler = decompiler;
+        this.infoStream = infoStream;
+    }
+
+    public List<DecompilerBlock> apply(List<Block> cfgBlocks) {
+        List<DecompilerBlock> blocks = new ArrayList<>();
+
+        while (!cfgBlocks.isEmpty()) {
+            Block firstBlock = cfgBlocks.get(0);
+            cfgBlocks.remove(0);
+            if (firstBlock.isLoopHeader()) {
+                DecompilerLoopBlock loopBlock = new DecompilerLoopBlock(firstBlock, decompiler, decompiler.getSchedule(), infoStream);
+                Loop loop = firstBlock.getLoop();
+
+                for (int i = 0; i < cfgBlocks.size(); i++) {
+                    if (loop.blocks.contains(cfgBlocks.get(i)) && cfgBlocks.get(i) != firstBlock) {
+                        loopBlock.addBodyBlock(cfgBlocks.get(i));
+                    }
+                }
+
+                // Asserting:
+                for (Block b : loopBlock.getBody()) {
+                    if (!loop.blocks.contains(b)) {
+                        throw new AssertionError();
+                    }
+                }
+                for (Block b : loop.blocks) {
+                    if (b != firstBlock && !loopBlock.getBody().contains(b)) {
+                        throw new AssertionError();
+                    }
+                }
+
+                for (Block b : loopBlock.getBody()) {
+                    cfgBlocks.remove(b);
+                }
+
+                blocks.add(loopBlock);
+                loopBlock.detectLoops();
+            } else {
+                DecompilerBasicBlock wrappedBlock = new DecompilerBasicBlock(firstBlock, decompiler, decompiler.getSchedule());
+                blocks.add(wrappedBlock);
+            }
+        }
+        return blocks;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerPhiRemover.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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.java.decompiler;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.java.decompiler.lines.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+
+public class DecompilerPhiRemover {
+
+    public static void apply(ControlFlowGraph cfg, List<DecompilerBlock> decompilerBlocks) {
+        List<DecompilerBasicBlock> blocks = collectAllBasicBlocks(decompilerBlocks);
+        for (DecompilerBasicBlock b : blocks) {
+            List<DecompilerSyntaxLine> removedLines = new ArrayList<>();
+            Map<DecompilerSyntaxLine, DecompilerBasicBlock> addedLines = new HashMap<>();
+            for (DecompilerSyntaxLine l : b.getCode()) {
+                if (l instanceof DecompilerPhiLine) {
+                    DecompilerPhiLine phi = (DecompilerPhiLine) l;
+                    removedLines.add(phi);
+                    PhiNode phiNode = (PhiNode) phi.getNode();
+                    for (int i = 0; i < phiNode.merge().phiPredecessorCount(); i++) {
+                        Node n = phiNode.merge().phiPredecessorAt(i);
+                        DecompilerBasicBlock targetBlock = getBlock(n, cfg, blocks);
+                        DecompilerPhiResolveLine assignment = new DecompilerPhiResolveLine(targetBlock, phiNode, n);
+                        addedLines.put(assignment, targetBlock);
+                    }
+                }
+            }
+            for (DecompilerSyntaxLine l : addedLines.keySet()) {
+                addAssignment(addedLines.get(l), l);
+            }
+            b.getCode().removeAll(removedLines);
+        }
+    }
+
+    private static List<DecompilerBasicBlock> collectAllBasicBlocks(List<DecompilerBlock> blocks) {
+        List<DecompilerBasicBlock> allBasicBlocks = new ArrayList<>();
+        for (DecompilerBlock b : blocks) {
+            allBasicBlocks.addAll(b.getAllBasicBlocks());
+        }
+        return allBasicBlocks;
+    }
+
+    private static DecompilerBasicBlock getBlock(Node n, ControlFlowGraph cfg, List<DecompilerBasicBlock> blocks) {
+        Block b = cfg.blockFor(n);
+        for (DecompilerBasicBlock basicBlock : blocks) {
+            if (basicBlock.getBlock() == b) {
+                return basicBlock;
+            }
+        }
+        throw new IllegalStateException("Block not found");
+    }
+
+    private static void addAssignment(DecompilerBasicBlock block, DecompilerSyntaxLine line) {
+        if (block.getCode().isEmpty()) {
+            block.getCode().add(line);
+            return;
+        }
+        DecompilerSyntaxLine lastLine = block.getCode().get(block.getCode().size() - 1);
+        if (lastLine instanceof DecompilerIfLine || lastLine instanceof DecompilerControlSplitLine) {
+            block.getCode().remove(lastLine);
+            block.getCode().add(line);
+            block.getCode().add(lastLine);
+        } else {
+            block.getCode().add(line);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBasicBlock.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,81 @@
+/*
+ * 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.java.decompiler.block;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.java.decompiler.*;
+import com.oracle.graal.java.decompiler.lines.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.schedule.*;
+
+public class DecompilerBasicBlock extends DecompilerBlock {
+
+    public DecompilerBasicBlock(Block block, Decompiler decompiler, SchedulePhase schedule) {
+        super(block, decompiler);
+        initCode(schedule);
+    }
+
+    @Override
+    public void printBlock(PrintStream stream, Block codeSuccessor) {
+        stream.println(decompiler.getIdent() + block);
+        for (DecompilerSyntaxLine l : code) {
+            if (l != null) {
+                String line = l.getAsString();
+                stream.println(decompiler.getIdent() + line);
+            }
+        }
+        if (!(block.getSuccessorCount() == 0 || (block.getSuccessorCount() == 1 && block.getFirstSuccessor() == codeSuccessor))) {
+            stream.println(decompiler.getIdent() + "GOTO " + Arrays.toString(block.getSuccessors().toArray()));
+        }
+    }
+
+    @Override
+    public String toString() {
+        return block.toString();
+    }
+
+    @Override
+    public int getSuccessorCount() {
+        return block.getSuccessorCount();
+    }
+
+    public List<Block> getSuccessors() {
+        return block.getSuccessors();
+    }
+
+    @Override
+    public boolean contains(Block b) {
+        return b == block;
+    }
+
+    public List<DecompilerSyntaxLine> getCode() {
+        return code;
+    }
+
+    @Override
+    public List<DecompilerBasicBlock> getAllBasicBlocks() {
+        return Arrays.asList(new DecompilerBasicBlock[]{this});
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBlock.java	Mon Jun 24 10:25:41 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.java.decompiler.block;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.java.decompiler.*;
+import com.oracle.graal.java.decompiler.lines.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.schedule.*;
+
+public abstract class DecompilerBlock {
+
+    protected final Block block;
+    protected final Decompiler decompiler;
+    protected final List<DecompilerSyntaxLine> code;
+
+    public DecompilerBlock(Block block, Decompiler decompiler) {
+        this.block = block;
+        this.decompiler = decompiler;
+        this.code = new ArrayList<>();
+    }
+
+    public Block getBlock() {
+        return block;
+    }
+
+    public abstract void printBlock(PrintStream stream, Block codeSuccessor);
+
+    public final int getPredecessorCount() {
+        return block.getPredecessorCount();
+    }
+
+    public abstract int getSuccessorCount();
+
+    public abstract boolean contains(Block b);
+
+    public abstract List<DecompilerBasicBlock> getAllBasicBlocks();
+
+    @Override
+    public abstract String toString();
+
+    protected void initCode(SchedulePhase schedule) {
+        List<ScheduledNode> instructions = schedule.nodesFor(block);
+        for (ScheduledNode n : instructions) {
+            if (n instanceof MergeNode) {
+                MergeNode merge = (MergeNode) n;
+                for (PhiNode phi : merge.phis()) {
+                    addLine(new DecompilerPhiLine(this, phi));
+                }
+            } else if (n instanceof StartNode || n instanceof BeginNode || n instanceof EndNode || n instanceof LoopEndNode || n instanceof LoopExitNode) {
+                // do nothing
+            } else if (n instanceof ConstantNode) {
+                // do nothing
+            } else if (n instanceof IfNode) {
+                assert n.inputs().count() == 1;
+                addLine(new DecompilerIfLine(this, n, ((IfNode) n).condition()));
+            } else if (n instanceof ReturnNode) {
+                addLine(new DecompilerReturnLine(this, n.inputs().first()));
+            } else if (n instanceof ControlSplitNode) {
+                addLine(new DecompilerControlSplitLine(this, n));
+            } else if (n instanceof ProxyNode) {
+                ProxyNode proxy = (ProxyNode) n;
+                addLine(new DecompilerProxyLine(this, proxy, proxy.value()));
+            } else if (n instanceof ValueNode) {
+                addLine(new DecompilerAssignmentLine(this, n));
+            } else {
+                throw new IllegalStateException(n.toString(Verbosity.All) + " " + n.getClass());
+            }
+        }
+        simplifyCode();
+    }
+
+    private void simplifyCode() {
+        for (int i = 0; i < code.size(); i++) {
+            if (code.get(i) instanceof DecompilerAssignmentLine) {
+                if (i + 1 < code.size()) {
+                    if (code.get(i + 1) instanceof DecompilerIfLine) {
+                        if (code.get(i).getNode().usages().count() == 1) {
+                            if (((DecompilerIfLine) code.get(i + 1)).getCondition() == code.get(i).getNode()) {
+                                ((DecompilerIfLine) code.get(i + 1)).setMergedCondition((DecompilerAssignmentLine) code.get(i));
+                                code.set(i, null);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    protected void addLine(DecompilerSyntaxLine line) {
+        code.add(line);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerIfBlock.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,177 @@
+/*
+ * 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.java.decompiler.block;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.java.decompiler.*;
+import com.oracle.graal.java.decompiler.lines.*;
+import com.oracle.graal.nodes.cfg.*;
+
+public class DecompilerIfBlock extends DecompilerBlock {
+
+    private List<DecompilerBlock> thenBranch;
+    private List<DecompilerBlock> elseBranch;
+    private final DecompilerBasicBlock head;
+    private final PrintStream infoStream;
+
+    public DecompilerIfBlock(Block block, Decompiler decompiler, List<DecompilerBlock> thenBranch, List<DecompilerBlock> elseBranch, PrintStream infoStream) {
+        super(block, decompiler);
+        this.thenBranch = thenBranch;
+        this.elseBranch = elseBranch;
+        this.infoStream = infoStream;
+        this.head = new DecompilerBasicBlock(block, decompiler, decompiler.getSchedule());
+
+        if (!(thenBranch.isEmpty() == false && head.getBlock().getSuccessors().contains(thenBranch.get(0).getBlock()) || (elseBranch.isEmpty() == false && head.getBlock().getSuccessors().contains(
+                        elseBranch.get(0).getBlock())))) {
+            // first block of then / else MUST be a successor of the head!
+            throw new AssertionError(decompiler.contexInformation);
+        }
+    }
+
+    @Override
+    public void printBlock(PrintStream stream, Block codeSuccessor) {
+        List<DecompilerSyntaxLine> lines = head.getCode();
+        for (int i = 0; i < lines.size() - 1; i++) {
+            if (lines.get(i) != null) {
+                String line = lines.get(i).getAsString();
+                stream.println(decompiler.getIdent() + line);
+            }
+        }
+        DecompilerIfLine ifLine = (DecompilerIfLine) lines.get(lines.size() - 1);
+        if (!thenBranch.isEmpty() && block.getSuccessors().contains(thenBranch.get(0).getBlock())) {
+            if (elseBranch.isEmpty()) {
+                // while break:
+                stream.println(decompiler.getIdent() + ifLine.getIfNegStatement());
+                decompiler.ident();
+                stream.println(decompiler.getIdent() + "BREAK TO " + block.getSuccessors().get(1));
+                decompiler.undent();
+                for (int i = 0; i < thenBranch.size(); i++) {
+                    if (i < thenBranch.size() - 1) {
+                        thenBranch.get(i).printBlock(stream, thenBranch.get(i + 1).getBlock());
+                    } else {
+                        thenBranch.get(i).printBlock(stream, codeSuccessor);
+                    }
+                }
+            } else {
+                stream.println(decompiler.getIdent() + ifLine.getIfStatement() + " {");
+                decompiler.ident();
+                for (int i = 0; i < thenBranch.size(); i++) {
+                    if (i < thenBranch.size() - 1) {
+                        thenBranch.get(i).printBlock(stream, thenBranch.get(i + 1).getBlock());
+                    } else {
+                        thenBranch.get(i).printBlock(stream, codeSuccessor);
+                    }
+                }
+                decompiler.undent();
+                stream.println(decompiler.getIdent() + "} ELSE {");
+                decompiler.ident();
+                for (int i = 0; i < elseBranch.size(); i++) {
+                    if (i < elseBranch.size() - 1) {
+                        elseBranch.get(i).printBlock(stream, elseBranch.get(i + 1).getBlock());
+                    } else {
+                        elseBranch.get(i).printBlock(stream, codeSuccessor);
+                    }
+                }
+                decompiler.undent();
+                stream.println(decompiler.getIdent() + "}");
+            }
+        } else if (!elseBranch.isEmpty() && block.getSuccessors().contains(elseBranch.get(0).getBlock())) {
+            if (thenBranch.isEmpty()) {
+                // while break:
+                stream.println(decompiler.getIdent() + ifLine.getIfStatement());
+                decompiler.ident();
+                stream.println(decompiler.getIdent() + "BREAK TO " + block.getSuccessors().get(0));
+                decompiler.undent();
+                for (int i = 0; i < elseBranch.size(); i++) {
+                    if (i < elseBranch.size() - 1) {
+                        elseBranch.get(i).printBlock(stream, elseBranch.get(i + 1).getBlock());
+                    } else {
+                        elseBranch.get(i).printBlock(stream, codeSuccessor);
+                    }
+                }
+            } else {
+                stream.println(decompiler.getIdent() + ifLine.getIfNegStatement() + " {");
+                decompiler.ident();
+                for (int i = 0; i < elseBranch.size(); i++) {
+                    if (i < elseBranch.size() - 1) {
+                        elseBranch.get(i).printBlock(stream, elseBranch.get(i + 1).getBlock());
+                    } else {
+                        elseBranch.get(i).printBlock(stream, codeSuccessor);
+                    }
+                }
+                decompiler.undent();
+                stream.println(decompiler.getIdent() + "} ELSE {");
+                decompiler.ident();
+
+                for (int i = 0; i < thenBranch.size(); i++) {
+                    if (i < thenBranch.size() - 1) {
+                        thenBranch.get(i).printBlock(stream, thenBranch.get(i + 1).getBlock());
+                    } else {
+                        thenBranch.get(i).printBlock(stream, codeSuccessor);
+                    }
+                }
+
+                decompiler.undent();
+                stream.println(decompiler.getIdent() + "}");
+            }
+        } else {
+            throw new AssertionError();
+        }
+    }
+
+    public void detectIfs() {
+        thenBranch = new DecompilerIfSimplify(decompiler, infoStream).apply(thenBranch);
+        elseBranch = new DecompilerIfSimplify(decompiler, infoStream).apply(elseBranch);
+    }
+
+    @Override
+    public int getSuccessorCount() {
+        return 1;
+    }
+
+    @Override
+    public String toString() {
+        return "IF" + block.toString();
+    }
+
+    @Override
+    public boolean contains(Block b) {
+        return b == block || thenBranch.contains(b) || elseBranch.contains(b);
+    }
+
+    @Override
+    public List<DecompilerBasicBlock> getAllBasicBlocks() {
+        List<DecompilerBasicBlock> blocks = new ArrayList<>();
+        blocks.add(head);
+        for (DecompilerBlock b : thenBranch) {
+            blocks.addAll(b.getAllBasicBlocks());
+        }
+        for (DecompilerBlock b : elseBranch) {
+            blocks.addAll(b.getAllBasicBlocks());
+        }
+        return blocks;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerLoopBlock.java	Mon Jun 24 10:25:41 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.java.decompiler.block;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.java.decompiler.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.schedule.*;
+
+public class DecompilerLoopBlock extends DecompilerBlock {
+
+    private final List<Block> body;
+    private List<DecompilerBlock> decompilerBlockBody;
+    private final PrintStream infoStream;
+
+    public DecompilerLoopBlock(Block block, Decompiler decompiler, SchedulePhase schedule, PrintStream infoStream) {
+        super(block, decompiler);
+        this.infoStream = infoStream;
+        this.body = new ArrayList<>();
+        decompilerBlockBody = new ArrayList<>();
+        decompilerBlockBody.add(new DecompilerBasicBlock(block, decompiler, schedule));
+    }
+
+    public void addBodyBlock(Block bodyBlock) {
+        body.add(bodyBlock);
+    }
+
+    public List<Block> getBody() {
+        return body;
+    }
+
+    public void detectLoops() {
+        decompilerBlockBody.addAll(new DecompilerLoopSimplify(decompiler, infoStream).apply(body));
+    }
+
+    public void detectIfs() {
+        decompilerBlockBody = new DecompilerIfSimplify(decompiler, infoStream).apply(decompilerBlockBody);
+    }
+
+    @Override
+    public void printBlock(PrintStream stream, Block codeSuccessor) {
+        stream.println(decompiler.getIdent() + block);
+        stream.println(decompiler.getIdent() + "while {");
+        decompiler.ident();
+        for (int i = 0; i < decompilerBlockBody.size(); i++) {
+            if (i < decompilerBlockBody.size() - 1) {
+                decompilerBlockBody.get(i).printBlock(stream, decompilerBlockBody.get(i + 1).getBlock());
+            } else {
+                decompilerBlockBody.get(i).printBlock(stream, block);
+            }
+        }
+        decompiler.undent();
+        stream.println(decompiler.getIdent() + "}");
+    }
+
+    @Override
+    public String toString() {
+        return "LOOP " + block.toString();
+    }
+
+    @Override
+    public int getSuccessorCount() {
+        return block.getLoop().exits.size();
+    }
+
+    @Override
+    public boolean contains(Block b) {
+        if (b == block) {
+            return true;
+        }
+        for (Block bodyBlock : body) {
+            if (bodyBlock == b) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public List<DecompilerBasicBlock> getAllBasicBlocks() {
+        List<DecompilerBasicBlock> blocks = new ArrayList<>();
+        for (DecompilerBlock b : decompilerBlockBody) {
+            blocks.addAll(b.getAllBasicBlocks());
+        }
+        return blocks;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerAssignmentLine.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.java.decompiler.lines;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.nodes.*;
+
+public class DecompilerAssignmentLine extends DecompilerSyntaxLine {
+
+    private final NodeClassIterable inputs;
+
+    public DecompilerAssignmentLine(DecompilerBlock block, Node node) {
+        super(block, node);
+        this.inputs = node.inputs();
+    }
+
+    @Override
+    public String getAsString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getStringRepresentation(node));
+        sb.append(" = ");
+        sb.append(getStatement());
+        return sb.toString();
+    }
+
+    public String getStatement() {
+        StringBuilder sb = new StringBuilder();
+        if (node instanceof CallTargetNode) {
+            CallTargetNode callTarget = (CallTargetNode) node;
+            sb.append(callTarget.targetName());
+        } else {
+            sb.append(node.toString(Verbosity.Name));
+            sb.append(" ");
+            for (Node n : inputs) {
+                sb.append(getStringRepresentation(n));
+                sb.append(", ");
+            }
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerControlSplitLine.java	Mon Jun 24 10:25:41 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.java.decompiler.lines;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.nodes.cfg.*;
+
+public class DecompilerControlSplitLine extends DecompilerSyntaxLine {
+
+    public DecompilerControlSplitLine(DecompilerBlock block, Node node) {
+        super(block, node);
+    }
+
+    @Override
+    public String getAsString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(node.toString(Verbosity.Name));
+        sb.append(": ");
+        for (Block b : block.getBlock().getSuccessors()) {
+            sb.append(b);
+            sb.append(" ");
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerIfLine.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.java.decompiler.lines;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.decompiler.block.*;
+
+public class DecompilerIfLine extends DecompilerSyntaxLine {
+
+    private final Node condition;
+    private DecompilerAssignmentLine mergedCondition;
+
+    public DecompilerIfLine(DecompilerBlock block, Node node, Node condition) {
+        super(block, node);
+        this.condition = condition;
+    }
+
+    public void setMergedCondition(DecompilerAssignmentLine mergedCondition) {
+        this.mergedCondition = mergedCondition;
+    }
+
+    @Override
+    public String getAsString() {
+        if (mergedCondition == null) {
+            return "IF (" + getStringRepresentation(condition) + ") " + block.getBlock().getSuccessors().get(0) + ":" + block.getBlock().getSuccessors().get(1);
+        } else {
+            return "IF (" + mergedCondition.getStatement() + ") " + block.getBlock().getSuccessors().get(0) + ":" + block.getBlock().getSuccessors().get(1);
+        }
+    }
+
+    public String getIfStatement() {
+        if (mergedCondition == null) {
+            return "IF (" + getStringRepresentation(condition) + ")";
+        } else {
+            return "IF (" + mergedCondition.getStatement() + ")";
+        }
+
+    }
+
+    public String getIfNegStatement() {
+        if (mergedCondition == null) {
+            return "IF (!(" + getStringRepresentation(condition) + "))";
+        } else {
+            return "IF (!(" + mergedCondition.getStatement() + "))";
+        }
+    }
+
+    public Node getCondition() {
+        return condition;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerPhiLine.java	Mon Jun 24 10:25:41 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.java.decompiler.lines;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.nodes.*;
+
+public class DecompilerPhiLine extends DecompilerSyntaxLine {
+
+    public DecompilerPhiLine(DecompilerBlock block, Node node) {
+        super(block, node);
+    }
+
+    @Override
+    public String getAsString() {
+        PhiNode phi = (PhiNode) node;
+        StringBuilder sb = new StringBuilder();
+        sb.append(getStringRepresentation(phi));
+        sb.append(" = Phi {");
+        for (Node n : phi.values()) {
+            sb.append(getStringRepresentation(n));
+            sb.append(",");
+        }
+        sb.append("}");
+
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerPhiResolveLine.java	Mon Jun 24 10:25:41 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.java.decompiler.lines;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.decompiler.block.*;
+
+public class DecompilerPhiResolveLine extends DecompilerSyntaxLine {
+
+    private final Node value;
+
+    public DecompilerPhiResolveLine(DecompilerBlock block, Node node, Node value) {
+        super(block, node);
+        this.value = value;
+    }
+
+    @Override
+    public String getAsString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getStringRepresentation(node));
+        sb.append(" = ");
+        sb.append(getStringRepresentation(value));
+        return sb.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerProxyLine.java	Mon Jun 24 10:25:41 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.java.decompiler.lines;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.decompiler.block.*;
+
+public class DecompilerProxyLine extends DecompilerSyntaxLine {
+
+    private final Node proxy;
+
+    public DecompilerProxyLine(DecompilerBlock block, Node node, Node proxy) {
+        super(block, node);
+        this.proxy = proxy;
+    }
+
+    @Override
+    public String getAsString() {
+        return getVariable(node) + " = " + getStringRepresentation(proxy);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerReturnLine.java	Mon Jun 24 10:25:41 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.java.decompiler.lines;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.decompiler.block.*;
+
+public class DecompilerReturnLine extends DecompilerSyntaxLine {
+
+    public DecompilerReturnLine(DecompilerBlock block, Node node) {
+        super(block, node);
+    }
+
+    @Override
+    public String getAsString() {
+        return "return " + getStringRepresentation(node);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerSyntaxLine.java	Mon Jun 24 10:25:41 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.java.decompiler.lines;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.nodes.*;
+
+public abstract class DecompilerSyntaxLine {
+
+    protected final Node node;
+    protected final DecompilerBlock block;
+
+    protected DecompilerSyntaxLine(DecompilerBlock block, Node node) {
+        this.node = node;
+        this.block = block;
+    }
+
+    public Node getNode() {
+        return node;
+    }
+
+    public abstract String getAsString();
+
+    public DecompilerBlock getBlock() {
+        return block;
+    }
+
+    protected static String getStringRepresentation(Node node) {
+        if (node instanceof ConstantNode) {
+            return String.valueOf(((ConstantNode) node).asConstant().asBoxedValue());
+        } else if (node instanceof LocalNode) {
+            return "local_" + ((LocalNode) node).index();
+        } else {
+            return getVariable(node);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    protected static String getVariable(Node node) {
+        if (node != null) {
+            return "var_" + node.getId();
+        } else {
+            return "null";
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Mon Jun 24 10:25:41 2013 +0200
@@ -34,12 +34,10 @@
 
     private static final long serialVersionUID = -3583286416638228207L;
 
-    @Component({ REG, OperandFlag.ILLEGAL })
-    protected AllocatableValue base;
+    @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue base;
     protected final int displacement;
 
-    public SPARCAddressValue(PlatformKind kind, AllocatableValue baseRegister,
-            int finalDisp) {
+    public SPARCAddressValue(PlatformKind kind, AllocatableValue baseRegister, int finalDisp) {
         super(kind);
         this.base = baseRegister;
         this.displacement = finalDisp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Mon Jun 24 10:25:41 2013 +0200
@@ -30,13 +30,15 @@
  */
 public abstract class FixedWithNextNode extends FixedNode {
 
+    @Successor private FixedNode next;
+
     public FixedNode next() {
-        assert scheduledNext() == null || scheduledNext() instanceof FixedNode : "next() cannot be used while the graph is scheduled";
-        return (FixedNode) scheduledNext();
+        return next;
     }
 
     public void setNext(FixedNode x) {
-        setScheduledNext(x);
+        updatePredecessor(next, x);
+        next = x;
     }
 
     public FixedWithNextNode(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Mon Jun 24 10:25:41 2013 +0200
@@ -26,17 +26,6 @@
 
 public abstract class ScheduledNode extends Node {
 
-    @Successor private ScheduledNode scheduledNext; // the immediate successor of the current node
-
-    public ScheduledNode scheduledNext() {
-        return scheduledNext;
-    }
-
-    public void setScheduledNext(ScheduledNode x) {
-        updatePredecessor(scheduledNext, x);
-        scheduledNext = x;
-    }
-
     @Override
     public StructuredGraph graph() {
         return (StructuredGraph) super.graph();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Mon Jun 24 10:25:41 2013 +0200
@@ -131,13 +131,14 @@
         IntegerStamp other = (IntegerStamp) otherStamp;
         if (lowerBound > other.upperBound || upperBound < other.lowerBound) {
             return true;
-        } else {
-            if ((mask & other.mask) == 0) {
-                // zero is the only common value if the masks don't overlap => check for non-zero
-                return lowerBound > 0 || upperBound < 0 || other.lowerBound > 0 || other.upperBound < 0;
-            }
-            return false;
+        } else if ((mask & other.mask) == 0 && (lowerBound > 0 || upperBound < 0 || other.lowerBound > 0 || other.upperBound < 0)) {
+            /*
+             * Zero is the only common value if the masks don't overlap. If one of the two values is
+             * less than or greater than zero, they are always distinct.
+             */
+            return true;
         }
+        return false;
     }
 
     @Override
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Jun 24 10:25:41 2013 +0200
@@ -183,6 +183,8 @@
     public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
     @Option(help = "")
     public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
+    @Option(help = "Sets a phase after which the decompiler dumps the graph, -G:Dump= required")
+    public static final OptionValue<String> DecompileAfterPhase = new OptionValue<>(null);
 
     // HotSpot command line options
     @Option(help = "")
@@ -308,6 +310,7 @@
     public static final OptionValue<Boolean> IntrinsifyInstalledCodeMethods = new OptionValue<>(true);
     @Option(help = "")
     public static final OptionValue<Boolean> IntrinsifyCallSiteTarget = new OptionValue<>(true);
+
     /**
      * Counts the various paths taken through snippets.
      */
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Jun 24 10:25:41 2013 +0200
@@ -209,25 +209,6 @@
         sortNodesWithinBlocks(graph, selectedStrategy);
     }
 
-    /**
-     * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the
-     * scheduling built by {@link #run(StructuredGraph)}. This method should thus only be called
-     * when run has been successfully executed.
-     */
-    public void scheduleGraph() {
-        assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed";
-        for (Block block : cfg.getBlocks()) {
-            List<ScheduledNode> nodeList = blockToNodesMap.get(block);
-            ScheduledNode last = null;
-            for (ScheduledNode node : nodeList) {
-                if (last != null) {
-                    last.setScheduledNext(node);
-                }
-                last = node;
-            }
-        }
-    }
-
     public ControlFlowGraph getCFG() {
         return cfg;
     }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Mon Jun 24 10:25:41 2013 +0200
@@ -43,6 +43,9 @@
             }
             dumpHandlers.add(new CFGPrinterObserver());
         }
+        if (DecompileAfterPhase.getValue() != null) {
+            dumpHandlers.add(new DecompilerDebugDumpHandler());
+        }
         GraalDebugConfig hotspotDebugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), Time.getValue(), Dump.getValue(), MethodFilter.getValue(), log, dumpHandlers);
         Debug.setConfig(hotspotDebugConfig);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.printer;
+
+import java.io.*;
+import java.util.concurrent.atomic.*;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.java.decompiler.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.schedule.*;
+
+public class DecompilerDebugDumpHandler implements DebugDumpHandler {
+
+    private final PrintStream infoPrintStream = System.out;
+    private File file;
+    private FileOutputStream fos;
+    private PrintStream printStream;
+    private String fileName;
+    private static final AtomicInteger uniqueId = new AtomicInteger();
+
+    @Override
+    public void dump(Object object, final String message) {
+        if (object instanceof StructuredGraph) {
+            if (Debug.currentScope().contains("LowTier")) {
+                // no decompilation after high / mid tier
+                return;
+            }
+            final StructuredGraph graph = (StructuredGraph) object;
+            String filter = DecompileAfterPhase.getValue();
+            if (filter.endsWith("Phase")) {
+                filter = filter.substring(0, filter.indexOf("Phase"));
+            }
+
+            if (printStream == null) {
+                fileName = "decompilerDump_" + uniqueId.incrementAndGet() + "_" + System.currentTimeMillis() + ".txt";
+                file = new File(fileName);
+                try {
+                    fos = new FileOutputStream(file, true);
+                } catch (FileNotFoundException e) {
+                    throw new IllegalStateException(e);
+                }
+                printStream = new PrintStream(fos);
+                infoPrintStream.println("Dump Decompiler Output to " + file.getAbsolutePath());
+            }
+
+            final String currentScope = Debug.currentScope();
+            if (currentScope.endsWith(filter) && graph.method() != null) {
+                final String methodName = graph.method().getName();
+                Debug.sandbox("Printing Decompiler Output", null, new Runnable() {
+
+                    @Override
+                    public void run() {
+                        printStream.println();
+                        printStream.println("Object: " + methodName);
+                        printStream.println("Message: " + message);
+                        new Decompiler(graph, getPredefinedSchedule(), printStream, infoPrintStream, currentScope).decompile();
+                        printStream.flush();
+                    }
+                });
+
+            }
+        }
+    }
+
+    private static SchedulePhase getPredefinedSchedule() {
+        SchedulePhase result = null;
+        for (Object o : Debug.context()) {
+            if (o instanceof SchedulePhase) {
+                result = (SchedulePhase) o;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public void close() {
+        try {
+            printStream.close();
+            fos.close();
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+}
--- /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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,73 @@
+/*
+ * 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.*;
+
+@Ignore("Currently ignored due to problems with code coverage tools.")
+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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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.*;
+
+@Ignore("Currently ignored due to problems with code coverage tools.")
+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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,276 @@
+/*
+ * 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;
+    int nodeCountPartialEval;
+    int nodeCountLowered;
+
+    @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 %5.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;
+                            continue;
+                        }
+                    }
+                    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()) {
+                    int nodeCountTruffle = new InliningHelper.CallTargetProfile(rootNode).nodeCount;
+                    OUT.printf("[truffle] optimized %-50s |Nodes %7d |Time %5.0f(%4.0f+%-4.0f)ms |Nodes %5d/%5d |CodeSize %d\n", rootNode, nodeCountTruffle,
+                                    (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6,
+                                    (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, codeSize);
+                }
+            }
+        } catch (Throwable e) {
+            disableCompilation = true;
+            if (TraceTruffleCompilation.getValue()) {
+                if (e instanceof BailoutException) {
+                    OUT.printf("[truffle] opt bailout %-48s  %s\n", rootNode, e.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 static 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) target.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, target.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 static 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 static 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,310 @@
+/*
+ * 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 nodeCountBefore = graph.getNodeCount();
+                    Map<Node, Node> mapping = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false);
+                    if (Debug.isDumpEnabled()) {
+                        int nodeCountAfter = graph.getNodeCount();
+                        Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter);
+                    }
+
+                    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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 2013 +0200
@@ -0,0 +1,206 @@
+/*
+ * 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();
+        compilable.nodeCountPartialEval = graph.getNodeCount();
+        InstalledCode compiledMethod = compileMethodHelper(graph, config, compilable, assumptions);
+        compilable.timeCompilationFinished = System.nanoTime();
+        compilable.nodeCountLowered = graph.getNodeCount();
+        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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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 == next ? 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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	Mon Jun 24 10:25:41 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);
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Mon Jun 24 10:25:41 2013 +0200
@@ -209,13 +209,15 @@
 
             setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", ""));
             NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class);
-            if (nodeInfo != null && !nodeInfo.shortName().isEmpty()) {
-                setNodeProperty(node, "shortName", nodeInfo.shortName());
+            if (nodeInfo != null) {
+                setNodeProperty(node, "kind", nodeInfo.kind());
+                if (!nodeInfo.shortName().isEmpty()) {
+                    setNodeProperty(node, "shortName", nodeInfo.shortName());
+                }
             }
-            setNodeProperty(node, "nodeType", (Node.class.isAssignableFrom(node.getClass()) ? Node.class.getSimpleName() : "other"));
-            setNodeProperty(node, "nodeClass", node.getClass().getSimpleName());
-            copyDebugProperties(node); // TODO: may overwrite property "name"? (currently allowed)
+            setNodeProperty(node, "class", node.getClass().getSimpleName());
             readNodeProperties((Node) node);
+            copyDebugProperties(node);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java	Mon Jun 24 10:25:41 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/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Jun 24 10:22:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Jun 24 10:25:41 2013 +0200
@@ -57,6 +57,10 @@
     public @interface Child {
     }
 
+    protected Node() {
+        CompilerAsserts.neverPartOfCompilation();
+    }
+
     /**
      * Assigns a link to a guest language source section to this node.
      * 
@@ -86,6 +90,18 @@
     }
 
     /**
+     * Retrieves the guest language source code section that is currently assigned to this node.
+     * 
+     * @return the assigned source code section
+     */
+    public final SourceSection getEncapsulatingSourceSection() {
+        if (sourceSection == null && getParent() != null) {
+            return getParent().getEncapsulatingSourceSection();
+        }
+        return sourceSection;
+    }
+
+    /**
      * Method that updates the link to the parent in the array of specified new child nodes to this
      * node.
      * 
@@ -109,6 +125,9 @@
      */
     protected final <T extends Node> T adoptChild(T newChild) {
         if (newChild != null) {
+            if (newChild == this) {
+                throw new IllegalStateException("The parent of a node can never be the node itself.");
+            }
             ((Node) newChild).parent = this;
         }
         return newChild;
@@ -144,7 +163,9 @@
      */
     @SuppressWarnings({"unchecked"})
     public final <T extends Node> T replace(T newNode, String reason) {
-        assert this.getParent() != null;
+        if (this.getParent() == null) {
+            throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
+        }
         if (sourceSection != null) {
             // Pass on the source section to the new node.
             newNode.assignSourceSection(sourceSection);
--- a/mx/commands.py	Mon Jun 24 10:22:28 2013 +0200
+++ b/mx/commands.py	Mon Jun 24 10:25:41 2013 +0200
@@ -937,6 +937,11 @@
         vm(['-esa', '-version'])
         tasks.append(t.stop())
 
+        _vmbuild = 'fastdebug'
+        t = Task('BootstrapWithGCVerification:fastdebug')
+        vm(['-XX:+VerifyBeforeGC', '-version'])
+        tasks.append(t.stop())
+
         _vmbuild = 'product'
         t = Task('BootstrapWithRegisterPressure:product')
         vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version'])
--- a/mx/projects	Mon Jun 24 10:22:28 2013 +0200
+++ b/mx/projects	Mon Jun 24 10:25:41 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
@@ -385,10 +385,26 @@
 project@com.oracle.graal.java@javaCompliance=1.7
 project@com.oracle.graal.java@workingSets=Graal,Java
 
+# graal.java.decompiler
+project@com.oracle.graal.java.decompiler@subDir=graal
+project@com.oracle.graal.java.decompiler@sourceDirs=src
+project@com.oracle.graal.java.decompiler@dependencies=com.oracle.graal.java
+project@com.oracle.graal.java.decompiler@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.java.decompiler@javaCompliance=1.7
+project@com.oracle.graal.java.decompiler@workingSets=Graal
+
+# graal.java.decompiler.test
+project@com.oracle.graal.java.decompiler.test@subDir=graal
+project@com.oracle.graal.java.decompiler.test@sourceDirs=src
+project@com.oracle.graal.java.decompiler.test@dependencies=com.oracle.graal.printer
+project@com.oracle.graal.java.decompiler.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.java.decompiler.test@javaCompliance=1.7
+project@com.oracle.graal.java.decompiler.test@workingSets=Graal,Test
+
 # 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
@@ -523,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
 
 
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -1826,20 +1826,6 @@
   verify_oop_args(masm, method, sig_bt, regs);
   vmIntrinsics::ID iid = method->intrinsic_id();
 
-
-#ifdef GRAAL
-  if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
-    // We are called from compiled code here. The three object arguments
-    // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The
-    // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail
-    // call to its verified entry point.
-    __ set(nmethod::verified_entry_point_offset(), O0);
-    __ JMP(O0, 0);
-    __ delayed()->nop();
-    return;
-  }
-#endif
-
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
   Register receiver_reg   = noreg;
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -3412,6 +3412,7 @@
     // These entry points require SharedInfo::stack0 to be set up in non-core builds
     StubRoutines::_throw_AbstractMethodError_entry         = generate_throw_exception("AbstractMethodError throw_exception",          CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError));
     StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
+    StubRoutines::_throw_InvalidInstalledCodeException_entry= generate_throw_exception("InvalidInstalledCodeException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_InvalidInstalledCodeException));
     StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
 
     StubRoutines::_handler_for_unsafe_access_entry =
--- a/src/cpu/x86/vm/c2_globals_x86.hpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/cpu/x86/vm/c2_globals_x86.hpp	Mon Jun 24 10:25:41 2013 +0200
@@ -86,7 +86,11 @@
 define_pd_global(bool, OptoScheduling,               false);
 define_pd_global(bool, OptoBundling,                 false);
 
+#ifdef GRAAL
+define_pd_global(intx, ReservedCodeCacheSize,        64*M);
+#else
 define_pd_global(intx, ReservedCodeCacheSize,        48*M);
+#endif
 define_pd_global(uintx,CodeCacheMinBlockLength,      4);
 
 // Heap related flags
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -40,6 +40,9 @@
 #ifdef COMPILER2
 #include "opto/runtime.hpp"
 #endif
+#ifdef GRAAL
+#include "graal/graalJavaAccess.hpp"
+#endif
 
 #define __ masm->
 
@@ -1674,9 +1677,22 @@
   if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
     // We are called from compiled code here. The three object arguments
     // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The
-    // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail
-    // call to its verified entry point.
+    // fourth argument (j_rarg3) is a pointer to the HotSpotInstalledCode object.
+
+    // Load the nmethod pointer from the HotSpotInstalledCode object
+    __ movq(j_rarg3, Address(j_rarg3, sizeof(oopDesc)));
+
+    // Check whether the nmethod was invalidated
+    __ testq(j_rarg3, j_rarg3);
+    Label invalid_nmethod;
+    __ jcc(Assembler::zero, invalid_nmethod);
+
+    // Perform a tail call to the verified entry point of the nmethod.
     __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+
+    __ bind(invalid_nmethod);
+
+    __ jump(RuntimeAddress(StubRoutines::throw_InvalidInstalledCodeException_entry()));
     return;
   }
 #endif
--- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -2897,6 +2897,7 @@
     // and need to be relocatable, so they each fabricate a RuntimeStub internally.
     StubRoutines::_throw_AbstractMethodError_entry         = generate_throw_exception("AbstractMethodError throw_exception",          CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError));
     StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
+    StubRoutines::_throw_InvalidInstalledCodeException_entry         = generate_throw_exception("InvalidInstalledCodeException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_InvalidInstalledCodeException));
     StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
 
     //------------------------------------------------------------------------------------------------------------------------
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -3756,6 +3756,12 @@
                                                 SharedRuntime::
                                                 throw_IncompatibleClassChangeError));
 
+    StubRoutines::_throw_InvalidInstalledCodeException_entry =
+      generate_throw_exception("InvalidInstalledCodeException throw_exception",
+                               CAST_FROM_FN_PTR(address,
+                                                SharedRuntime::
+                                                throw_InvalidInstalledCodeException));
+
     StubRoutines::_throw_NullPointerException_at_call_entry =
       generate_throw_exception("NullPointerException at call throw_exception",
                                CAST_FROM_FN_PTR(address,
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -46,6 +46,9 @@
 #include "runtime/vframeArray.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/macros.hpp"
+#ifdef GRAAL
+#include "graal/graalJavaAccess.hpp"
+#endif
 
 #define __ _masm->
 
@@ -908,20 +911,34 @@
 
   // Move first object argument from interpreter calling convention to compiled
   // code calling convention.
-  __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5));
+  __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*4));
 
   // Move second object argument.
-  __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4));
+  __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*3));
 
   // Move third object argument.
-  __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3));
+  __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*2));
+
+  // Load the raw pointer to the HotSpotInstalledCode object.
+  __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize));
 
-  // Load the raw pointer to the nmethod.
-  __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize));
+  // Load the nmethod pointer from the HotSpotInstalledCode object
+  __ movq(j_rarg3, Address(j_rarg3, sizeof(oopDesc)));
+
+  // Check whether the nmethod was invalidated
+  __ testq(j_rarg3, j_rarg3);
+  Label invalid_nmethod;
+  __ jcc(Assembler::zero, invalid_nmethod);
 
   // Perform a tail call to the verified entry point of the nmethod.
   __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
 
+  __ bind(invalid_nmethod);
+
+  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_InvalidInstalledCodeException));
+  // the call_VM checks for exception, so we should never return here.
+  __ should_not_reach_here();
+
   return entry_point;
 }
 
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Jun 24 10:25:41 2013 +0200
@@ -348,6 +348,8 @@
   template(com_oracle_graal_api_code_VirtualObject,                  "com/oracle/graal/api/code/VirtualObject")                       \
   template(com_oracle_graal_api_code_RegisterSaveLayout,             "com/oracle/graal/api/code/RegisterSaveLayout")                  \
   template(com_oracle_graal_api_code_InvalidInstalledCodeException,  "com/oracle/graal/api/code/InvalidInstalledCodeException")       \
+  /* graal.truffle */                                                                                                                 \
+  template(com_oracle_graal_truffle_GraalTruffleRuntime,             "com/oracle/graal/truffle/GraalTruffleRuntime")                  \
   template(startCompiler_name,                    "startCompiler")                                                                    \
   template(bootstrap_name,                        "bootstrap")                                                                        \
   template(shutdownCompiler_name,                 "shutdownCompiler")                                                                 \
@@ -382,6 +384,7 @@
   template(getVMToCompiler_name,                  "getVMToCompiler")                                                                  \
   template(getVMToCompiler_signature,             "()Lcom/oracle/graal/hotspot/bridge/VMToCompiler;")                                 \
   template(getInstance_name,                      "getInstance")                                                                      \
+  template(getTruffleRuntimeInstance_signature,   "()Lcom/oracle/graal/truffle/GraalTruffleRuntime;")                                 \
   template(makeInstance_name,                     "makeInstance")                                                                     \
   template(initialize_name,                       "initialize")                                                                       \
   template(getInstance_signature,                 "()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;")                                 \
@@ -1145,7 +1148,7 @@
    do_name(     Double_valueOf_signature,                        "(D)Ljava/lang/Double;")                               \
                                                                                                                         \
   do_intrinsic(_CompilerToVMImpl_executeCompiledMethod,           com_oracle_graal_hotspot_bridge_CompilerToVMImpl, executeCompiledMethod_name, CompilerToVMImpl_executeCompiledMethod_signature, F_SN)\
-   do_name(     CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;J)Ljava/lang/Object;")                               \
+   do_name(     CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;)Ljava/lang/Object;")                               \
    do_name(     executeCompiledMethod_name,                       "executeCompiledMethodIntrinsic")                     \
     /*end*/
 
--- a/src/share/vm/code/nmethod.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/code/nmethod.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -1397,9 +1397,10 @@
     if (!is_osr_method() && !is_not_entrant()) {
       address stub = SharedRuntime::get_handle_wrong_method_stub();
 #ifdef GRAAL
-      if (_graal_installed_code != NULL && !HotSpotNmethod::isDefault(_graal_installed_code)) {
-        // This was manually installed machine code. Patch entry with stub that throws an exception.
-        stub = SharedRuntime::get_deoptimized_installed_code_stub();
+      if (_graal_installed_code != NULL) {
+        // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely.
+        HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0);
+        _graal_installed_code = NULL;
       }
 #endif
       NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -1004,10 +1004,11 @@
   return JNIHandles::make_local(element);
 C2V_END
 
-C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nmethodValue))
+C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jobject hotspotInstalledCode))
   ResourceMark rm;
   HandleMark hm;
 
+  jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode);
   nmethod* nm = (nmethod*) (address) nmethodValue;
   methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
@@ -1156,9 +1157,10 @@
 C2V_END
 
 
-C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jlong nativeMethod))
+C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jobject hotspotInstalledCode))
+  jlong nativeMethod = HotSpotInstalledCode::codeBlob(hotspotInstalledCode);
   nmethod* m = (nmethod*)nativeMethod;
-  if (!m->is_not_entrant()) {
+  if (m != NULL && !m->is_not_entrant()) {
     m->mark_for_deoptimization();
     VM_Deoptimize op;
     VMThread::execute(&op);
@@ -1166,11 +1168,6 @@
 C2V_END
 
 
-C2V_VMENTRY(jboolean, isInstalledCodeValid, (JNIEnv *env, jobject, jlong nativeMethod))
-  nmethod* m = (nmethod*)nativeMethod;
-  return m->is_alive() && !m->is_not_entrant();
-C2V_END
-
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
 
@@ -1203,7 +1200,6 @@
 #define METHOD_DATA           "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;"
 #define METASPACE_METHOD      "J"
 #define METASPACE_METHOD_DATA "J"
-#define NMETHOD               "J"
 
 JNINativeMethod CompilerToVM_methods[] = {
   {CC"initializeBytecode",            CC"("METASPACE_METHOD"[B)[B",                                     FN_PTR(initializeBytecode)},
@@ -1243,14 +1239,13 @@
   {CC"installCode0",                  CC"("HS_COMPILED_CODE HS_INSTALLED_CODE"[Z)I",                    FN_PTR(installCode0)},
   {CC"getCode",                       CC"(J)[B",                                                        FN_PTR(getCode)},
   {CC"disassembleCodeBlob",           CC"(J)"STRING,                                                    FN_PTR(disassembleCodeBlob)},
-  {CC"executeCompiledMethodVarargs",  CC"(["OBJECT NMETHOD")"OBJECT,                                    FN_PTR(executeCompiledMethodVarargs)},
+  {CC"executeCompiledMethodVarargs",  CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT,                          FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
   {CC"getLineNumberTable",            CC"("HS_RESOLVED_METHOD")[J",                                     FN_PTR(getLineNumberTable)},
   {CC"getLocalVariableTable",         CC"("HS_RESOLVED_METHOD")["LOCAL,                                 FN_PTR(getLocalVariableTable)},
   {CC"getFileName",                   CC"("HS_RESOLVED_JAVA_TYPE")"STRING,                              FN_PTR(getFileName)},
   {CC"reprofile",                     CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
-  {CC"invalidateInstalledCode",       CC"(J)V",                                                         FN_PTR(invalidateInstalledCode)},
-  {CC"isInstalledCodeValid",          CC"(J)Z",                                                         FN_PTR(isInstalledCodeValid)},
+  {CC"invalidateInstalledCode",       CC"("HS_INSTALLED_CODE")V",                                       FN_PTR(invalidateInstalledCode)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalJavaAccess.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -63,6 +63,7 @@
 
 void graal_compute_offsets() {
   COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD)
+  guarantee(HotSpotInstalledCode::_codeBlob_offset == sizeof(oopDesc), "codeBlob must be first field!");
 }
 
 #define EMPTY0
--- a/src/share/vm/graal/graalRuntime.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -474,3 +474,8 @@
 JVM_ENTRY(jobject, JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass))
   return VMToCompiler::graalRuntimePermObject();
 JVM_END
+
+// JVM_InitializeTruffleRuntime
+JVM_ENTRY(jobject, JVM_InitializeTruffleRuntime(JNIEnv *env, jclass graalclass))
+  return JNIHandles::make_local(VMToCompiler::truffleRuntime()());
+JVM_END
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -46,6 +46,16 @@
   return _vmToCompilerPermKlass;
 }
 
+Handle VMToCompiler::truffleRuntime() {
+  Symbol* name = vmSymbols::com_oracle_graal_truffle_GraalTruffleRuntime();
+  KlassHandle klass = loadClass(name);
+
+  JavaValue result(T_OBJECT);
+  JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::getTruffleRuntimeInstance_signature(), Thread::current());
+  check_pending_exception("Couldn't initialize GraalTruffleRuntime");
+  return Handle((oop) result.get_jobject());
+}
+
 Handle VMToCompiler::graalRuntime() {
   if (JNIHandles::resolve(_graalRuntimePermObject) == NULL) {
 #ifdef AMD64
@@ -292,3 +302,4 @@
 
 }
 
+
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Mon Jun 24 10:25:41 2013 +0200
@@ -44,6 +44,7 @@
 
 public:
   static Handle graalRuntime();
+  static Handle truffleRuntime();
 
   static jobject graalRuntimePermObject() {
     graalRuntime();
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -501,6 +501,10 @@
 IRT_END
 
 
+IRT_ENTRY(void, InterpreterRuntime::throw_InvalidInstalledCodeException(JavaThread* thread))
+  THROW(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException());
+IRT_END
+
 //------------------------------------------------------------------------------------------------------------------------
 // Fields
 //
--- a/src/share/vm/interpreter/interpreterRuntime.hpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/interpreter/interpreterRuntime.hpp	Mon Jun 24 10:25:41 2013 +0200
@@ -89,6 +89,7 @@
   // Exceptions thrown by the interpreter
   static void    throw_AbstractMethodError(JavaThread* thread);
   static void    throw_IncompatibleClassChangeError(JavaThread* thread);
+  static void    throw_InvalidInstalledCodeException(JavaThread* thread);
   static void    throw_StackOverflowError(JavaThread* thread);
   static void    throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
   static void    throw_ClassCastException(JavaThread* thread, oopDesc* obj);
--- a/src/share/vm/prims/nativeLookup.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/prims/nativeLookup.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -125,6 +125,7 @@
   void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
 #ifdef GRAAL
   jobject JNICALL JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass);
+  jobject JNICALL JVM_InitializeTruffleRuntime(JNIEnv *env, jclass graalclass);
 #endif
 }
 
@@ -142,6 +143,7 @@
   { CC"Java_sun_hotspot_WhiteBox_registerNatives",                 NULL, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
 #ifdef GRAAL
   { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_InitializeGraalRuntime)      },
+  { CC"Java_com_oracle_truffle_api_Truffle_initializeRuntime",     NULL, FN_PTR(JVM_InitializeTruffleRuntime)    },
 #endif
 };
 
--- a/src/share/vm/runtime/sharedRuntime.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -752,6 +752,11 @@
   throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_IncompatibleClassChangeError(), "vtable stub");
 JRT_END
 
+JRT_ENTRY(void, SharedRuntime::throw_InvalidInstalledCodeException(JavaThread* thread))
+  // These errors occur only at call sites
+  throw_and_post_jvmti_exception(thread, vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException());
+JRT_END
+
 JRT_ENTRY(void, SharedRuntime::throw_ArithmeticException(JavaThread* thread))
   throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArithmeticException(), "/ by zero");
 JRT_END
--- a/src/share/vm/runtime/sharedRuntime.hpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Mon Jun 24 10:25:41 2013 +0200
@@ -186,6 +186,7 @@
   };
   static void    throw_AbstractMethodError(JavaThread* thread);
   static void    throw_IncompatibleClassChangeError(JavaThread* thread);
+  static void    throw_InvalidInstalledCodeException(JavaThread* thread);
   static void    throw_ArithmeticException(JavaThread* thread);
   static void    throw_NullPointerException(JavaThread* thread);
   static void    throw_NullPointerException_at_call(JavaThread* thread);
--- a/src/share/vm/runtime/stubRoutines.cpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/runtime/stubRoutines.cpp	Mon Jun 24 10:25:41 2013 +0200
@@ -51,6 +51,7 @@
 address StubRoutines::_forward_exception_entry                  = NULL;
 address StubRoutines::_throw_AbstractMethodError_entry          = NULL;
 address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL;
+address StubRoutines::_throw_InvalidInstalledCodeException_entry = NULL;
 address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
 address StubRoutines::_throw_StackOverflowError_entry           = NULL;
 address StubRoutines::_handler_for_unsafe_access_entry          = NULL;
--- a/src/share/vm/runtime/stubRoutines.hpp	Mon Jun 24 10:22:28 2013 +0200
+++ b/src/share/vm/runtime/stubRoutines.hpp	Mon Jun 24 10:25:41 2013 +0200
@@ -128,6 +128,7 @@
   static address _catch_exception_entry;
   static address _throw_AbstractMethodError_entry;
   static address _throw_IncompatibleClassChangeError_entry;
+  static address _throw_InvalidInstalledCodeException_entry;
   static address _throw_NullPointerException_at_call_entry;
   static address _throw_StackOverflowError_entry;
   static address _handler_for_unsafe_access_entry;
@@ -261,6 +262,7 @@
   // Implicit exceptions
   static address throw_AbstractMethodError_entry()         { return _throw_AbstractMethodError_entry; }
   static address throw_IncompatibleClassChangeError_entry(){ return _throw_IncompatibleClassChangeError_entry; }
+  static address throw_InvalidInstalledCodeException_entry(){ return _throw_InvalidInstalledCodeException_entry; }
   static address throw_NullPointerException_at_call_entry(){ return _throw_NullPointerException_at_call_entry; }
   static address throw_StackOverflowError_entry()          { return _throw_StackOverflowError_entry; }