changeset 13736:64fa70319890

Merge with 9161ed8ce7964ca3df5e91894522b207a2bc4a3e
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Wed, 22 Jan 2014 21:34:00 -0800
parents 2c1c805153e6 (current diff) 9161ed8ce796 (diff)
children b9c5875e3a36 7b80276a4e65 174aebb02383 3f27e57439ed
files graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/JRubyParser.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java
diffstat 116 files changed, 1271 insertions(+), 742 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Wed Jan 22 21:34:00 2014 -0800
@@ -146,6 +146,7 @@
                 case Short:
                 case Int:
                 case Long:
+                case NarrowOop:
                 case Object:
                     return true;
             }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Wed Jan 22 21:34:00 2014 -0800
@@ -223,6 +223,8 @@
                 return 8;
             case Object:
                 return wordSize;
+            case NarrowOop:
+                return wordSize / 2;
             default:
                 return 0;
         }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Wed Jan 22 21:34:00 2014 -0800
@@ -227,10 +227,17 @@
         return sb;
     }
 
+    public interface RefMapFormatter {
+
+        String formatStackSlot(int frameRefMapIndex);
+
+        String formatRegister(int regRefMapIndex);
+    }
+
     /**
      * Formats a location present in a register or frame reference map.
      */
-    public static class RefMapFormatter {
+    public static class DefaultRefMapFormatter implements RefMapFormatter {
 
         /**
          * The size of a stack slot.
@@ -252,7 +259,7 @@
          */
         public final int refMapToFPOffset;
 
-        public RefMapFormatter(Architecture arch, int slotSize, Register fp, int refMapToFPOffset) {
+        public DefaultRefMapFormatter(Architecture arch, int slotSize, Register fp, int refMapToFPOffset) {
             this.arch = arch;
             this.slotSize = slotSize;
             this.fp = fp;
@@ -283,25 +290,16 @@
      */
     public static StringBuilder append(StringBuilder sb, DebugInfo info, RefMapFormatter formatter) {
         String nl = NEW_LINE;
-        if (info.hasRegisterRefMap()) {
+        ReferenceMap refMap = info.getReferenceMap();
+        if (refMap != null && refMap.hasRegisterRefMap()) {
             sb.append("  reg-ref-map:");
-            BitSet bm = info.getRegisterRefMap();
-            if (formatter != null) {
-                for (int reg = bm.nextSetBit(0); reg >= 0; reg = bm.nextSetBit(reg + 1)) {
-                    sb.append(" " + formatter.formatRegister(reg));
-                }
-            }
-            sb.append(' ').append(bm).append(nl);
+            refMap.appendRegisterMap(sb, formatter);
+            sb.append(nl);
         }
-        if (info.hasStackRefMap()) {
+        if (refMap != null && refMap.hasFrameRefMap()) {
             sb.append("frame-ref-map:");
-            BitSet bm = info.getFrameRefMap();
-            if (formatter != null) {
-                for (int i = bm.nextSetBit(0); i >= 0; i = bm.nextSetBit(i + 1)) {
-                    sb.append(" " + formatter.formatStackSlot(i));
-                }
-            }
-            sb.append(' ').append(bm).append(nl);
+            refMap.appendFrameMap(sb, formatter);
+            sb.append(nl);
         }
         RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
         if (calleeSaveInfo != null) {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Jan 22 21:34:00 2014 -0800
@@ -696,8 +696,19 @@
 
     private static void appendDebugInfo(StringBuilder sb, DebugInfo info) {
         if (info != null) {
-            appendRefMap(sb, "stackMap", info.getFrameRefMap());
-            appendRefMap(sb, "registerMap", info.getRegisterRefMap());
+            ReferenceMap refMap = info.getReferenceMap();
+            if (refMap != null) {
+                if (refMap.hasFrameRefMap()) {
+                    sb.append(" stackMap[");
+                    refMap.appendFrameMap(sb, null);
+                    sb.append(']');
+                }
+                if (refMap.hasRegisterRefMap()) {
+                    sb.append(" registerMap[");
+                    refMap.appendRegisterMap(sb, null);
+                    sb.append(']');
+                }
+            }
             RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
             if (calleeSaveInfo != null) {
                 sb.append(" callee-save-info[");
@@ -721,12 +732,6 @@
         }
     }
 
-    private static void appendRefMap(StringBuilder sb, String name, BitSet map) {
-        if (map != null) {
-            sb.append(' ').append(name).append('[').append(map.toString()).append(']');
-        }
-    }
-
     /**
      * @return the list of infopoints, sorted by {@link Site#pcOffset}
      */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Wed Jan 22 21:34:00 2014 -0800
@@ -23,15 +23,13 @@
 package com.oracle.graal.api.code;
 
 import java.io.*;
-import java.util.*;
 
 /**
  * Represents the debugging information for a particular point of execution. This information
  * includes:
  * <ul>
  * <li>a {@linkplain #getBytecodePosition() bytecode position}</li>
- * <li>a reference map for {@linkplain #getRegisterRefMap() registers}</li>
- * <li>a reference map for {@linkplain #getFrameRefMap() stack slots} in the current frame</li>
+ * <li>a reference map for registers and stack slots in the current frame</li>
  * <li>a map from bytecode locals and operand stack slots to their values or locations from which
  * their values can be read</li>
  * <li>a map from the registers (in the caller's frame) to the slots where they are saved in the
@@ -42,8 +40,7 @@
     private static final long serialVersionUID = -6047206624915812516L;
 
     private final BytecodePosition bytecodePosition;
-    private final BitSet registerRefMap;
-    private final BitSet frameRefMap;
+    private final ReferenceMap referenceMap;
     private RegisterSaveLayout calleeSaveInfo;
 
     /**
@@ -51,13 +48,11 @@
      * 
      * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame
      *            frame} info
-     * @param registerRefMap the register map
-     * @param frameRefMap the reference map for {@code frame}, which may be {@code null}
+     * @param referenceMap the reference map
      */
-    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap) {
+    public DebugInfo(BytecodePosition codePos, ReferenceMap referenceMap) {
         this.bytecodePosition = codePos;
-        this.registerRefMap = registerRefMap;
-        this.frameRefMap = frameRefMap;
+        this.referenceMap = referenceMap;
     }
 
     /**
@@ -68,20 +63,6 @@
     }
 
     /**
-     * @return {@code true} if this debug info has a reference map for the registers
-     */
-    public boolean hasRegisterRefMap() {
-        return getRegisterRefMap() != null && getRegisterRefMap().size() > 0;
-    }
-
-    /**
-     * @return {@code true} if this debug info has a reference map for the stack
-     */
-    public boolean hasStackRefMap() {
-        return getFrameRefMap() != null && getFrameRefMap().size() > 0;
-    }
-
-    /**
      * Gets the deoptimization information for each inlined frame (if available).
      * 
      * @return {@code null} if no frame de-opt info is {@linkplain #hasFrame() available}
@@ -107,21 +88,8 @@
         return bytecodePosition;
     }
 
-    /**
-     * @return The reference map for the registers at this point. The reference map is <i>packed</i>
-     *         in that for bit {@code k} in byte {@code n}, it refers to the register whose
-     *         {@linkplain Register#number number} is {@code (k + n * 8)}.
-     */
-    public BitSet getRegisterRefMap() {
-        return registerRefMap;
-    }
-
-    /**
-     * @return The reference map for the stack frame at this point. A set bit at {@code k} in the
-     *         map represents stack slot number {@code k}.
-     */
-    public BitSet getFrameRefMap() {
-        return frameRefMap;
+    public ReferenceMap getReferenceMap() {
+        return referenceMap;
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java	Wed Jan 22 21:34:00 2014 -0800
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2009, 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.api.code;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.CodeUtil.RefMapFormatter;
+
+public class ReferenceMap implements Serializable {
+
+    private static final long serialVersionUID = -1052183095979496819L;
+
+    /**
+     * Contains 2 bits per register.
+     * <ul>
+     * <li>bit0 = 0: contains no references</li>
+     * <li>bit0 = 1, bit1 = 0: contains a wide oop</li>
+     * <li>bit0 = 1, bit1 = 1: contains a narrow oop</li>
+     * </ul>
+     */
+    private final BitSet registerRefMap;
+
+    /**
+     * Contains 3 bits per stack slot.
+     * <ul>
+     * <li>bit0 = 0: contains no references</li>
+     * <li>bit0 = 1, bit1+2 = 0: contains a wide oop</li>
+     * <li>bit0 = 1, bit1 = 1: contains a narrow oop in the lower half</li>
+     * <li>bit0 = 1, bit2 = 1: contains a narrow oop in the upper half</li>
+     * </ul>
+     */
+    private final BitSet frameRefMap;
+
+    public ReferenceMap(int registerCount, int frameSlotCount) {
+        if (registerCount > 0) {
+            this.registerRefMap = new BitSet(registerCount * 2);
+        } else {
+            this.registerRefMap = null;
+        }
+        this.frameRefMap = new BitSet(frameSlotCount * 3);
+    }
+
+    public void setRegister(int idx, boolean narrow) {
+        registerRefMap.set(2 * idx);
+        if (narrow) {
+            registerRefMap.set(2 * idx + 1);
+        }
+    }
+
+    public void setStackSlot(int idx, boolean narrow1, boolean narrow2) {
+        frameRefMap.set(3 * idx);
+        if (narrow1) {
+            frameRefMap.set(3 * idx + 1);
+        }
+        if (narrow2) {
+            frameRefMap.set(3 * idx + 2);
+        }
+    }
+
+    public boolean hasRegisterRefMap() {
+        return registerRefMap != null && registerRefMap.size() > 0;
+    }
+
+    public boolean hasFrameRefMap() {
+        return frameRefMap != null && frameRefMap.size() > 0;
+    }
+
+    private static class NumberedRefMapFormatter implements RefMapFormatter {
+
+        public String formatStackSlot(int frameRefMapIndex) {
+            return "s" + frameRefMapIndex;
+        }
+
+        public String formatRegister(int regRefMapIndex) {
+            return "r" + regRefMapIndex;
+        }
+    }
+
+    public void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg) {
+        RefMapFormatter formatter = formatterArg;
+        if (formatter == null) {
+            formatter = new NumberedRefMapFormatter();
+        }
+
+        for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 2)) {
+            sb.append(' ').append(formatter.formatRegister(reg / 2));
+        }
+    }
+
+    public void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg) {
+        RefMapFormatter formatter = formatterArg;
+        if (formatter == null) {
+            formatter = new NumberedRefMapFormatter();
+        }
+
+        for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + 3)) {
+            sb.append(' ').append(formatter.formatStackSlot(slot / 3));
+        }
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Wed Jan 22 21:34:00 2014 -0800
@@ -159,6 +159,7 @@
             case Double:
                 return asDouble();
             case Object:
+            case NarrowOop:
                 return object;
             case Illegal:
                 return this;
@@ -171,7 +172,7 @@
         if (!ignoreKind && getKind() != other.getKind()) {
             return false;
         }
-        if (getKind() == Kind.Object) {
+        if (getKind() == Kind.Object || getKind() == Kind.NarrowOop) {
             return object == other.object;
         }
         return primitive == other.primitive && getPrimitiveAnnotation() == other.getPrimitiveAnnotation();
@@ -234,12 +235,12 @@
 
     /**
      * Returns the object reference this constant represents. The constant must have kind
-     * {@link Kind#Object}.
+     * {@link Kind#Object} or {@link Kind#NarrowOop}.
      * 
      * @return the constant value
      */
     public Object asObject() {
-        assert getKind() == Kind.Object;
+        assert getKind() == Kind.Object || getKind() == Kind.NarrowOop;
         return object;
     }
 
@@ -249,7 +250,7 @@
      * @return null if this constant is not primitive or has no annotation
      */
     public Object getPrimitiveAnnotation() {
-        return getKind() == Kind.Object ? null : object;
+        return getKind() == Kind.Object || getKind() == Kind.NarrowOop ? null : object;
     }
 
     /**
@@ -259,7 +260,7 @@
      */
     @Override
     public int hashCode() {
-        if (getKind() == Kind.Object) {
+        if (getKind() == Kind.Object || getKind() == Kind.NarrowOop) {
             return System.identityHashCode(object);
         }
         return (int) primitive * getKind().ordinal();
@@ -393,6 +394,16 @@
     }
 
     /**
+     * Creates a boxed narrow oop constant.
+     * 
+     * @param o the object value to box
+     * @return a boxed copy of {@code value}
+     */
+    public static Constant forNarrowOop(Object o) {
+        return new Constant(Kind.NarrowOop, o, 0L);
+    }
+
+    /**
      * Creates an annotated int or long constant. An annotation enables a client to associate some
      * extra semantic or debugging information with a primitive. An annotated primitive constant is
      * never {@linkplain #equals(Object) equal} to a non-annotated constant.
@@ -440,6 +451,8 @@
                 return forDouble((Double) value);
             case Object:
                 return forObject(value);
+            case NarrowOop:
+                return forNarrowOop(value);
             default:
                 throw new RuntimeException("cannot create Constant for boxed " + kind + " value");
         }
@@ -472,6 +485,8 @@
                 return LONG_0;
             case Object:
                 return NULL_OBJECT;
+            case NarrowOop:
+                return forNarrowOop(null);
             default:
                 throw new IllegalArgumentException(kind.toString());
         }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Wed Jan 22 21:34:00 2014 -0800
@@ -57,6 +57,9 @@
     /** The Object kind, also used for arrays. */
     Object('a', "Object", false, null, null),
 
+    /** The narrow oop kind. */
+    NarrowOop('n', "NarrowOop", false, null, null),
+
     /** The void float kind. */
     Void('v', "void", false, java.lang.Void.TYPE, java.lang.Void.class),
 
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Wed Jan 22 21:34:00 2014 -0800
@@ -700,6 +700,9 @@
         bra(str);
     }
 
+    /**
+     * @param r
+     */
     public void nullCheck(Register r) {
         // setp(....);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXMethodInvalidation1Test.java	Wed Jan 22 21:34:00 2014 -0800
@@ -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.compiler.ptx.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.ptx.*;
+
+/**
+ * Tests that a {@linkplain PTXWrapperBuilder PTX kernel wrapper} deoptimizes if the kernel is
+ * invalid.
+ */
+public class PTXMethodInvalidation1Test extends PTXTest {
+
+    @Test
+    public void test() {
+        test("testSnippet", 100);
+    }
+
+    @Override
+    protected HotSpotNmethod installKernel(ResolvedJavaMethod method, ExternalCompilationResult ptxCode) {
+        HotSpotNmethod ptxKernel = super.installKernel(method, ptxCode);
+        ptxKernel.invalidate();
+        return ptxKernel;
+    }
+
+    int f = 42;
+
+    public int testSnippet(int delta) {
+        return f + delta;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXMethodInvalidation2Test.java	Wed Jan 22 21:34:00 2014 -0800
@@ -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.compiler.ptx.test;
+
+import java.lang.ref.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.ptx.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * A full GC on HotSpot will unload an nmethod that contains an embedded oop which is the only
+ * reference to its referent. The nmethod created for a {@linkplain PTXWrapperBuilder PTX kernel
+ * wrapper} has an embedded oop referring to a {@link HotSpotNmethod} object associated with the
+ * nmethod for the installed PTX kernel. This embedded oop is a weak reference as described above so
+ * there must be another strong reference from the wrapper to the {@link HotSpotNmethod} object.
+ */
+public class PTXMethodInvalidation2Test extends PTXTest {
+
+    @Test
+    public void test() {
+        test("testSnippet", 100);
+    }
+
+    @Override
+    protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) {
+        InstalledCode code = super.getCode(method, graph);
+
+        // Try hard to force a full GC
+        int attempts = 0;
+        WeakReference<Object> ref = new WeakReference<>(new Object());
+        while (ref.get() != null) {
+            System.gc();
+            // Give up after 1000 attempts
+            Assume.assumeTrue(++attempts < 1000);
+        }
+
+        Assert.assertFalse(code.getStart() == 0L);
+        return code;
+    }
+
+    int f = 42;
+
+    public int testSnippet(int delta) {
+        return f + delta;
+    }
+}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -57,13 +57,18 @@
         return compileKernel(getMetaAccess().lookupJavaMethod(getMethod(test)));
     }
 
+    protected HotSpotNmethod installKernel(ResolvedJavaMethod method, ExternalCompilationResult ptxCode) {
+        PTXHotSpotBackend ptxBackend = getPTXBackend();
+        return ptxBackend.installKernel(method, ptxCode);
+    }
+
     @Override
     protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) {
         PTXHotSpotBackend ptxBackend = getPTXBackend();
         ExternalCompilationResult ptxCode = compileKernel(method);
         Assume.assumeTrue(ptxBackend.isDeviceInitialized());
-        InstalledCode installedPTXCode = ptxBackend.installKernel(method, ptxCode);
-        StructuredGraph wrapper = new PTXWrapperBuilder(method, installedPTXCode.getStart(), (HotSpotProviders) getProviders()).getGraph();
+        HotSpotNmethod installedPTXCode = installKernel(method, ptxCode);
+        StructuredGraph wrapper = new PTXWrapperBuilder(method, installedPTXCode, (HotSpotProviders) getProviders()).getGraph();
         return super.getCode(method, wrapper);
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -299,8 +299,8 @@
 
     final ValueNode getResult(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-        return graph.getNodes().filter(ReturnNode.class).first().result();
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first().result();
     }
 
     private void processMethod(final String snippet) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -98,11 +98,9 @@
         for (int i = 1; i <= 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("integerTest" + i);
 
-            ValueNode result = getResult(graph);
-            assertTrue(result instanceof ConditionalNode);
-            ConditionalNode mat = (ConditionalNode) result;
-            assertTrue(mat.condition() instanceof IntegerTestNode);
-            IntegerTestNode test = (IntegerTestNode) mat.condition();
+            ReturnNode returnNode = (ReturnNode) graph.start().next();
+            ConditionalNode conditional = (ConditionalNode) returnNode.result();
+            IntegerTestNode test = (IntegerTestNode) conditional.condition();
             ParameterNode param0 = graph.getParameter(0);
             ParameterNode param1 = graph.getParameter(1);
             assertTrue((test.x() == param0 && test.y() == param1) || (test.x() == param1 && test.y() == param0));
@@ -133,8 +131,9 @@
         assertTrue(result.isConstant() && result.asConstant().asLong() == 1);
         result = getResult(getCanonicalizedGraph("integerTestCanonicalization2"));
         assertTrue(result.isConstant() && result.asConstant().asLong() == 1);
-        result = getResult(getCanonicalizedGraph("integerTestCanonicalization3"));
-        assertTrue(result instanceof ConditionalNode);
+        StructuredGraph graph = getCanonicalizedGraph("integerTestCanonicalization3");
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        assertTrue(graph.getNodes(ReturnNode.class).first().result() instanceof ConditionalNode);
     }
 
     public static int integerTestCanonicalization1(boolean b) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -154,14 +154,18 @@
 
     @SuppressWarnings("unused")
     public static int testDisjunctionSnippet(Object a) {
-        if (a instanceof Integer) {
-            if (a == null) {
-                return -1;
+        try {
+            if (a instanceof Integer) {
+                if (a == null) {
+                    return -1;
+                } else {
+                    return 2;
+                }
             } else {
-                return 2;
+                return 3;
             }
-        } else {
-            return 3;
+        } finally {
+            field = null;
         }
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -68,6 +68,7 @@
 
             for (Node n : graph.getNodes()) {
                 if (n instanceof ReturnNode) {
+                    assert returnNode == null;
                     returnNode = (ReturnNode) n;
                 } else if (n instanceof MonitorExit) {
                     monitorexit = (MonitorExit) n;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -172,8 +172,8 @@
 
     protected void assertConstantReturn(StructuredGraph graph, int value) {
         String graphString = getCanonicalGraphString(graph, false);
-        Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes().filter(ReturnNode.class).count(), 1);
-        ValueNode result = graph.getNodes().filter(ReturnNode.class).first().result();
+        Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1);
+        ValueNode result = graph.getNodes(ReturnNode.class).first().result();
         Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant());
         Assert.assertEquals("unexpected ReturnNode result kind: " + graphString, result.asConstant().getKind(), Kind.Int);
         Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asConstant().asInt(), value);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -115,7 +115,7 @@
         for (TestMode mode : TestMode.values()) {
             SchedulePhase schedule = getFinalSchedule("testSplit1Snippet", mode);
             assertReadWithinStartBlock(schedule, true);
-            assertReadWithinReturnBlock(schedule, false);
+            assertReadWithinAllReturnBlocks(schedule, false);
         }
     }
 
@@ -131,6 +131,7 @@
             } else {
                 container.b = 15;
             }
+            container.obj = null;
         }
     }
 
@@ -138,7 +139,7 @@
     public void testSplit2() {
         SchedulePhase schedule = getFinalSchedule("testSplit2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     /**
@@ -163,7 +164,7 @@
         SchedulePhase schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(6, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, true);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
     /**
@@ -188,7 +189,7 @@
         SchedulePhase schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(6, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     /**
@@ -208,9 +209,9 @@
     @Test
     public void testLoop3() {
         SchedulePhase schedule = getFinalSchedule("testLoop3Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertEquals(7, schedule.getCFG().getBlocks().length);
+        assertEquals(6, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, true);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
     public String testStringReplaceSnippet(String input) {
@@ -246,7 +247,7 @@
         SchedulePhase schedule = getFinalSchedule("testLoop5Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(7, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
     /**
@@ -261,10 +262,11 @@
     public void testArrayCopy() {
         SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES);
         StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph();
-        ReturnNode ret = graph.getNodes().filter(ReturnNode.class).first();
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        ReturnNode ret = graph.getNodes(ReturnNode.class).first();
         assertTrue(ret.result() instanceof FloatingReadNode);
         assertEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result()));
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     /**
@@ -281,7 +283,7 @@
     @Test
     public void testIfRead1() {
         SchedulePhase schedule = getFinalSchedule("testIfRead1Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertEquals(4, schedule.getCFG().getBlocks().length);
+        assertEquals(3, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, true);
         assertReadAndWriteInSameBlock(schedule, false);
     }
@@ -302,10 +304,10 @@
     @Test
     public void testIfRead2() {
         SchedulePhase schedule = getFinalSchedule("testIfRead2Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertEquals(4, schedule.getCFG().getBlocks().length);
+        assertEquals(3, schedule.getCFG().getBlocks().length);
         assertEquals(1, schedule.getCFG().graph.getNodes().filter(FloatingReadNode.class).count());
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
         assertReadAndWriteInSameBlock(schedule, false);
     }
 
@@ -326,7 +328,7 @@
         SchedulePhase schedule = getFinalSchedule("testIfRead3Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(4, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     /**
@@ -345,9 +347,9 @@
     @Test
     public void testIfRead4() {
         SchedulePhase schedule = getFinalSchedule("testIfRead4Snippet", TestMode.WITHOUT_FRAMESTATES);
-        assertEquals(4, schedule.getCFG().getBlocks().length);
+        assertEquals(3, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
         assertReadAndWriteInSameBlock(schedule, true);
     }
 
@@ -366,7 +368,7 @@
         SchedulePhase schedule = getFinalSchedule("testIfRead5Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertEquals(4, schedule.getCFG().getBlocks().length);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
         assertReadAndWriteInSameBlock(schedule, false);
     }
 
@@ -432,7 +434,7 @@
     public void testBlockSchedule2() {
         SchedulePhase schedule = getFinalSchedule("testBlockSchedule2Snippet", TestMode.WITHOUT_FRAMESTATES, MemoryScheduling.OPTIMAL, SchedulingStrategy.LATEST);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
         assertReadAndWriteInSameBlock(schedule, false);
     }
 
@@ -454,7 +456,7 @@
          * read of container.b for increment operation should be in return block. TODO: not sure
          * though, could be replaced by read of container.b of the loop header...
          */
-        assertReadWithinReturnBlock(schedule, true);
+        assertReadWithinAllReturnBlocks(schedule, true);
     }
 
     public static void testProxy2Snippet() {
@@ -476,7 +478,7 @@
     public void testProxy2() {
         SchedulePhase schedule = getFinalSchedule("testProxy2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
     private int hash = 0;
@@ -499,7 +501,7 @@
     public void testStringHashCode() {
         SchedulePhase schedule = getFinalSchedule("testStringHashCodeSnippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, true);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
 
         hash = 0x1337;
         value[0] = 'a';
@@ -531,30 +533,26 @@
     public void testLoop4() {
         SchedulePhase schedule = getFinalSchedule("testLoop4Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
-        assertReadWithinReturnBlock(schedule, false);
+        assertReadWithinAllReturnBlocks(schedule, false);
     }
 
-    private void assertReadWithinReturnBlock(SchedulePhase schedule, boolean withinReturnBlock) {
+    private void assertReadWithinAllReturnBlocks(SchedulePhase schedule, boolean withinReturnBlock) {
         StructuredGraph graph = schedule.getCFG().graph;
-        assertEquals(graph.getNodes().filter(ReturnNode.class).count(), 1);
+        assertTrue(graph.getNodes(ReturnNode.class).isNotEmpty());
 
-        Block end = null;
-        outer: for (Block b : schedule.getCFG().getBlocks()) {
-            for (Node n : b.getNodes()) {
-                if (n instanceof ReturnNode) {
-                    end = b;
-                    break outer;
+        int withRead = 0;
+        int returnBlocks = 0;
+        for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) {
+            Block block = schedule.getCFG().getNodeToBlock().get(returnNode);
+            for (Node node : schedule.getBlockToNodesMap().get(block)) {
+                if (node instanceof FloatingReadNode) {
+                    withRead++;
+                    break;
                 }
             }
+            returnBlocks++;
         }
-        assertNotNull("no block with ReturnNode found", end);
-        boolean readEncountered = false;
-        for (Node node : schedule.getBlockToNodesMap().get(end)) {
-            if (node instanceof FloatingReadNode) {
-                readEncountered = true;
-            }
-        }
-        assertEquals(readEncountered, withinReturnBlock);
+        assertEquals(withRead == returnBlocks, withinReturnBlock);
     }
 
     private void assertReadWithinStartBlock(SchedulePhase schedule, boolean withinStartBlock) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -0,0 +1,66 @@
+/*
+ * 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.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class MergeCanonicalizerTest extends GraalCompilerTest {
+
+    public static int staticField;
+
+    private int field;
+
+    @Test
+    public void testSplitReturn() {
+        test("testSplitReturnSnippet", 2);
+        testReturnCount("testSplitReturnSnippet", 2);
+    }
+
+    public int testSplitReturnSnippet(int b) {
+        int v;
+        if (b < 0) {
+            staticField = 1;
+            v = 10;
+        } else {
+            staticField = 2;
+            v = 20;
+        }
+        int i = field;
+        i = field + i;
+        return v;
+    }
+
+    private void testReturnCount(String snippet, int returnCount) {
+        StructuredGraph graph = parse(snippet);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
+        Debug.dump(graph, "Graph");
+        assertEquals(returnCount, graph.getNodes(ReturnNode.class).count());
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -167,7 +167,6 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         StructuredGraph referenceGraph = parse(referenceSnippet);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -76,7 +76,6 @@
         test("test1Snippet");
     }
 
-    @Test(expected = AssertionError.class)
     public void test2() {
         test("test2Snippet");
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -98,13 +98,11 @@
         test("test4Snippet", "referenceSnippet3");
     }
 
-    public static final Object constantObject1 = "1";
-    public static final Object constantObject2 = "2";
-    public static final Object constantObject3 = "3";
-
+    @SuppressWarnings("unused")
     public static int test4Snippet(Object o) {
         if (o == null) {
-            if (o == constantObject1) {
+            Object o2 = Integer.class;
+            if (o == o2) {
                 return 3;
             } else {
                 return 1;
@@ -121,40 +119,41 @@
 
     public static int referenceSnippet5(Object o, Object a) {
         if (o == null) {
-            if (a == constantObject1 || a == constantObject2) {
+            if (a == Integer.class || a == Double.class) {
                 return 1;
             }
         } else {
-            if (a == constantObject2 || a == constantObject3) {
+            if (a == Double.class || a == Long.class) {
                 return 11;
             }
         }
-        if (a == constantObject1) {
+        if (a == Integer.class) {
             return 3;
         }
         return 5;
     }
 
+    @SuppressWarnings("unused")
     public static int test5Snippet(Object o, Object a) {
         if (o == null) {
-            if (a == constantObject1 || a == constantObject2) {
+            if (a == Integer.class || a == Double.class) {
                 if (a == null) {
                     return 10;
                 }
                 return 1;
             }
         } else {
-            if (a == constantObject2 || a == constantObject3) {
+            if (a == Double.class || a == Long.class) {
                 if (a != null) {
                     return 11;
                 }
                 return 2;
             }
         }
-        if (a == constantObject1) {
+        if (a == Integer.class) {
             return 3;
         }
-        if (a == constantObject2) {
+        if (a == Double.class) {
             return 4;
         }
         return 5;
@@ -185,7 +184,6 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         // a second canonicalizer is needed to process nested MaterializeNodes
@@ -198,8 +196,8 @@
     @Override
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
         if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
-            outputGraph(expected, "expected");
-            outputGraph(graph, "actual");
+            Debug.dump(expected, "expected (node count)");
+            Debug.dump(graph, "graph (node count)");
             Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount());
         }
     }
@@ -239,12 +237,11 @@
 
     private <T extends Node> void testHelper(String snippet, Class<T> clazz) {
         StructuredGraph graph = parse(snippet);
-        Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         new ConditionalEliminationPhase(getMetaAccess()).apply(graph);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
-        Debug.dump(graph, "Graph");
+        Debug.dump(graph, "Graph " + snippet);
         Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -33,8 +33,9 @@
     @Test
     public void testSimpleMerge() {
         testEscapeAnalysis("simpleMergeSnippet", null, false);
-        assertTrue(returnNode.result() instanceof PhiNode);
-        PhiNode phi = (PhiNode) returnNode.result();
+        assertEquals(1, returnNodes.size());
+        assertTrue(returnNodes.get(0).result() instanceof PhiNode);
+        PhiNode phi = (PhiNode) returnNodes.get(0).result();
         assertTrue(phi.valueAt(0) instanceof ParameterNode);
         assertTrue(phi.valueAt(1) instanceof ParameterNode);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Wed Jan 22 21:34:00 2014 -0800
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
+import java.util.*;
+
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
@@ -119,7 +121,7 @@
 
     protected StructuredGraph graph;
     protected HighTierContext context;
-    protected ReturnNode returnNode;
+    protected List<ReturnNode> returnNodes;
 
     /**
      * Runs Escape Analysis on the given snippet and makes sure that no allocations remain in the
@@ -134,8 +136,10 @@
     protected void testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) {
         prepareGraph(snippet, iterativeEscapeAnalysis);
         if (expectedConstantResult != null) {
-            Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
-            Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+            for (ReturnNode returnNode : returnNodes) {
+                Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
+                Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+            }
         }
         int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() +
                         graph.getNodes().filter(CommitAllocationNode.class).count();
@@ -153,8 +157,7 @@
             new DeadCodeEliminationPhase().apply(graph);
             new CanonicalizerPhase(true).apply(graph, context);
             new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true)).apply(graph, context);
-            Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-            returnNode = graph.getNodes().filter(ReturnNode.class).first();
+            returnNodes = graph.getNodes(ReturnNode.class).snapshot();
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -213,8 +213,9 @@
         prepareGraph("testFullyUnrolledLoopSnippet", false);
         new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
-        Assert.assertTrue(returnNode.result() instanceof AllocatedObjectNode);
-        CommitAllocationNode commit = ((AllocatedObjectNode) returnNode.result()).getCommit();
+        Assert.assertEquals(1, returnNodes.size());
+        Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode);
+        CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit();
         Assert.assertEquals(2, commit.getValues().size());
         Assert.assertEquals(1, commit.getVirtualObjects().size());
         Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -79,8 +79,8 @@
 
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-        return graph.getNodes().filter(ReturnNode.class).first();
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first();
     }
 
     private void processMethod(final String snippet) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -24,6 +24,8 @@
 
 import static org.junit.Assert.*;
 
+import java.util.*;
+
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
@@ -194,14 +196,14 @@
 
     @Test
     public void testPhi() {
-        ValueNode result = getReturn("testPhiSnippet").result();
+        processMethod("testPhiSnippet");
         assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty());
-        assertTrue(result instanceof PhiNode);
-        PhiNode phi = (PhiNode) result;
-        assertTrue(phi.valueAt(0).isConstant());
-        assertTrue(phi.valueAt(1).isConstant());
-        assertEquals(1, phi.valueAt(0).asConstant().asInt());
-        assertEquals(2, phi.valueAt(1).asConstant().asInt());
+        List<ReturnNode> returnNodes = graph.getNodes(ReturnNode.class).snapshot();
+        assertEquals(2, returnNodes.size());
+        assertTrue(returnNodes.get(0).predecessor() instanceof StoreFieldNode);
+        assertTrue(returnNodes.get(1).predecessor() instanceof StoreFieldNode);
+        assertTrue(returnNodes.get(0).result().isConstant());
+        assertTrue(returnNodes.get(1).result().isConstant());
     }
 
     @SuppressWarnings("all")
@@ -236,8 +238,8 @@
 
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
-        return graph.getNodes().filter(ReturnNode.class).first();
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first();
     }
 
     protected void processMethod(final String snippet) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -86,8 +86,9 @@
     @Test
     public void testMergedDouble() {
         testEscapeAnalysis("testMergedDoubleSnippet", null, false);
-        Assert.assertTrue(returnNode.result() instanceof PhiNode);
-        PhiNode phi = (PhiNode) returnNode.result();
+        Assert.assertEquals(1, returnNodes.size());
+        Assert.assertTrue(returnNodes.get(0).result() instanceof PhiNode);
+        PhiNode phi = (PhiNode) returnNodes.get(0).result();
         Assert.assertTrue(phi.valueAt(0) instanceof LoadFieldNode);
         Assert.assertTrue(phi.valueAt(1) instanceof LoadFieldNode);
     }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Jan 22 21:34:00 2014 -0800
@@ -458,7 +458,7 @@
         if (c.getKind() == Kind.Long) {
             return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
         } else if (c.getKind() == Kind.Object) {
-            return Constant.forIntegerKind(Kind.Int, 0xdeaddead, c.asObject());
+            return Constant.forNarrowOop(c.asObject());
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Wed Jan 22 21:34:00 2014 -0800
@@ -141,14 +141,14 @@
             public StructuredGraph getGraphFor(ResolvedJavaMethod method) {
                 if (canOffloadToGPU(method)) {
                     ExternalCompilationResult ptxCode = PTXHotSpotBackend.this.compileKernel(method, true);
-                    InstalledCode installedPTXCode = PTXHotSpotBackend.this.installKernel(method, ptxCode);
-                    return new PTXWrapperBuilder(method, installedPTXCode.getStart(), getRuntime().getHostBackend().getProviders()).getGraph();
+                    HotSpotNmethod installedPTXCode = PTXHotSpotBackend.this.installKernel(method, ptxCode);
+                    return new PTXWrapperBuilder(method, installedPTXCode, getRuntime().getHostBackend().getProviders()).getGraph();
                 }
                 return null;
             }
 
             private boolean canOffloadToGPU(ResolvedJavaMethod method) {
-                return method.getName().contains("lambda$main$") & method.isSynthetic();
+                return method.getName().contains("lambda$") & method.isSynthetic();
             }
         };
     }
@@ -181,9 +181,27 @@
 
     }
 
-    public InstalledCode installKernel(ResolvedJavaMethod method, ExternalCompilationResult ptxCode) {
-        assert ptxCode.getEntryPoint() != 0L;
-        return getProviders().getCodeCache().addExternalMethod(method, ptxCode);
+    /**
+     * A list of the {@linkplain #installKernel(ResolvedJavaMethod, ExternalCompilationResult)
+     * installed} kernels. This is required so that there is a strong reference to each installed
+     * kernel as long as it is {@linkplain HotSpotNmethod#isValid() valid}. The list is pruned of
+     * invalid kernels every time a new kernel is installed.
+     */
+    private List<HotSpotNmethod> installedKernels = new LinkedList<>();
+
+    public final HotSpotNmethod installKernel(ResolvedJavaMethod method, ExternalCompilationResult ptxCode) {
+        assert OmitDeviceInit || ptxCode.getEntryPoint() != 0L;
+        HotSpotNmethod kernel = getProviders().getCodeCache().addExternalMethod(method, ptxCode);
+        synchronized (installedKernels) {
+            for (Iterator<HotSpotNmethod> i = installedKernels.iterator(); i.hasNext();) {
+                HotSpotNmethod entry = i.next();
+                if (!entry.isValid()) {
+                    i.remove();
+                }
+            }
+            installedKernels.add(kernel);
+        }
+        return kernel;
     }
 
     static final class RegisterAnalysis extends ValueProcedure {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Wed Jan 22 21:34:00 2014 -0800
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.ptx;
 
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.api.meta.MetaUtil.*;
@@ -53,9 +54,9 @@
 import com.oracle.graal.word.*;
 
 /**
- * Utility for building a graph that "wraps" the PTX binary compiled for a method. Such a wrapper
- * handles the transition from the host CPU to the GPU and back. The graph created is something like
- * the following pseudo code with UPPER CASE denoting compile-time constants:
+ * Utility for building a graph that "wraps" a compiled PTX kernel. Such a wrapper handles the
+ * transition from the host CPU to the GPU and back. The graph created is something like the
+ * following pseudo code with UPPER CASE denoting compile-time constants:
  * 
  * <pre>
  *     T kernel(p0, p1, ..., pN) {
@@ -65,6 +66,10 @@
  *         return convert(result);
  *     }
  * </pre>
+ * <p>
+ * The generated graph includes a reference to the {@link HotSpotNmethod} for the kernel. There must
+ * be another reference to the same {@link HotSpotNmethod} object to ensure that the nmethod is not
+ * unloaded by the next full GC.
  */
 public class PTXWrapperBuilder extends GraphKit {
 
@@ -97,9 +102,10 @@
      * Creates the graph implementing the CPU to GPU transition.
      * 
      * @param method a method that has been compiled to GPU binary code
-     * @param kernelAddress the entry point of the GPU binary for {@code kernelMethod}
+     * @param kernel the installed GPU binary for {@code method}
+     * @see PTXWrapperBuilder
      */
-    public PTXWrapperBuilder(ResolvedJavaMethod method, long kernelAddress, HotSpotProviders providers) {
+    public PTXWrapperBuilder(ResolvedJavaMethod method, HotSpotNmethod kernel, HotSpotProviders providers) {
         super(new StructuredGraph(method), providers);
         int wordSize = providers.getCodeCache().getTarget().wordSize;
         Kind wordKind = providers.getCodeCache().getTarget().wordKind;
@@ -132,11 +138,13 @@
             }
         }
 
+        InvokeNode kernelStart = createInvoke(getClass(), "getKernelStart", ConstantNode.forObject(kernel, providers.getMetaAccess(), getGraph()));
+
         AllocaNode buf = append(new AllocaNode(bufSize / wordSize, objects));
 
         Map<LaunchArg, ValueNode> args = new EnumMap<>(LaunchArg.class);
         args.put(Thread, append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false)));
-        args.put(Kernel, ConstantNode.forLong(kernelAddress, getGraph()));
+        args.put(Kernel, kernelStart);
         args.put(DimX, forInt(1, getGraph()));
         args.put(DimY, forInt(1, getGraph()));
         args.put(DimZ, forInt(1, getGraph()));
@@ -252,6 +260,19 @@
     }
 
     /**
+     * Snippet invoked to get the {@linkplain HotSpotNmethod#getStart() entry point} of the kernel,
+     * deoptimizing if the kernel is invalid.
+     */
+    @Snippet
+    private static long getKernelStart(HotSpotNmethod ptxKernel) {
+        long start = ptxKernel.getStart();
+        if (start == 0L) {
+            DeoptimizeNode.deopt(InvalidateRecompile, RuntimeConstraint);
+        }
+        return start;
+    }
+
+    /**
      * Snippet invoked upon return from the kernel to handle any pending exceptions.
      */
     @Snippet
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Jan 22 21:34:00 2014 -0800
@@ -556,9 +556,8 @@
                 int id = allocateCompileTaskId(method, entryBCI);
                 HotSpotBackend backend = runtime.getHostBackend();
                 CompilationTask task = new CompilationTask(backend, method, entryBCI, id);
-                boolean isLambdaMethod = (method.getName().contains("lambda$main$") & method.isSynthetic());
 
-                if (blocking || isLambdaMethod) {
+                if (blocking) {
                     task.runCompilation(true);
                 } else {
                     try {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Wed Jan 22 21:34:00 2014 -0800
@@ -26,6 +26,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CodeUtil.DefaultRefMapFormatter;
 import com.oracle.graal.api.code.CodeUtil.RefMapFormatter;
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
@@ -65,7 +66,7 @@
             HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
             addExceptionHandlersComment(compResult, hcf);
             Register fp = regConfig.getFrameRegister();
-            RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0);
+            RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.arch, target.wordSize, fp, 0);
             for (Infopoint infopoint : compResult.getInfopoints()) {
                 if (infopoint instanceof Call) {
                     Call call = (Call) infopoint;
@@ -190,16 +191,16 @@
         return installMethod(hotspotMethod, compResult);
     }
 
-    public InstalledCode addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+    public HotSpotNmethod addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
         HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotInstalledCode icode = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
+        HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
         HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(target.arch, javaMethod, compResult);
         CompilerToVM vm = runtime.getCompilerToVM();
-        CodeInstallResult result = vm.installCode(compiled, icode, null);
+        CodeInstallResult result = vm.installCode(compiled, code, null);
         if (result != CodeInstallResult.OK) {
             return null;
         }
-        return icode;
+        return code;
     }
 
     public boolean needsDataPatch(Constant constant) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Wed Jan 22 21:34:00 2014 -0800
@@ -118,8 +118,8 @@
 
     @MacroSubstitution(macro = ClassIsInstanceNode.class, isStatic = false)
     @MethodSubstitution(isStatic = false)
-    public static boolean isInstance(final Class<?> thisObj, Object obj) {
-        return !isPrimitive(thisObj) && ConditionalNode.materializeIsInstance(thisObj, obj);
+    public static boolean isInstance(Class<?> thisObj, Object obj) {
+        return ConditionalNode.materializeIsInstance(thisObj, obj);
     }
 
     @MacroSubstitution(macro = ClassCastNode.class, isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Jan 22 21:34:00 2014 -0800
@@ -187,7 +187,7 @@
         BeginNode anchorNode = BeginNode.anchor();
         Word hub = loadWordFromObject(mirror, klassOffset());
         Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode);
-        if (!checkUnknownSubType(hub, objectHub)) {
+        if (hub.equal(0) || !checkUnknownSubType(hub, objectHub)) {
             return falseValue;
         }
         return trueValue;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Wed Jan 22 21:34:00 2014 -0800
@@ -521,7 +521,7 @@
                     StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod());
                     InliningUtil.inline(invoke, inlineeGraph, false);
 
-                    List<ReturnNode> rets = graph.getNodes().filter(ReturnNode.class).snapshot();
+                    List<ReturnNode> rets = graph.getNodes(ReturnNode.class).snapshot();
                     for (ReturnNode ret : rets) {
                         returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass());
                         String msg = "unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d";
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Wed Jan 22 21:34:00 2014 -0800
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.Register.RegisterCategory;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 
 /**
  * Represents the HSAIL architecture.
@@ -166,39 +165,16 @@
         Register reg;
         int encoding = 0;
         String regPrefix = null;
-        String argType = arg.getKind().getJavaName();
-        if (argType.equals("double") || argType.equals("long")) {
+        Kind kind = arg.getKind();
+        if (kind == Kind.Double || kind == Kind.Long) {
             regPrefix = "$d";
-        } else if (argType.equals("int") || argType.equals("float")) {
+        } else if (kind == Kind.Int || kind == Kind.Float || kind == Kind.NarrowOop) {
             regPrefix = "$s";
         } else {
             regPrefix = "$d";
         }
-        switch (argType) {
-            case "float":
-                reg = asFloatReg(arg);
-                encoding = reg.encoding();
-                break;
-            case "int":
-                reg = asIntReg(arg);
-                encoding = reg.encoding();
-                break;
-            case "long":
-                reg = asLongReg(arg);
-                encoding = reg.encoding();
-                break;
-            case "double":
-                reg = asDoubleReg(arg);
-                encoding = reg.encoding();
-                break;
-            case "Object":
-                reg = asObjectReg(arg);
-                encoding = reg.encoding();
-                break;
-            default:
-                GraalInternalError.shouldNotReachHere();
-                break;
-        }
+        reg = asRegister(arg);
+        encoding = reg.encoding();
         return new String(regPrefix + encoding);
     }
 
@@ -217,6 +193,7 @@
                 case Int:
                 case Long:
                 case Object:
+                case NarrowOop:
                     return true;
             }
         } else if (category == FPU) {
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java	Wed Jan 22 21:34:00 2014 -0800
@@ -150,6 +150,7 @@
             case Short:
             case Byte:
             case Float:
+            case NarrowOop:
                 return regBitness32.clone();
             case Long:
             case Double:
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jan 22 21:34:00 2014 -0800
@@ -120,7 +120,6 @@
 
         private ValueNode methodSynchronizedObject;
         private ExceptionDispatchBlock unwindBlock;
-        private Block returnBlock;
 
         private FixedWithNextNode lastInstr;                 // the last instruction added
 
@@ -198,7 +197,6 @@
             this.stream = new BytecodeStream(method.getCode());
             this.constantPool = method.getConstantPool();
             unwindBlock = null;
-            returnBlock = null;
             methodSynchronizedObject = null;
             this.currentGraph = graph;
             this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
@@ -270,7 +268,6 @@
             for (Block block : blockMap.blocks) {
                 processBlock(block);
             }
-            processBlock(returnBlock);
             processBlock(unwindBlock);
 
             Debug.dump(currentGraph, "After bytecode parsing");
@@ -305,16 +302,6 @@
             return unwindBlock;
         }
 
-        private Block returnBlock(int bci) {
-            if (returnBlock == null) {
-                returnBlock = new Block();
-                returnBlock.startBci = bci;
-                returnBlock.endBci = bci;
-                returnBlock.blockID = Integer.MAX_VALUE;
-            }
-            return returnBlock;
-        }
-
         public BytecodeStream stream() {
             return stream;
         }
@@ -1264,11 +1251,18 @@
         }
 
         private void genReturn(ValueNode x) {
+            frameState.setRethrowException(false);
             frameState.clearStack();
-            if (x != null) {
-                frameState.push(x.kind(), x);
+            if (graphBuilderConfig.eagerInfopointMode()) {
+                append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci())));
             }
-            appendGoto(createTarget(returnBlock(bci()), frameState));
+
+            synchronizedEpilogue(FrameState.AFTER_BCI, x);
+            if (frameState.lockDepth() != 0) {
+                throw new BailoutException("unbalanced monitors");
+            }
+
+            append(new ReturnNode(x));
         }
 
         private MonitorEnterNode genMonitorEnter(ValueNode x) {
@@ -1648,10 +1642,7 @@
                 ((MergeNode) lastInstr).setStateAfter(frameState.create(bci));
             }
 
-            if (block == returnBlock) {
-                frameState.setRethrowException(false);
-                createReturn();
-            } else if (block == unwindBlock) {
+            if (block == unwindBlock) {
                 frameState.setRethrowException(false);
                 createUnwind();
             } else if (block instanceof ExceptionDispatchBlock) {
@@ -1692,26 +1683,12 @@
             append(new UnwindNode(exception));
         }
 
-        private void createReturn() {
-            Kind returnKind = method.getSignature().getReturnKind().getStackKind();
-            ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind);
-            assert frameState.stackSize() == 0;
-
-            if (graphBuilderConfig.eagerInfopointMode()) {
-                append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci())));
-            }
-
-            synchronizedEpilogue(FrameState.AFTER_BCI, x);
-            if (frameState.lockDepth() != 0) {
-                throw new BailoutException("unbalanced monitors");
-            }
-
-            append(new ReturnNode(x));
-        }
-
         private void synchronizedEpilogue(int bci, ValueNode returnValue) {
             if (Modifier.isSynchronized(method.getModifiers())) {
                 MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue);
+                if (returnValue != null) {
+                    frameState.push(returnValue.kind(), returnValue);
+                }
                 monitorExit.setStateAfter(frameState.create(bci));
                 assert !frameState.rethrowException();
             }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Wed Jan 22 21:34:00 2014 -0800
@@ -343,24 +343,12 @@
         }
     }
 
-    /**
-     * Initializes a reference map that covers all registers of the target architecture.
-     */
-    public BitSet initRegisterRefMap() {
-        return new BitSet(target.arch.getRegisterReferenceMapBitCount());
-    }
-
-    /**
-     * Initializes a reference map. Initially, the size is large enough to cover all the slots in
-     * the frame. If the method has incoming reference arguments on the stack, the reference map
-     * might grow later when such a reference is set.
-     */
-    public BitSet initFrameRefMap() {
-        BitSet frameRefMap = new BitSet(frameSize() / target.wordSize);
+    public ReferenceMap initReferenceMap(boolean canHaveRegisters) {
+        ReferenceMap refMap = new ReferenceMap(canHaveRegisters ? target.arch.getRegisterReferenceMapBitCount() : 0, frameSize() / target.wordSize);
         for (StackSlot slot : objectStackSlots) {
-            setReference(slot, null, frameRefMap);
+            setReference(slot, refMap);
         }
-        return frameRefMap;
+        return refMap;
     }
 
     /**
@@ -369,16 +357,22 @@
      * {@link Constant} is automatically tracked.
      * 
      * @param location The location to be added to the reference map.
-     * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}.
-     * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
+     * @param refMap A reference map, as created by {@link #initReferenceMap(boolean)}.
      */
-    public void setReference(Value location, BitSet registerRefMap, BitSet frameRefMap) {
-        if (location.getKind() == Kind.Object) {
+    public void setReference(Value location, ReferenceMap refMap) {
+        Kind kind = location.getKind();
+        if (kind == Kind.Object || kind == Kind.NarrowOop) {
             if (isRegister(location)) {
-                registerRefMap.set(asRegister(location).number);
+                refMap.setRegister(asRegister(location).number, kind == Kind.NarrowOop);
             } else if (isStackSlot(location)) {
-                int index = indexForStackSlot(asStackSlot(location));
-                frameRefMap.set(index);
+                if (kind == Kind.NarrowOop) {
+                    int offset = offsetForStackSlot(asStackSlot(location));
+                    assert offset % target.wordSize == 0 || offset % target.wordSize == target.wordSize / 2;
+                    refMap.setStackSlot(offset / target.wordSize, offset % target.wordSize == 0, offset % target.wordSize != 0);
+                } else {
+                    int index = indexForStackSlot(asStackSlot(location));
+                    refMap.setStackSlot(index, false, false);
+                }
             } else {
                 assert isConstant(location);
             }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Jan 22 21:34:00 2014 -0800
@@ -116,8 +116,7 @@
      * @param canHaveRegisters True if there can be any register map entries.
      */
     public void initDebugInfo(FrameMap frameMap, boolean canHaveRegisters) {
-        BitSet registerRefMap = (canHaveRegisters ? frameMap.initRegisterRefMap() : null);
-        debugInfo = new DebugInfo(topFrame, registerRefMap, frameMap.initFrameRefMap());
+        debugInfo = new DebugInfo(topFrame, frameMap.initReferenceMap(canHaveRegisters));
     }
 
     /**
@@ -129,16 +128,7 @@
      * @param frameMap The frame map.
      */
     public void markLocation(Value location, FrameMap frameMap) {
-        if (location.getKind() == Kind.Object) {
-            if (isRegister(location)) {
-                debugInfo.getRegisterRefMap().set(asRegister(location).number);
-            } else if (isStackSlot(location)) {
-                int index = frameMap.indexForStackSlot(asStackSlot(location));
-                debugInfo.getFrameRefMap().set(index);
-            } else {
-                assert isConstant(location);
-            }
-        }
+        frameMap.setReference(location, debugInfo.getReferenceMap());
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -104,12 +104,16 @@
         if (condition() instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition();
             return graph().unique(new GuardNode(negation.getInput(), getGuard(), reason, action, !negated, speculation));
-        }
-        if (condition() instanceof LogicConstantNode) {
+        } else if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
             if (c.getValue() != negated) {
                 return graph().start();
             }
+        } else if (negated && condition() instanceof ShortCircuitOrNode) {
+            ShortCircuitOrNode or = (ShortCircuitOrNode) condition();
+            GuardNode firstGuard = graph().unique(new GuardNode(or.getX(), getGuard(), reason, action, !or.isXNegated(), speculation));
+            GuardNode secondGuard = graph().unique(new GuardNode(or.getY(), firstGuard, reason, action, !or.isYNegated(), speculation));
+            return secondGuard;
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -371,6 +371,29 @@
                 }
             }
         }
+        if (trueSuccessor().next() instanceof ReturnNode && falseSuccessor().next() instanceof ReturnNode) {
+            ReturnNode trueEnd = (ReturnNode) trueSuccessor().next();
+            ReturnNode falseEnd = (ReturnNode) falseSuccessor().next();
+            ValueNode trueValue = trueEnd.result();
+            ValueNode falseValue = falseEnd.result();
+            ConditionalNode conditional = null;
+            if (trueValue != null) {
+                if (trueValue.kind() != falseValue.kind()) {
+                    return false;
+                }
+                if (trueValue.kind() != Kind.Int && trueValue.kind() != Kind.Long) {
+                    return false;
+                }
+                conditional = canonicalizeConditionalCascade(trueValue, falseValue);
+                if (conditional == null) {
+                    return false;
+                }
+            }
+            ReturnNode newReturn = graph().add(new ReturnNode(conditional));
+            replaceAtPredecessor(newReturn);
+            GraphUtil.killCFG(this);
+            return true;
+        }
         return false;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -34,4 +36,6 @@
     }
 
     public abstract MemoryNode getLastLocationAccess(LocationIdentity locationIdentity);
+
+    public abstract Set<LocationIdentity> getLocations();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -24,6 +24,8 @@
 
 import static com.oracle.graal.graph.iterators.NodePredicates.*;
 
+import java.util.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -194,6 +196,35 @@
                 tool.addToWorkList(newEnd.predecessor()); // ?
             }
             graph().reduceTrivialMerge(this);
+        } else if (next instanceof ReturnNode) {
+            ReturnNode returnNode = (ReturnNode) next;
+            if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) {
+                return;
+            }
+            List<PhiNode> phis = phis().snapshot();
+            for (PhiNode phi : phis) {
+                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
+                    if (usage != returnNode) {
+                        return;
+                    }
+                }
+            }
+
+            PhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (PhiNode) returnNode.result();
+            List<AbstractEndNode> endNodes = forwardEnds().snapshot();
+            for (AbstractEndNode end : endNodes) {
+                ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
+                end.replaceAtPredecessor(newReturn);
+            }
+            GraphUtil.killCFG(this);
+            for (AbstractEndNode end : endNodes) {
+                end.safeDelete();
+            }
+            for (PhiNode phi : phis) {
+                if (phi.isAlive() && phi.usages().isEmpty()) {
+                    GraphUtil.killWithUnusedFloatingInputs(phi);
+                }
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -28,7 +28,7 @@
 /**
  * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call.
  */
-@NodeInfo(nameTemplate = "Local({p#index})")
+@NodeInfo(nameTemplate = "Param({p#index})")
 public final class ParameterNode extends AbstractLocalNode implements IterableNodeType {
 
     public ParameterNode(int index, Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class ReturnNode extends ControlSinkNode implements LIRLowerable {
+public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
 
     @Input private ValueNode result;
     @Input private MemoryMapNode memoryMap;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -62,7 +62,11 @@
         if (mirror().isConstant()) {
             Class clazz = (Class) mirror().asConstant().asObject();
             ResolvedJavaType t = tool.getMetaAccess().lookupJavaType(clazz);
-            return graph().unique(new InstanceOfNode(t, object(), null));
+            if (t.isPrimitive()) {
+                return LogicConstantNode.contradiction(graph());
+            } else {
+                return graph().unique(new InstanceOfNode(t, object(), null));
+            }
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -60,6 +60,9 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
+        if (usages().isEmpty() && (isStatic() || ObjectStamp.isObjectNonNull(object().stamp()))) {
+            return null;
+        }
         MetaAccessProvider metaAccess = tool.getMetaAccess();
         if (tool.canonicalizeReads() && metaAccess != null) {
             ConstantNode constant = asConstant(metaAccess);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Jan 22 21:34:00 2014 -0800
@@ -84,6 +84,7 @@
             return false;
         }
 
+        @Override
         public Set<LocationIdentity> getLocations() {
             return lastMemorySnapshot.keySet();
         }
@@ -111,6 +112,46 @@
         }
     }
 
+    public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List<? extends MemoryMapNode> states) {
+        MemoryMapImpl newState = new MemoryMapImpl();
+
+        Set<LocationIdentity> keys = new HashSet<>();
+        for (MemoryMapNode other : states) {
+            keys.addAll(other.getLocations());
+        }
+        assert !keys.contains(FINAL_LOCATION);
+
+        for (LocationIdentity key : keys) {
+            int mergedStatesCount = 0;
+            boolean isPhi = false;
+            MemoryNode merged = null;
+            for (MemoryMapNode state : states) {
+                MemoryNode last = state.getLastLocationAccess(key);
+                if (isPhi) {
+                    merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last));
+                } else {
+                    if (merged == last) {
+                        // nothing to do
+                    } else if (merged == null) {
+                        merged = last;
+                    } else {
+                        MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
+                        for (int j = 0; j < mergedStatesCount; j++) {
+                            phi.addInput(ValueNodeUtil.asNode(merged));
+                        }
+                        phi.addInput(ValueNodeUtil.asNode(last));
+                        merged = phi;
+                        isPhi = true;
+                    }
+                }
+                mergedStatesCount++;
+            }
+            newState.lastMemorySnapshot.put(key, merged);
+        }
+        return newState;
+
+    }
+
     private static class CollectMemoryCheckpointsClosure extends NodeIteratorClosure<Set<LocationIdentity>> {
 
         private final Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops;
@@ -238,42 +279,7 @@
 
         @Override
         protected MemoryMapImpl merge(MergeNode merge, List<MemoryMapImpl> states) {
-            MemoryMapImpl newState = new MemoryMapImpl();
-
-            Set<LocationIdentity> keys = new HashSet<>();
-            for (MemoryMapImpl other : states) {
-                keys.addAll(other.lastMemorySnapshot.keySet());
-            }
-            assert !keys.contains(FINAL_LOCATION);
-
-            for (LocationIdentity key : keys) {
-                int mergedStatesCount = 0;
-                boolean isPhi = false;
-                MemoryNode merged = null;
-                for (MemoryMapImpl state : states) {
-                    MemoryNode last = state.getLastLocationAccess(key);
-                    if (isPhi) {
-                        merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last));
-                    } else {
-                        if (merged == last) {
-                            // nothing to do
-                        } else if (merged == null) {
-                            merged = last;
-                        } else {
-                            MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
-                            for (int j = 0; j < mergedStatesCount; j++) {
-                                phi.addInput(ValueNodeUtil.asNode(merged));
-                            }
-                            phi.addInput(ValueNodeUtil.asNode(last));
-                            merged = phi;
-                            isPhi = true;
-                        }
-                    }
-                    mergedStatesCount++;
-                }
-                newState.lastMemorySnapshot.put(key, merged);
-            }
-            return newState;
+            return mergeMemoryMaps(merge, states);
         }
 
         @Override
@@ -302,19 +308,21 @@
                 modifiedLocations.addAll(initialState.lastMemorySnapshot.keySet());
             }
 
-            Map<LocationIdentity, PhiNode> phis = new HashMap<>();
+            Map<LocationIdentity, MemoryPhiNode> phis = new HashMap<>();
             for (LocationIdentity location : modifiedLocations) {
                 MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location));
                 phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location)));
                 phis.put(location, phi);
-                initialState.lastMemorySnapshot.put(location, phi);
+            }
+            for (Map.Entry<LocationIdentity, MemoryPhiNode> entry : phis.entrySet()) {
+                initialState.lastMemorySnapshot.put(entry.getKey(), entry.getValue());
             }
 
             LoopInfo<MemoryMapImpl> loopInfo = ReentrantNodeIterator.processLoop(this, loop, initialState);
 
             for (Map.Entry<LoopEndNode, MemoryMapImpl> entry : loopInfo.endStates.entrySet()) {
                 int endIndex = loop.phiPredecessorIndex(entry.getKey());
-                for (Map.Entry<LocationIdentity, PhiNode> phiEntry : phis.entrySet()) {
+                for (Map.Entry<LocationIdentity, MemoryPhiNode> phiEntry : phis.entrySet()) {
                     LocationIdentity key = phiEntry.getKey();
                     PhiNode phi = phiEntry.getValue();
                     phi.initializeValueAt(endIndex, ValueNodeUtil.asNode(entry.getValue().getLastLocationAccess(key)));
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Jan 22 21:34:00 2014 -0800
@@ -27,6 +27,7 @@
 import java.util.*;
 import java.util.Map.Entry;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -107,7 +108,7 @@
 
         private void processGuard(Node node) {
             GuardNode guard = (GuardNode) node;
-            if (guard.negated() && guard.condition() instanceof IsNullNode) {
+            if (guard.negated() && guard.condition() instanceof IsNullNode && (guard.getSpeculation() == null || guard.getSpeculation().equals(Constant.NULL_OBJECT))) {
                 ValueNode obj = ((IsNullNode) guard.condition()).object();
                 nullGuarded.put(obj, guard);
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Jan 22 21:34:00 2014 -0800
@@ -1295,8 +1295,10 @@
      */
     public static Map<Node, Node> inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
         final NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
-        StructuredGraph graph = invoke.asNode().graph();
+        FixedNode invokeNode = invoke.asNode();
+        StructuredGraph graph = invokeNode.graph();
         assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal();
+        Kind returnKind = invokeNode.kind();
 
         FrameState stateAfter = invoke.stateAfter();
         assert stateAfter == null || stateAfter.isAlive();
@@ -1305,7 +1307,7 @@
         }
 
         ArrayList<Node> nodes = new ArrayList<>(inlineGraph.getNodes().count());
-        ReturnNode returnNode = null;
+        ArrayList<ReturnNode> returnNodes = new ArrayList<>(4);
         UnwindNode unwindNode = null;
         final StartNode entryPointNode = inlineGraph.start();
         FixedNode firstCFGNode = entryPointNode.next();
@@ -1318,8 +1320,7 @@
             } else {
                 nodes.add(node);
                 if (node instanceof ReturnNode) {
-                    assert returnNode == null;
-                    returnNode = (ReturnNode) node;
+                    returnNodes.add((ReturnNode) node);
                 } else if (node instanceof UnwindNode) {
                     assert unwindNode == null;
                     unwindNode = (UnwindNode) node;
@@ -1327,7 +1328,7 @@
             }
         }
 
-        final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invoke.asNode());
+        final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode);
         DuplicationReplacement localReplacement = new DuplicationReplacement() {
 
             public Node replacement(Node node) {
@@ -1340,12 +1341,12 @@
             }
         };
 
-        assert invoke.asNode().successors().first() != null : invoke;
-        assert invoke.asNode().predecessor() != null;
+        assert invokeNode.successors().first() != null : invoke;
+        assert invokeNode.predecessor() != null;
 
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement);
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
-        invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate);
+        invokeNode.replaceAtPredecessor(firstCFGNodeDuplicate);
 
         FrameState stateAtExceptionEdge = null;
         if (invoke instanceof InvokeWithExceptionNode) {
@@ -1400,7 +1401,8 @@
                 if (frameState != null) {
                     assert frameState.bci != FrameState.BEFORE_BCI : frameState;
                     if (frameState.bci == FrameState.AFTER_BCI) {
-                        frameState.replaceAndDelete(stateAfter);
+                        frameState.replaceAndDelete(returnKind == Kind.Void ? stateAfter : stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), returnKind,
+                                        frameState.stackAt(0)));
                     } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) {
                         if (frameState.isAlive()) {
                             assert stateAtExceptionEdge != null;
@@ -1413,7 +1415,7 @@
                         if (frameState.outerFrameState() == null) {
                             assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method() == inlineGraph.method();
                             if (outerFrameState == null) {
-                                outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.asNode().kind());
+                                outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invokeNode.kind());
                                 outerFrameState.setDuringCall(true);
                             }
                             frameState.setOuterFrameState(outerFrameState);
@@ -1430,27 +1432,55 @@
         } else {
             assert checkContainsOnlyInvalidOrAfterFrameState(duplicates);
         }
-        Node returnValue = null;
-        if (returnNode != null) {
-            if (returnNode.result() instanceof ParameterNode) {
-                returnValue = localReplacement.replacement(returnNode.result());
-            } else if (returnNode.result() != null) {
-                returnValue = duplicates.get(returnNode.result());
+        if (!returnNodes.isEmpty()) {
+            FixedNode n = invoke.next();
+            invoke.setNext(null);
+            if (returnNodes.size() == 1) {
+                ReturnNode returnNode = (ReturnNode) duplicates.get(returnNodes.get(0));
+                Node returnValue = returnNode.result();
+                invokeNode.replaceAtUsages(returnValue);
+                returnNode.clearInputs();
+                returnNode.replaceAndDelete(n);
+            } else {
+                ArrayList<ReturnNode> returnDuplicates = new ArrayList<>(returnNodes.size());
+                for (ReturnNode returnNode : returnNodes) {
+                    returnDuplicates.add((ReturnNode) duplicates.get(returnNode));
+                }
+                MergeNode merge = graph.add(new MergeNode());
+                merge.setStateAfter(stateAfter);
+                ValueNode returnValue = mergeReturns(merge, returnDuplicates);
+                invokeNode.replaceAtUsages(returnValue);
+                merge.setNext(n);
             }
-            invoke.asNode().replaceAtUsages(returnValue);
-            Node returnDuplicate = duplicates.get(returnNode);
-            returnDuplicate.clearInputs();
-            Node n = invoke.next();
-            invoke.setNext(null);
-            returnDuplicate.replaceAndDelete(n);
         }
 
-        invoke.asNode().replaceAtUsages(null);
-        GraphUtil.killCFG(invoke.asNode());
+        invokeNode.replaceAtUsages(null);
+        GraphUtil.killCFG(invokeNode);
 
         return duplicates;
     }
 
+    public static ValueNode mergeReturns(MergeNode merge, List<? extends ReturnNode> returnNodes) {
+        PhiNode returnValuePhi = null;
+
+        for (ReturnNode returnNode : returnNodes) {
+            // create and wire up a new EndNode
+            EndNode endNode = merge.graph().add(new EndNode());
+            merge.addForwardEnd(endNode);
+
+            if (returnNode.result() != null) {
+                if (returnValuePhi == null) {
+                    returnValuePhi = merge.graph().addWithoutUnique(new PhiNode(returnNode.result().kind(), merge));
+                }
+                returnValuePhi.addInput(returnNode.result());
+            }
+            returnNode.clearInputs();
+            returnNode.replaceAndDelete(endNode);
+
+        }
+        return returnValuePhi;
+    }
+
     private static boolean checkContainsOnlyInvalidOrAfterFrameState(Map<Node, Node> duplicates) {
         for (Node node : duplicates.values()) {
             if (node instanceof FrameState) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Wed Jan 22 21:34:00 2014 -0800
@@ -153,7 +153,7 @@
     }
 
     private static boolean doesNotAlwaysDeopt(StructuredGraph graph) {
-        return graph.getNodes().filter(ReturnNode.class).iterator().hasNext();
+        return graph.getNodes(ReturnNode.class).isNotEmpty();
     }
 
     private void computeLoopFactors() {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Jan 22 21:34:00 2014 -0800
@@ -61,4 +61,17 @@
     public void afterSplit(AbstractBeginNode node) {
         // empty default implementation
     }
+
+    public static final class EmptyState extends MergeableState<EmptyState> {
+
+        @Override
+        public EmptyState clone() {
+            return this;
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<EmptyState> withStates) {
+            return true;
+        }
+    }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Jan 22 21:34:00 2014 -0800
@@ -262,6 +262,7 @@
 
     @Override
     protected void run(StructuredGraph graph) {
+        assert GraphOrder.assertNonCyclicGraph(graph);
         cfg = ControlFlowGraph.compute(graph, true, true, true, true);
         earliestCache = graph.createNodeMap();
         blockToNodesMap = new BlockMap<>(cfg);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Jan 22 21:34:00 2014 -0800
@@ -26,102 +26,88 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.graph.*;
 
-public final class GraphOrder implements Iterable<Node> {
-
-    private final ArrayList<Node> nodes = new ArrayList<>();
+public final class GraphOrder {
 
     private GraphOrder() {
     }
 
-    public static GraphOrder forwardGraph(Graph graph) {
-        GraphOrder result = new GraphOrder();
-
+    /**
+     * Asserts that there are no (invalid) cycles in the given graph. First, an ordered list of all
+     * nodes in the graph (a total ordering) is created. A second run over this list checks whether
+     * inputs are scheduled before their usages.
+     * 
+     * @param graph the graph to be checked.
+     * @throws AssertionError if a cycle was detected.
+     */
+    public static boolean assertNonCyclicGraph(StructuredGraph graph) {
+        List<Node> order = createOrder(graph);
         NodeBitMap visited = graph.createNodeBitMap();
+        visited.clearAll();
+        for (Node node : order) {
+            if (node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode) {
+                assert visited.isMarked(((PhiNode) node).valueAt(0));
+                // nothing to do
+            } else {
+                for (Node input : node.inputs()) {
+                    if (!visited.isMarked(input)) {
+                        if (input instanceof FrameState && node instanceof StateSplit && input == ((StateSplit) node).stateAfter()) {
+                            // nothing to do - after frame states are known, allowed cycles
+                        } else {
+                            assert false : "cycle detected: " + node + " -> " + input;
+                        }
+                    }
+                }
+            }
+            visited.mark(node);
+        }
 
-        for (ControlSinkNode node : graph.getNodes().filter(ControlSinkNode.class)) {
-            result.visitForward(visited, node);
-        }
-        return result;
+        return true;
     }
 
-    public static GraphOrder backwardGraph(Graph graph) {
-        GraphOrder result = new GraphOrder();
-
-        NodeBitMap visited = graph.createNodeBitMap();
+    private static List<Node> createOrder(StructuredGraph graph) {
+        final ArrayList<Node> nodes = new ArrayList<>();
+        final NodeBitMap visited = graph.createNodeBitMap();
 
-        for (Node node : forwardGraph(graph)) {
-            result.visitBackward(visited, node);
-        }
-        return result;
+        new PostOrderNodeIterator<MergeableState.EmptyState>(graph.start(), new MergeableState.EmptyState()) {
+            @Override
+            protected void node(FixedNode node) {
+                visitForward(nodes, visited, node, false);
+            }
+        }.apply();
+        return nodes;
     }
 
-    private void visitForward(NodeBitMap visited, Node node) {
+    private static void visitForward(ArrayList<Node> nodes, NodeBitMap visited, Node node, boolean floatingOnly) {
         if (node != null && !visited.isMarked(node)) {
+            assert !floatingOnly || !(node instanceof FixedNode) : "unexpected reference to fixed node: " + node;
             visited.mark(node);
-            if (node.predecessor() != null) {
-                visitForward(visited, node.predecessor());
+            FrameState stateAfter = null;
+            if (node instanceof StateSplit) {
+                stateAfter = ((StateSplit) node).stateAfter();
             }
-            if (node instanceof MergeNode) {
-                // make sure that the cfg predecessors of a MergeNode are processed first
-                MergeNode merge = (MergeNode) node;
-                for (int i = 0; i < merge.forwardEndCount(); i++) {
-                    visitForward(visited, merge.forwardEndAt(i));
+            for (Node input : node.inputs()) {
+                if (input != stateAfter) {
+                    visitForward(nodes, visited, input, true);
                 }
             }
-            for (Node input : node.inputs()) {
-                visitForward(visited, input);
-            }
-            if (node instanceof LoopBeginNode) {
-                LoopBeginNode loopBegin = (LoopBeginNode) node;
-                for (LoopEndNode loopEnd : loopBegin.loopEnds()) {
-                    visitForward(visited, loopEnd);
+            if (node instanceof EndNode) {
+                EndNode end = (EndNode) node;
+                for (PhiNode phi : end.merge().phis()) {
+                    visitForward(nodes, visited, phi.valueAt(end), true);
                 }
             }
             nodes.add(node);
-        }
-    }
-
-    private void visitBackward(NodeBitMap visited, Node node) {
-        if (node != null && !visited.isMarked(node)) {
-            visited.mark(node);
-            for (Node successor : node.successors()) {
-                visitBackward(visited, successor);
+            if (node instanceof MergeNode) {
+                for (PhiNode phi : ((MergeNode) node).phis()) {
+                    visited.mark(phi);
+                    nodes.add(phi);
+                }
             }
-            for (Node usage : node.usages()) {
-                visitBackward(visited, usage);
+            if (stateAfter != null) {
+                visitForward(nodes, visited, stateAfter, true);
             }
-            nodes.add(node);
         }
     }
-
-    @Override
-    public Iterator<Node> iterator() {
-        return new Iterator<Node>() {
-
-            private int pos = 0;
-
-            private void removeDeleted() {
-                while (pos < nodes.size() && nodes.get(pos).isDeleted()) {
-                    pos++;
-                }
-            }
-
-            @Override
-            public boolean hasNext() {
-                removeDeleted();
-                return pos < nodes.size();
-            }
-
-            @Override
-            public Node next() {
-                return nodes.get(pos++);
-            }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
-    }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Jan 22 21:34:00 2014 -0800
@@ -443,9 +443,9 @@
                 protected void doState(LIRFrameState state) {
                     if (state.hasDebugInfo()) {
                         DebugInfo di = state.debugInfo();
-                        stateString.append(debugInfoToString(di.getBytecodePosition(), di.getRegisterRefMap(), di.getFrameRefMap(), di.getCalleeSaveInfo(), target.arch));
+                        stateString.append(debugInfoToString(di.getBytecodePosition(), di.getReferenceMap(), di.getCalleeSaveInfo(), target.arch));
                     } else {
-                        stateString.append(debugInfoToString(state.topFrame, null, null, null, target.arch));
+                        stateString.append(debugInfoToString(state.topFrame, null, null, target.arch));
                     }
                 }
             });
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Wed Jan 22 21:34:00 2014 -0800
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CodeUtil.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 
@@ -111,26 +112,38 @@
         end("compilation");
     }
 
+    private static class ArchitectureRegFormatter implements RefMapFormatter {
+
+        private final Register[] registers;
+
+        public ArchitectureRegFormatter(Architecture arch) {
+            registers = arch.getRegisters();
+        }
+
+        public String formatStackSlot(int frameRefMapIndex) {
+            return null;
+        }
+
+        public String formatRegister(int regRefMapIndex) {
+            return registers[regRefMapIndex].toString();
+        }
+    }
+
     /**
      * Formats given debug info as a multi line string.
      */
-    protected String debugInfoToString(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, RegisterSaveLayout calleeSaveInfo, Architecture arch) {
+    protected String debugInfoToString(BytecodePosition codePos, ReferenceMap refMap, RegisterSaveLayout calleeSaveInfo, Architecture arch) {
         StringBuilder sb = new StringBuilder();
 
-        if (registerRefMap != null) {
+        if (refMap != null && refMap.hasRegisterRefMap()) {
             sb.append("reg-ref-map:");
-            Register[] registers = arch.getRegisters();
-            for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 1)) {
-                sb.append(' ').append(arch == null ? "r" + reg : registers[reg]);
-            }
+            refMap.appendRegisterMap(sb, arch != null ? new ArchitectureRegFormatter(arch) : null);
             sb.append("\n");
         }
 
-        if (frameRefMap != null) {
+        if (refMap != null && refMap.hasFrameRefMap()) {
             sb.append("frame-ref-map:");
-            for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + 1)) {
-                sb.append(' ').append("s").append(slot);
-            }
+            refMap.appendFrameMap(sb, null);
             sb.append("\n");
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Jan 22 21:34:00 2014 -0800
@@ -36,9 +36,8 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.Mark;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
@@ -623,43 +622,49 @@
         assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders);
 
         new FloatingReadPhase(FloatingReadPhase.ExecutionMode.ANALYSIS_ONLY).apply(snippetCopy);
-        this.memoryMap = null;
 
         this.snippet = snippetCopy;
-        ReturnNode retNode = null;
+        List<ReturnNode> returnNodes = new ArrayList<>(4);
+        List<MemoryMapNode> memMaps = new ArrayList<>(4);
         StartNode entryPointNode = snippet.start();
-        nodes = new ArrayList<>(snippet.getNodeCount());
-        boolean seenReturn = false;
-        boolean containsMemoryMap = false;
-        for (Node node : snippet.getNodes()) {
-            if (node == entryPointNode || node == entryPointNode.stateAfter()) {
-                // Do nothing.
-            } else {
-                nodes.add(node);
-                if (node instanceof ReturnNode) {
-                    retNode = (ReturnNode) node;
-                    NodeIterable<MemoryMapNode> memstates = retNode.inputs().filter(MemoryMapNode.class);
-                    assert memstates.count() == 1;
-                    memoryMap = memstates.first();
-                    retNode.replaceFirstInput(memoryMap, null);
-                    memoryMap.safeDelete();
-
-                    assert !seenReturn : "can handle only one ReturnNode";
-                    seenReturn = true;
-                } else if (node instanceof MemoryMapNode) {
-                    containsMemoryMap = true;
-                }
+        for (ReturnNode retNode : snippet.getNodes(ReturnNode.class)) {
+            MemoryMapNode memMap = retNode.getMemoryMap();
+            memMaps.add(memMap);
+            retNode.setMemoryMap(null);
+            returnNodes.add(retNode);
+            if (memMap.usages().isEmpty()) {
+                memMap.safeDelete();
             }
         }
-        assert !containsMemoryMap;
+        assert snippet.getNodes().filter(MemoryMapNode.class).isEmpty();
+        if (returnNodes.isEmpty()) {
+            this.returnNode = null;
+            this.memoryMap = null;
+        } else if (returnNodes.size() == 1) {
+            this.returnNode = returnNodes.get(0);
+            this.memoryMap = memMaps.get(0);
+        } else {
+            MergeNode merge = snippet.add(new MergeNode());
+            ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes);
+            this.returnNode = snippet.add(new ReturnNode(returnValue));
+            this.memoryMap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps);
+            merge.setNext(this.returnNode);
+        }
 
         this.sideEffectNodes = curSideEffectNodes;
         this.deoptNodes = curDeoptNodes;
         this.stampNodes = curStampNodes;
-        this.returnNode = retNode;
+
+        nodes = new ArrayList<>(snippet.getNodeCount());
+        for (Node node : snippet.getNodes()) {
+            if (node != entryPointNode && node != entryPointNode.stateAfter()) {
+                nodes.add(node);
+            }
+        }
 
         Debug.metric(debugValueName("SnippetTemplateNodeCount", args)).add(nodes.size());
         args.info.notifyNewTemplate();
+        Debug.dump(snippet, "SnippetTemplate final state");
     }
 
     private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, VarargsPlaceholderNode[] placeholders) {
@@ -720,7 +725,7 @@
 
     /**
      * Nodes that inherit the {@link DeoptimizingNode#getDeoptimizationState()} from the replacee
-     * during insantiation.
+     * during instantiation.
      */
     private final ArrayList<DeoptimizingNode> deoptNodes;
 
@@ -737,7 +742,7 @@
     /**
      * map of killing locations to memory checkpoints (nodes).
      */
-    private MemoryMapNode memoryMap;
+    private final MemoryMapNode memoryMap;
 
     /**
      * Times instantiations of this template.
@@ -876,7 +881,7 @@
                         // MemoryCheckPoint inside the snippet graph
                         MemoryNode lastAccess = mmap.getLastLocationAccess(identity);
 
-                        assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)";
+                        assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kills the same location as the lowerable node?)";
                         if (usage instanceof MemoryAccess) {
                             MemoryAccess access = (MemoryAccess) usage;
                             if (access.getLastLocationAccess() == oldNode) {
@@ -961,6 +966,11 @@
                 return (MemoryNode) duplicates.get(ValueNodeUtil.asNode(lastLocationAccess));
             }
         }
+
+        @Override
+        public Set<LocationIdentity> getLocations() {
+            return memoryMap.getLocations();
+        }
     }
 
     /**
@@ -1014,25 +1024,18 @@
                 }
             }
 
-            for (ValueNode stampNode : stampNodes) {
-                Node stampDup = duplicates.get(stampNode);
-                ((ValueNode) stampDup).setStamp(((ValueNode) replacee).stamp());
-            }
+            updateStamps(replacee, duplicates);
 
             // Replace all usages of the replacee with the value returned by the snippet
             ValueNode returnValue = null;
             if (returnNode != null && !(replacee instanceof ControlSinkNode)) {
-                if (returnNode.result() instanceof ParameterNode) {
-                    returnValue = (ValueNode) replacements.get(returnNode.result());
-                } else if (returnNode.result() != null) {
-                    returnValue = (ValueNode) duplicates.get(returnNode.result());
-                }
-                Node returnDuplicate = duplicates.get(returnNode);
+                ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode);
+                returnValue = returnDuplicate.result();
                 MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
                 if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
                     replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap);
                 } else {
-                    assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages();
+                    assert returnValue != null || replacee.usages().isEmpty();
                     replacer.replace(replacee, returnValue, mmap);
                 }
                 if (returnDuplicate.isAlive()) {
@@ -1051,6 +1054,30 @@
         }
     }
 
+    private void propagateStamp(Node node) {
+        if (node instanceof PhiNode) {
+            PhiNode phi = (PhiNode) node;
+            if (phi.inferPhiStamp()) {
+                for (Node usage : node.usages()) {
+                    propagateStamp(usage);
+                }
+            }
+        }
+    }
+
+    private void updateStamps(ValueNode replacee, Map<Node, Node> duplicates) {
+        for (ValueNode stampNode : stampNodes) {
+            Node stampDup = duplicates.get(stampNode);
+            ((ValueNode) stampDup).setStamp(replacee.stamp());
+        }
+        for (ParameterNode paramNode : snippet.getNodes(ParameterNode.class)) {
+            for (Node usage : paramNode.usages()) {
+                Node usageDup = duplicates.get(usage);
+                propagateStamp(usageDup);
+            }
+        }
+    }
+
     /**
      * Gets a copy of the specialized graph.
      */
@@ -1097,23 +1124,14 @@
                     ((StateSplit) sideEffectDup).setStateAfter(((StateSplit) replacee).stateAfter());
                 }
             }
-            for (ValueNode stampNode : stampNodes) {
-                Node stampDup = duplicates.get(stampNode);
-                ((ValueNode) stampDup).setStamp(((ValueNode) replacee).stamp());
-            }
+            updateStamps(replacee, duplicates);
 
             // Replace all usages of the replacee with the value returned by the snippet
-            assert returnNode != null : replaceeGraph;
-            ValueNode returnValue = null;
-            if (returnNode.result() instanceof ParameterNode) {
-                returnValue = (ValueNode) replacements.get(returnNode.result());
-            } else {
-                returnValue = (ValueNode) duplicates.get(returnNode.result());
-            }
+            ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode);
+            ValueNode returnValue = returnDuplicate.result();
             assert returnValue != null || replacee.usages().isEmpty();
             replacer.replace(replacee, returnValue, new DuplicateMapper(duplicates, replaceeGraph.start()));
 
-            Node returnDuplicate = duplicates.get(returnNode);
             if (returnDuplicate.isAlive()) {
                 returnDuplicate.clearInputs();
                 returnDuplicate.replaceAndDelete(next);
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed Jan 22 21:34:00 2014 -0800
@@ -162,6 +162,7 @@
                 case Int:
                 case Long:
                 case Object:
+                case NarrowOop:
                     return true;
             }
         } else if (category == FPU) {
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -42,8 +42,8 @@
         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);
+        RootTestNode rootNode = new RootTestNode(fd, "constantValue", result);
+        InstalledCode installedCode = assertPartialEvalEquals("constant42", rootNode);
         Assert.assertTrue(installedCode.isValid());
         try {
             assertEquals(42, installedCode.execute(null, null, null));
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -45,7 +45,6 @@
 import com.oracle.graal.truffle.*;
 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 {
@@ -64,13 +63,13 @@
         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) {
+        return assertPartialEvalEquals(methodName, root, Arguments.EMPTY_ARGUMENTS);
     }
 
-    protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, FrameDescriptor descriptor, Arguments arguments) {
+    protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, Arguments arguments) {
         Assumptions assumptions = new Assumptions(true);
-        StructuredGraph actual = partialEval(root, descriptor, arguments, assumptions, true);
+        StructuredGraph actual = partialEval(root, arguments, assumptions, true);
         InstalledCode result = new TruffleCompilerImpl().compileMethodHelper(actual, GraphBuilderConfiguration.getDefault(), assumptions, root.toString());
         StructuredGraph expected = parseForComparison(methodName);
         removeFrameStates(actual);
@@ -78,21 +77,21 @@
         return result;
     }
 
-    protected void assertPartialEvalNoInvokes(RootNode root, FrameDescriptor descriptor) {
-        assertPartialEvalNoInvokes(root, descriptor, Arguments.EMPTY_ARGUMENTS);
+    protected void assertPartialEvalNoInvokes(RootNode root) {
+        assertPartialEvalNoInvokes(root, Arguments.EMPTY_ARGUMENTS);
     }
 
-    protected void assertPartialEvalNoInvokes(RootNode root, FrameDescriptor descriptor, Arguments arguments) {
+    protected void assertPartialEvalNoInvokes(RootNode root, Arguments arguments) {
         Assumptions assumptions = new Assumptions(true);
-        StructuredGraph actual = partialEval(root, descriptor, arguments, assumptions, true);
+        StructuredGraph actual = partialEval(root, 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);
+    protected StructuredGraph partialEval(RootNode root, Arguments arguments, final Assumptions assumptions, final boolean canonicalizeReads) {
+        final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root);
 
         // Executed AST so that all classes are loaded and initialized.
         do {
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -38,28 +38,28 @@
     public void constantValue() {
         FrameDescriptor fd = new FrameDescriptor();
         AbstractTestNode result = new ConstantTestNode(42);
-        assertPartialEvalEquals("constant42", new RootTestNode("constantValue", result), fd);
+        assertPartialEvalEquals("constant42", new RootTestNode(fd, "constantValue", result));
     }
 
     @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);
+        assertPartialEvalEquals("constant42", new RootTestNode(fd, "addConstants", result));
     }
 
     @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);
+        assertPartialEvalEquals("constant42", new RootTestNode(fd, "sequenceConstants", result));
     }
 
     @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);
+        assertPartialEvalEquals("constant42", new RootTestNode(fd, "localVariable", result));
     }
 
     @Test
@@ -72,7 +72,7 @@
         }
 
         AbstractTestNode result = new BlockTestNode(children);
-        assertPartialEvalEquals("constant42", new RootTestNode("longSequenceConstants", result), fd);
+        assertPartialEvalEquals("constant42", new RootTestNode(fd, "longSequenceConstants", result));
     }
 
     @Test
@@ -82,7 +82,7 @@
         for (int i = 0; i < 20; ++i) {
             result = new AddTestNode(result, new ConstantTestNode(2));
         }
-        assertPartialEvalEquals("constant42", new RootTestNode("longAddConstants", result), fd);
+        assertPartialEvalEquals("constant42", new RootTestNode(fd, "longAddConstants", result));
     }
 
     @Test
@@ -90,7 +90,7 @@
         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);
+        assertPartialEvalEquals("constant42", new RootTestNode(fd, "mixLocalAndAdd", result));
     }
 
     @Test
@@ -98,7 +98,7 @@
         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);
+        assertPartialEvalEquals("constant42", new RootTestNode(fd, "loop", result));
     }
 
     @Test
@@ -106,6 +106,6 @@
         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);
+        assertPartialEvalNoInvokes(new RootTestNode(fd, "loop", result));
     }
 }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -30,8 +30,8 @@
     private final String name;
     @Child AbstractTestNode node;
 
-    public RootTestNode(String name, AbstractTestNode node) {
-        super(null);
+    public RootTestNode(FrameDescriptor descriptor, String name, AbstractTestNode node) {
+        super(null, descriptor);
         this.name = name;
         this.node = node;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java	Wed Jan 22 21:34:00 2014 -0800
@@ -26,8 +26,6 @@
 
 public class CompilationProfile {
 
-    private static final int MIN_INVOKES_AFTER_INLINING = 2;
-
     private int invokeCounter;
     private int originalInvokeCounter;
     private int loopAndInvokeCounter;
@@ -102,9 +100,9 @@
         loopAndInvokeCounter--;
     }
 
-    void reportInliningPerformed() {
-        invokeCounter = MIN_INVOKES_AFTER_INLINING;
-        int inliningReprofileCount = TruffleInliningReprofileCount.getValue();
+    void reportInliningPerformed(TruffleInlining inlining) {
+        invokeCounter = inlining.getInvocationReprofileCount();
+        int inliningReprofileCount = inlining.getReprofileCount();
         loopAndInvokeCounter = inliningReprofileCount;
         originalInvokeCounter = inliningReprofileCount;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Wed Jan 22 21:34:00 2014 -0800
@@ -74,18 +74,13 @@
     }
 
     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);
+            return new DefaultCallTarget(rootNode);
         }
         if (truffleCompiler == null) {
             truffleCompiler = new TruffleCompilerImpl();
         }
-        return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue());
+        return new OptimizedCallTarget(rootNode, truffleCompiler, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue());
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Jan 22 21:34:00 2014 -0800
@@ -51,11 +51,10 @@
     private boolean compilationEnabled;
     private int callCount;
 
-    protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int invokeCounter, int compilationThreshold) {
-        super(rootNode, descriptor);
+    protected OptimizedCallTarget(RootNode rootNode, TruffleCompiler compiler, int invokeCounter, int compilationThreshold) {
+        super(rootNode);
         this.compiler = compiler;
         this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter, rootNode.toString());
-        this.inlining = new TruffleInliningImpl();
         this.rootNode.setCallTarget(this);
 
         if (TruffleUseTimeForCompilationDecision.getValue()) {
@@ -68,8 +67,11 @@
         if (TruffleCallTargetProfiling.getValue()) {
             registerCallTarget(this);
         }
+        this.inlining = new TruffleInliningImpl();
+
     }
 
+    @CompilerDirectives.SlowPath
     @Override
     public Object call(PackedFrame caller, Arguments args) {
         return callHelper(caller, args);
@@ -204,13 +206,13 @@
     public boolean inline() {
         boolean result = inlining.performInlining(this);
         if (result) {
-            compilationProfile.reportInliningPerformed();
+            compilationProfile.reportInliningPerformed(inlining);
         }
         return result;
     }
 
     public Object executeHelper(PackedFrame caller, Arguments args) {
-        VirtualFrame frame = createFrame(frameDescriptor, caller, args);
+        VirtualFrame frame = createFrame(rootNode.getFrameDescriptor(), caller, args);
         return rootNode.execute(frame);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInlining.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInlining.java	Wed Jan 22 21:34:00 2014 -0800
@@ -24,5 +24,18 @@
 
 public interface TruffleInlining {
 
+    /** Returns true if reprofiling is required else false. */
     boolean performInlining(OptimizedCallTarget callTarget);
+
+    /**
+     * Returns the minimum number of invocations required until the next inlining can occur. Only
+     * used if {@link #performInlining(OptimizedCallTarget)} returned true.
+     */
+    int getInvocationReprofileCount();
+
+    /**
+     * Returns the number of invocations or loop invocations required until the next inlining can
+     * occur. Only used if {@link #performInlining(OptimizedCallTarget)} returned true.
+     */
+    int getReprofileCount();
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java	Wed Jan 22 21:34:00 2014 -0800
@@ -33,8 +33,18 @@
 
 class TruffleInliningImpl implements TruffleInlining {
 
+    private static final int MIN_INVOKES_AFTER_INLINING = 2;
+
     private static final PrintStream OUT = TTY.out().out();
 
+    public int getReprofileCount() {
+        return TruffleCompilerOptions.TruffleInliningReprofileCount.getValue();
+    }
+
+    public int getInvocationReprofileCount() {
+        return MIN_INVOKES_AFTER_INLINING;
+    }
+
     @Override
     public boolean performInlining(OptimizedCallTarget target) {
         final InliningPolicy policy = new InliningPolicy(target);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Wed Jan 22 21:34:00 2014 -0800
@@ -34,9 +34,6 @@
 public class OptimizedCallTargetSubstitutions {
 
     @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
-    public static native Object call(OptimizedCallTarget target, PackedFrame caller, Arguments args);
-
-    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
     public static native Object callHelper(OptimizedCallTarget target, PackedFrame caller, Arguments args);
 
     @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -49,8 +49,8 @@
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
         FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
-        TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
-        CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
+        TestRootNode rootNode = new TestRootNode(frameDescriptor, new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode);
         Assert.assertEquals(FrameSlotKind.Int, slot.getKind());
         Object result = target.call();
         Assert.assertEquals("42", result);
@@ -62,8 +62,8 @@
         @Child TestChildNode left;
         @Child TestChildNode right;
 
-        public TestRootNode(TestChildNode left, TestChildNode right) {
-            super(null);
+        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
+            super(null, descriptor);
             this.left = adoptChild(left);
             this.right = adoptChild(right);
         }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -65,8 +65,8 @@
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
         FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
-        TestRootNode rootNode = new TestRootNode(new AssignLocal(slot), new ReadLocal(slot));
-        CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
+        TestRootNode rootNode = new TestRootNode(frameDescriptor, new AssignLocal(slot), new ReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode);
         Object result = target.call();
         Assert.assertEquals(42, result);
     }
@@ -76,8 +76,8 @@
         @Child TestChildNode left;
         @Child TestChildNode right;
 
-        public TestRootNode(TestChildNode left, TestChildNode right) {
-            super(null);
+        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
+            super(null, descriptor);
             this.left = adoptChild(left);
             this.right = adoptChild(right);
         }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Wed Jan 22 21:34:00 2014 -0800
@@ -48,8 +48,8 @@
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
         FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
-        TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
-        CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
+        TestRootNode rootNode = new TestRootNode(frameDescriptor, new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode);
         Assert.assertEquals(FrameSlotKind.Int, slot.getKind());
         Object result = target.call();
         Assert.assertEquals("42", result);
@@ -61,8 +61,8 @@
         @Child TestChildNode left;
         @Child TestChildNode right;
 
-        public TestRootNode(TestChildNode left, TestChildNode right) {
-            super(null);
+        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
+            super(null, descriptor);
             this.left = adoptChild(left);
             this.right = adoptChild(right);
         }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Wed Jan 22 21:34:00 2014 -0800
@@ -28,8 +28,7 @@
 
 /**
  * Represents the target of a call. Instances of this interface can be created using the
- * {@link TruffleRuntime#createCallTarget(com.oracle.truffle.api.nodes.RootNode, FrameDescriptor)}
- * method.
+ * {@link TruffleRuntime#createCallTarget(com.oracle.truffle.api.nodes.RootNode)} method.
  */
 public abstract class CallTarget {
 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Wed Jan 22 21:34:00 2014 -0800
@@ -32,31 +32,53 @@
  */
 public class TruffleOptions {
 
-    /** Enables/disables the rewriting of traces in the truffle runtime to stdout. */
-    public static boolean TraceRewrites = false;
+    /**
+     * Enables/disables the rewriting of traces in the truffle runtime to stdout.
+     * <p>
+     * Can be set with {@code -Dtruffle.TraceRewrites=true}.
+     */
+    public static boolean TraceRewrites = Boolean.getBoolean("truffle.TraceRewrites");
 
     /**
      * Enables the generation of detailed rewrite reasons. Enabling this may introduce some overhead
      * for rewriting nodes.
+     * <p>
+     * Can be set with {@code -Dtruffle.DetailedRewriteReasons=true}.
      */
-    public static final boolean DetailedRewriteReasons = false;
+    public static final boolean DetailedRewriteReasons = Boolean.getBoolean("truffle.DetailedRewriteReasons");
 
     /**
      * Filters rewrites that do not contain the given string in the qualified name of the source or
      * target class hierarchy.
+     * <p>
+     * Can be set with {@code -Dtruffle.TraceRewritesFilterClass=name}.
      */
-    public static String TraceRewritesFilterClass = null;
+    public static String TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass");
 
     /**
      * Filters rewrites which does not contain the {@link Kind} in its source {@link NodeInfo}. If
      * no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * <p>
+     * Can be set with
+     * {@code -Dtruffle.TraceRewritesFilterFromKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
      */
-    public static NodeInfo.Kind TraceRewritesFilterFromKind = null;
+    public static NodeInfo.Kind TraceRewritesFilterFromKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromKind"));
 
     /**
      * Filters rewrites which does not contain the {@link Kind} in its target {@link NodeInfo}. If
      * no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * <p>
+     * Can be set with
+     * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
      */
-    public static NodeInfo.Kind TraceRewritesFilterToKind = null;
+    public static NodeInfo.Kind TraceRewritesFilterToKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToKind"));
+
+    private static NodeInfo.Kind parseNodeInfoKind(String kind) {
+        if (kind == null) {
+            return null;
+        }
+
+        return NodeInfo.Kind.valueOf(kind);
+    }
 
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Wed Jan 22 21:34:00 2014 -0800
@@ -51,17 +51,6 @@
     CallTarget createCallTarget(RootNode rootNode);
 
     /**
-     * Creates a new call target for a given root node and a given frame descriptor.
-     * 
-     * @param rootNode the root node whose
-     *            {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method
-     *            represents the entry point
-     * @param frameDescriptor the descriptor used for creating a new frame at each invocation
-     * @return the new call target object
-     */
-    CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor);
-
-    /**
      * Creates a new assumption object that can be checked and invalidated.
      * 
      * @return the newly created assumption object
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Wed Jan 22 21:34:00 2014 -0800
@@ -31,11 +31,9 @@
 public class DefaultCallTarget extends CallTarget {
 
     protected final RootNode rootNode;
-    protected final FrameDescriptor frameDescriptor;
 
-    public DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) {
+    public DefaultCallTarget(RootNode function) {
         this.rootNode = function;
-        this.frameDescriptor = frameDescriptor;
         this.rootNode.setCallTarget(this);
     }
 
@@ -46,14 +44,10 @@
 
     @Override
     public Object call(PackedFrame caller, Arguments args) {
-        VirtualFrame frame = new DefaultVirtualFrame(frameDescriptor, caller, args);
+        VirtualFrame frame = new DefaultVirtualFrame(rootNode.getFrameDescriptor(), caller, args);
         return rootNode.execute(frame);
     }
 
-    public FrameDescriptor getFrameDescriptor() {
-        return frameDescriptor;
-    }
-
     public RootNode getRootNode() {
         return rootNode;
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Wed Jan 22 21:34:00 2014 -0800
@@ -41,12 +41,7 @@
 
     @Override
     public CallTarget createCallTarget(RootNode rootNode) {
-        return createCallTarget(rootNode, new FrameDescriptor());
-    }
-
-    @Override
-    public CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor) {
-        return new DefaultCallTarget(rootNode, frameDescriptor);
+        return new DefaultCallTarget(rootNode);
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -30,15 +30,28 @@
 /**
  * A root node is a node with a method to execute it given only a frame as a parameter. Therefore, a
  * root node can be used to create a call target using
- * {@link TruffleRuntime#createCallTarget(RootNode, FrameDescriptor)}.
+ * {@link TruffleRuntime#createCallTarget(RootNode)}.
  */
 public abstract class RootNode extends Node {
 
+    private CallTarget callTarget;
+    private final FrameDescriptor frameDescriptor;
+
     protected RootNode() {
+        this(null, null);
     }
 
     protected RootNode(SourceSection sourceSection) {
+        this(sourceSection, null);
+    }
+
+    protected RootNode(SourceSection sourceSection, FrameDescriptor frameDescriptor) {
         super(sourceSection);
+        if (frameDescriptor == null) {
+            this.frameDescriptor = new FrameDescriptor();
+        } else {
+            this.frameDescriptor = frameDescriptor;
+        }
     }
 
     /**
@@ -49,12 +62,14 @@
      */
     public abstract Object execute(VirtualFrame frame);
 
-    private CallTarget callTarget;
-
     public CallTarget getCallTarget() {
         return callTarget;
     }
 
+    public FrameDescriptor getFrameDescriptor() {
+        return frameDescriptor;
+    }
+
     public void setCallTarget(CallTarget callTarget) {
         this.callTarget = callTarget;
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Wed Jan 22 21:34:00 2014 -0800
@@ -102,18 +102,18 @@
 
     private static class CodeWriter extends AbstractCodeWriter {
 
-        private final Element orignalElement;
+        private final Element originalElement;
         private final ProcessingEnvironment env;
 
         public CodeWriter(ProcessingEnvironment env, Element originalElement) {
             this.env = env;
-            this.orignalElement = originalElement;
+            this.originalElement = originalElement;
         }
 
         @Override
         protected Writer createWriter(CodeTypeElement clazz) throws IOException {
-            JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), orignalElement);
-            return jfo.openWriter();
+            JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), originalElement);
+            return new BufferedWriter(jfo.openWriter());
         }
 
         @Override
@@ -121,7 +121,7 @@
             if (env == null) {
                 return;
             }
-            String comment = CompilerFactory.getCompiler(orignalElement).getHeaderComment(env, orignalElement);
+            String comment = CompilerFactory.getCompiler(originalElement).getHeaderComment(env, originalElement);
             if (comment != null) {
                 writeLn(comment);
             }
--- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/RubyRootNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/RubyRootNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -22,8 +22,8 @@
     protected final String indicativeName;
     @Child protected RubyNode body;
 
-    public RubyRootNode(SourceSection sourceSection, String indicativeName, RubyNode body) {
-        super(sourceSection);
+    public RubyRootNode(SourceSection sourceSection, FrameDescriptor descriptor, String indicativeName, RubyNode body) {
+        super(sourceSection, descriptor);
 
         assert indicativeName != null;
         assert body != null;
--- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java	Wed Jan 22 21:34:00 2014 -0800
@@ -174,7 +174,7 @@
         final CheckArityNode checkArity = new CheckArityNode(context, sourceSection, arity);
         final SequenceNode block = new SequenceNode(context, sourceSection, checkArity, methodNode);
 
-        return new RubyRootNode(sourceSection, methodDetails.getClassAnnotation().name() + "#" + methodDetails.getMethodAnnotation().names()[0] + "(core)", block);
+        return new RubyRootNode(sourceSection, null, methodDetails.getClassAnnotation().name() + "#" + methodDetails.getMethodAnnotation().names()[0] + "(core)", block);
     }
 
     public static class MethodDetails {
--- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ModuleNodes.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ModuleNodes.java	Wed Jan 22 21:34:00 2014 -0800
@@ -96,7 +96,7 @@
 
             final SequenceNode block = new SequenceNode(context, sourceSection, checkArity, readInstanceVariable);
 
-            final RubyRootNode pristineRoot = new RubyRootNode(sourceSection, name + "(attr_reader)", block);
+            final RubyRootNode pristineRoot = new RubyRootNode(sourceSection, null, name + "(attr_reader)", block);
             final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRoot));
             final InlinableMethodImplementation methodImplementation = new InlinableMethodImplementation(callTarget, null, new FrameDescriptor(), pristineRoot, true, false);
             final RubyMethod method = new RubyMethod(sourceSection, module, new UniqueMethodIdentifier(), null, name, Visibility.PUBLIC, false, methodImplementation);
@@ -139,7 +139,7 @@
 
             final SequenceNode block = new SequenceNode(context, sourceSection, checkArity, writeInstanceVariable);
 
-            final RubyRootNode pristineRoot = new RubyRootNode(sourceSection, name + "(attr_writer)", block);
+            final RubyRootNode pristineRoot = new RubyRootNode(sourceSection, null, name + "(attr_writer)", block);
             final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRoot));
             final InlinableMethodImplementation methodImplementation = new InlinableMethodImplementation(callTarget, null, new FrameDescriptor(), pristineRoot, true, false);
             final RubyMethod method = new RubyMethod(sourceSection, module, new UniqueMethodIdentifier(), null, name + "=", Visibility.PUBLIC, false, methodImplementation);
--- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/JRubyParser.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/JRubyParser.java	Wed Jan 22 21:34:00 2014 -0800
@@ -161,11 +161,10 @@
                     throw new UnsupportedOperationException();
             }
 
-            final RootNode root = new RubyRootNode(truffleNode.getSourceSection(), indicativeName, truffleNode);
+            final RootNode root = new RubyRootNode(truffleNode.getSourceSection(), environment.getFrameDescriptor(), indicativeName, truffleNode);
 
             // Return the root and the frame descriptor
-
-            return new RubyParserResult(root, environment.getFrameDescriptor());
+            return new RubyParserResult(root);
         } finally {
             if (debugManager != null) {
                 debugManager.notifyFinishedLoading(source);
--- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/MethodTranslator.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/MethodTranslator.java	Wed Jan 22 21:34:00 2014 -0800
@@ -59,9 +59,9 @@
             body = new CatchNextNode(context, sourceSection, body);
         }
 
-        final RubyRootNode pristineRootNode = new RubyRootNode(sourceSection, methodName, body);
+        final RubyRootNode pristineRootNode = new RubyRootNode(sourceSection, environment.getFrameDescriptor(), methodName, body);
 
-        final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRootNode), environment.getFrameDescriptor());
+        final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRootNode));
 
         if (isBlock) {
             return new BlockDefinitionNode(context, sourceSection, methodName, environment.getUniqueMethodIdentifier(), environment.getFrameDescriptor(), environment.needsDeclarationFrame(),
--- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/ModuleTranslator.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/ModuleTranslator.java	Wed Jan 22 21:34:00 2014 -0800
@@ -57,9 +57,9 @@
 
         body = new CatchReturnNode(context, sourceSection, body, environment.getReturnID());
 
-        final RubyRootNode pristineRootNode = new RubyRootNode(sourceSection, methodName, body);
+        final RubyRootNode pristineRootNode = new RubyRootNode(sourceSection, environment.getFrameDescriptor(), methodName, body);
 
-        final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRootNode), environment.getFrameDescriptor());
+        final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRootNode));
 
         return new MethodDefinitionNode(context, sourceSection, methodName, environment.getUniqueMethodIdentifier(), environment.getFrameDescriptor(), environment.needsDeclarationFrame(),
                         pristineRootNode, callTarget);
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java	Wed Jan 22 21:34:00 2014 -0800
@@ -172,7 +172,7 @@
         try {
             final RubyParserResult parseResult = parser.parse(context, source, parserContext, parentFrame);
             final RubyArguments arguments = new RubyArguments(parentFrame, self, null);
-            final CallTarget callTarget = Truffle.getRuntime().createCallTarget(parseResult.getRootNode(), parseResult.getFrameDescriptor());
+            final CallTarget callTarget = Truffle.getRuntime().createCallTarget(parseResult.getRootNode());
 
             return callTarget.call(null, arguments);
         } catch (RaiseException e) {
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyParserResult.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyParserResult.java	Wed Jan 22 21:34:00 2014 -0800
@@ -9,7 +9,6 @@
  */
 package com.oracle.truffle.ruby.runtime;
 
-import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
 /**
@@ -19,23 +18,15 @@
  */
 public class RubyParserResult {
 
-    private RootNode rootNode;
-    private FrameDescriptor frameDescriptor;
+    private final RootNode rootNode;
 
-    public RubyParserResult(RootNode rootNode, FrameDescriptor frameDescriptor) {
+    public RubyParserResult(RootNode rootNode) {
         assert rootNode != null;
-        assert frameDescriptor != null;
-
         this.rootNode = rootNode;
-        this.frameDescriptor = frameDescriptor;
     }
 
     public RootNode getRootNode() {
         return rootNode;
     }
 
-    public FrameDescriptor getFrameDescriptor() {
-        return frameDescriptor;
-    }
-
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -189,7 +189,7 @@
 
         InlinedDirectCallNode(InlinableDirectCallNode prev, TypedNode inlinedBody) {
             super(prev.functionNode, prev.argumentsNode, prev.cachedFunction, prev.nextNode);
-            this.descriptor = cachedFunction.getFrameDescriptor();
+            this.descriptor = cachedFunction.getRootNode().getFrameDescriptor();
             this.inlinedBody = adoptChild(inlinedBody);
         }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -37,8 +37,8 @@
     private final String name;
     private final boolean inlineImmediatly;
 
-    private FunctionRootNode(TypedNode body, String name, boolean inlineImmediatly) {
-        super(null);
+    private FunctionRootNode(FrameDescriptor frameDescriptor, TypedNode body, String name, boolean inlineImmediatly) {
+        super(null, frameDescriptor);
         this.uninitializedBody = NodeUtil.cloneNode(body);
         this.body = adoptChild(body);
         this.name = name;
@@ -52,14 +52,14 @@
             arguments[i] = new ReadArgumentNode(i);
         }
         BuiltinNode buitinBody = factory.createNode(arguments, context);
-        FunctionRootNode root = new FunctionRootNode(buitinBody, name, true);
+        FunctionRootNode root = new FunctionRootNode(new FrameDescriptor(), buitinBody, name, true);
         return Truffle.getRuntime().createCallTarget(root);
     }
 
     public static CallTarget createFunction(StatementNode body, FrameDescriptor frameDescriptor, String name, TypedNode returnValue, String[] parameterNames) {
         FunctionBodyNode bodyContainer = new FunctionBodyNode(frameDescriptor, body, returnValue, parameterNames);
-        FunctionRootNode root = new FunctionRootNode(bodyContainer, name, false);
-        return Truffle.getRuntime().createCallTarget(root, frameDescriptor);
+        FunctionRootNode root = new FunctionRootNode(frameDescriptor, bodyContainer, name, false);
+        return Truffle.getRuntime().createCallTarget(root);
     }
 
     @Override
--- a/make/bsd/makefiles/vm.make	Wed Jan 22 21:02:06 2014 -0800
+++ b/make/bsd/makefiles/vm.make	Wed Jan 22 21:34:00 2014 -0800
@@ -222,20 +222,22 @@
 
 ifneq ($(INCLUDE_GRAAL), true)
   GRAAL_SPECIFIC_FILES   := graal\*
+  GRAAL_SPECIFIC_GPU_FILES  := gpu\* ptx\* hsail\*
 else
   GRAAL_SPECIFIC_FILES   :=
+  GRAAL_SPECIFIC_GPU_FILES  :=
 endif
 
 # Always exclude these.
 Src_Files_EXCLUDE += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
 Src_Files_EXCLUDE/GRAAL     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
--- a/make/linux/makefiles/vm.make	Wed Jan 22 21:02:06 2014 -0800
+++ b/make/linux/makefiles/vm.make	Wed Jan 22 21:34:00 2014 -0800
@@ -201,21 +201,23 @@
 ZERO_SPECIFIC_FILES      := zero
 
 ifneq ($(INCLUDE_GRAAL), true)
-  GRAAL_SPECIFIC_FILES   := graal\*
+  GRAAL_SPECIFIC_FILES   := graal\* 
+  GRAAL_SPECIFIC_GPU_FILES  := gpu\* ptx\* hsail\*
 else
   GRAAL_SPECIFIC_FILES   :=
+  GRAAL_SPECIFIC_GPU_FILES   :=
 endif
 
 # Always exclude these.
 Src_Files_EXCLUDE += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
 Src_Files_EXCLUDE/GRAAL     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
--- a/make/solaris/makefiles/vm.make	Wed Jan 22 21:02:06 2014 -0800
+++ b/make/solaris/makefiles/vm.make	Wed Jan 22 21:34:00 2014 -0800
@@ -219,17 +219,18 @@
 SHARK_SPECIFIC_FILES     := shark
 ZERO_SPECIFIC_FILES      := zero
 GRAAL_SPECIFIC_FILES     := graal
+GRAAL_SPECIFIC_GPU_FILES  := gpu\* ptx\* hsail\*
 
 # Always exclude these.
 Src_Files_EXCLUDE := dtrace jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
 Src_Files_EXCLUDE/GRAAL     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
--- a/mx/mx_graal.py	Wed Jan 22 21:02:06 2014 -0800
+++ b/mx/mx_graal.py	Wed Jan 22 21:34:00 2014 -0800
@@ -344,10 +344,10 @@
                     for line in releaseFileLines:
                         if line.startswith("SOURCE="):
                             try:
-                                sourceLine = line[0:-2] # remove last char
+                                sourceLine = line[0:-2]  # remove last char
                                 hgcfg = mx.HgConfig()
                                 hgcfg.check()
-                                revision = hgcfg.tip('.')[:12] # take first 12 chars
+                                revision = hgcfg.tip('.')[:12]  # take first 12 chars
                                 fp.write(sourceLine + ' graal:' + revision + '\"\n')
                             except:
                                 fp.write(line)
@@ -793,26 +793,29 @@
         if t.startswith('-'):
             mx.abort('VM option ' + t + ' must precede ' + tests[0])
 
-    candidates = []
+    candidates = {}
     for p in mx.projects_opt_limit_to_suites():
         if mx.java().javaCompliance < p.javaCompliance:
             continue
-        candidates += _find_classes_with_annotations(p, None, annotations).keys()
+        for c in _find_classes_with_annotations(p, None, annotations).keys():
+            candidates[c] = p
 
     classes = []
     if len(tests) == 0:
-        classes = candidates
+        classes = candidates.keys()
+        projectscp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites() if pcp.javaCompliance <= mx.java().javaCompliance])
     else:
+        projs = set()
         for t in tests:
             found = False
-            for c in candidates:
+            for c, p in candidates.iteritems():
                 if t in c:
                     found = True
                     classes.append(c)
+                    projs.add(p.name)
             if not found:
                 mx.log('warning: no tests matched by substring "' + t)
-
-    projectscp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites() if pcp.javaCompliance <= mx.java().javaCompliance])
+        projectscp = mx.classpath(projs)
 
     if len(classes) != 0:
         f_testfile = open(testfile, 'w')
@@ -1504,11 +1507,11 @@
     # gather graal options
     output = StringIO.StringIO()
     vm(['-XX:-BootstrapGraal', '-G:+PrintFlags' if optionType == "graal" else '-XX:+PrintFlagsWithComments'],
-       vm = "graal",
-       vmbuild = "optimized",
-       nonZeroIsFatal = False,
-       out = output.write,
-       err = subprocess.STDOUT)
+       vm="graal",
+       vmbuild="optimized",
+       nonZeroIsFatal=False,
+       out=output.write,
+       err=subprocess.STDOUT)
 
     valueMap = parser.parse(output.getvalue())
     return valueMap
--- a/mxtool/mx.py	Wed Jan 22 21:02:06 2014 -0800
+++ b/mxtool/mx.py	Wed Jan 22 21:34:00 2014 -0800
@@ -2751,6 +2751,9 @@
             if hasattr(dep, 'eclipse.container'):
                 memento = XMLDoc().element('classpathContainer', {'path' : getattr(dep, 'eclipse.container')}).xml(standalone='no')
                 slm.element('classpathContainer', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.classpathContainer'})
+            elif dep.get_source_path(resolve=True):
+                memento = XMLDoc().element('archive', {'detectRoot' : 'true', 'path' : dep.get_source_path(resolve=True)}).xml(standalone='no')
+                slm.element('container', {'memento' : memento, 'typeId':'org.eclipse.debug.core.containerType.externalArchive'})
         else:
             memento = XMLDoc().element('javaProject', {'name' : dep.name}).xml(standalone='no')
             slm.element('container', {'memento' : memento, 'typeId':'org.eclipse.jdt.launching.sourceContainer.javaProject'})
@@ -3097,7 +3100,7 @@
             update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n'))
             files.append(join(p.dir, '.factorypath'))
 
-    _, launchFile = make_eclipse_attach(suite, 'localhost', '8000', deps=projects())
+    _, launchFile = make_eclipse_attach(suite, 'localhost', '8000', deps=sorted_deps(projectNames=None, includeLibs=True))
     files.append(launchFile)
 
     _zip_files(files, suite.dir, configZip.path)
--- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Wed Jan 22 21:34:00 2014 -0800
@@ -72,9 +72,10 @@
       case 'b':
       case 's':
       case 'c':
+      case 'i':
         fatal("int-sized values not expected in DataPatch");
         break;
-      case 'i': {
+      case 'n': {
         address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
         Handle obj = Constant::object(inlineData);
 
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Wed Jan 22 21:34:00 2014 -0800
@@ -171,18 +171,21 @@
     @Override
     public void resultChanged(LookupEvent lookupEvent) {
         final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
-        if (p != null) {
             SwingUtilities.invokeLater(new Runnable() {
                 @Override
                 public void run() {
+                if (p != null) {
                     InputGraph graph = p.getGraph();
                     if (graph != null) {
                         Group g = graph.getGroup();
                         rootNode.update(graph, g.getMethod());
+                        return;
                     }
                 }
+                        rootNode.update(null, null);
+                    }
             });
-        }
+
     }
 
     final static class ResolvableHelper implements Serializable {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Wed Jan 22 21:34:00 2014 -0800
@@ -38,6 +38,9 @@
 import org.openide.actions.OpenAction;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
+import org.openide.nodes.NodeAdapter;
+import org.openide.nodes.NodeEvent;
+import org.openide.nodes.NodeMemberEvent;
 import org.openide.nodes.Sheet;
 import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
@@ -49,7 +52,7 @@
  * @author Thomas Wuerthinger
  */
 public class GraphNode extends AbstractNode {
-    private final InputGraph graph;
+    private InputGraph graph;
 
     /** Creates a new instance of GraphNode */
     public GraphNode(InputGraph graph) {
@@ -77,6 +80,13 @@
 
         // Action for cloning to the current graph
         content.add(new GraphCloneCookie(viewer, graph));
+        
+        this.addNodeListener(new NodeAdapter() {
+            @Override
+            public void childrenRemoved(NodeMemberEvent ev) {
+                GraphNode.this.graph = null;
+            }
+        });
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Wed Jan 22 21:34:00 2014 -0800
@@ -389,4 +389,9 @@
         }
         this.setSelectedNodes(newSelectedNodes);
     }
+
+    void close() {
+        filterChain.getChangedEvent().removeListener(filterChainChangedListener);
+        sequenceFilterChain.getChangedEvent().removeListener(filterChainChangedListener);
 }
+}
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Wed Jan 22 21:34:00 2014 -0800
@@ -408,6 +408,7 @@
 
     @Override
     public void componentClosed() {
+        rangeSliderModel.close();
     }
 
     @Override
@@ -580,4 +581,8 @@
         return scene.getUndoRedo();
     }
 
+    @Override
+    protected Object writeReplace() throws ObjectStreamException {
+        throw new NotSerializableException();
 }
+}
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Jan 22 21:34:00 2014 -0800
@@ -212,6 +212,7 @@
   do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,    Opt) \
   do_klass(BytecodePosition_klass,                com_oracle_graal_api_code_BytecodePosition,                   Opt) \
   do_klass(DebugInfo_klass,                       com_oracle_graal_api_code_DebugInfo,                          Opt) \
+  do_klass(ReferenceMap_klass,                    com_oracle_graal_api_code_ReferenceMap,                       Opt) \
   do_klass(RegisterSaveLayout_klass,              com_oracle_graal_api_code_RegisterSaveLayout,                 Opt) \
   do_klass(BytecodeFrame_klass,                   com_oracle_graal_api_code_BytecodeFrame,                      Opt) \
   do_klass(CompilationResult_klass,               com_oracle_graal_api_code_CompilationResult,                  Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Jan 22 21:34:00 2014 -0800
@@ -342,6 +342,7 @@
   template(com_oracle_graal_api_code_BytecodeFrame,                  "com/oracle/graal/api/code/BytecodeFrame")                       \
   template(com_oracle_graal_api_code_BytecodePosition,               "com/oracle/graal/api/code/BytecodePosition")                    \
   template(com_oracle_graal_api_code_DebugInfo,                      "com/oracle/graal/api/code/DebugInfo")                           \
+  template(com_oracle_graal_api_code_ReferenceMap,                   "com/oracle/graal/api/code/ReferenceMap")                        \
   template(com_oracle_graal_api_code_Register,                       "com/oracle/graal/api/code/Register")                            \
   template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue")                       \
   template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot")                           \
--- a/src/share/vm/compiler/compileBroker.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/compiler/compileBroker.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -1144,7 +1144,9 @@
   }
 #ifdef GRAALVM
   if (!JavaThread::current()->is_graal_compiling()) {
-    GraalCompiler::instance()->compile_method(method, osr_bci, is_compile_blocking(method, osr_bci));
+    bool blockingCompilation = is_compile_blocking(method, osr_bci) ||
+      CompilationPolicy::can_be_offloaded_to_gpu(method);
+    GraalCompiler::instance()->compile_method(method, osr_bci, blockingCompilation);
   } else {
     // Recursive compile request => ignore.
   }
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -84,28 +84,45 @@
 // creates a HotSpot oop map out of the byte arrays provided by DebugInfo
 static OopMap* create_oop_map(jint total_frame_size, jint parameter_count, oop debug_info) {
   OopMap* map = new OopMap(total_frame_size, parameter_count);
-  oop register_map = (oop) DebugInfo::registerRefMap(debug_info);
-  oop frame_map = (oop) DebugInfo::frameRefMap(debug_info);
+  oop reference_map = DebugInfo::referenceMap(debug_info);
+  oop register_map = ReferenceMap::registerRefMap(reference_map);
+  oop frame_map = ReferenceMap::frameRefMap(reference_map);
   oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info);
 
   if (register_map != NULL) {
     for (jint i = 0; i < RegisterImpl::number_of_registers; i++) {
-      bool is_oop = is_bit_set(register_map, i);
+      bool is_oop = is_bit_set(register_map, 2 * i);
       VMReg hotspot_reg = get_hotspot_reg(i);
       if (is_oop) {
-        map->set_oop(hotspot_reg);
+        if (is_bit_set(register_map, 2 * i + 1)) {
+          map->set_narrowoop(hotspot_reg);
+        } else {
+          map->set_oop(hotspot_reg);
+        }
       } else {
         map->set_value(hotspot_reg);
       }
     }
   }
 
-  for (jint i = 0; i < bitset_size(frame_map); i++) {
-    bool is_oop = is_bit_set(frame_map, i);
+  for (jint i = 0; i < bitset_size(frame_map) / 3; i++) {
+    bool is_oop = is_bit_set(frame_map, i * 3);
     // HotSpot stack slots are 4 bytes
     VMReg reg = VMRegImpl::stack2reg(i * VMRegImpl::slots_per_word);
     if (is_oop) {
-      map->set_oop(reg);
+      bool narrow1 = is_bit_set(frame_map, i * 3 + 1);
+      bool narrow2 = is_bit_set(frame_map, i * 3 + 2);
+      if(narrow1 || narrow2) {
+        if(narrow1) {
+          map->set_narrowoop(reg);
+        }
+        if(narrow2) {
+          VMReg reg2 = VMRegImpl::stack2reg(i * VMRegImpl::slots_per_word + 1);
+          map->set_narrowoop(reg2);
+        }
+      } else {
+        map->set_oop(reg);
+      }
     } else {
       map->set_value(reg);
     }
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -688,6 +688,9 @@
   HandleMark hm;
 
   jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode);
+  if (nmethodValue == 0L) {
+    THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
+  }
   nmethod* nm = (nmethod*) (address) nmethodValue;
   methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
--- a/src/share/vm/graal/graalGlobals.hpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/graal/graalGlobals.hpp	Wed Jan 22 21:34:00 2014 -0800
@@ -79,6 +79,12 @@
   develop(bool, TraceUncollectedSpeculations, false,                        \
           "Print message when a failed speculation was not collected")      \
                                                                             \
+  product(bool, GPUOffload, false,                                          \
+          "Offload execution to GPU whenever possible")                     \
+                                                                            \
+  product(bool, TraceGPUInteraction, false,                                 \
+          "Trace external GPU Interaction")                                 \
+                                                                            \
 
 
 // Read default values for Graal globals
--- a/src/share/vm/graal/graalJavaAccess.hpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Jan 22 21:34:00 2014 -0800
@@ -173,10 +173,13 @@
   end_class                                                                                                                                                    \
   start_class(DebugInfo)                                                                                                                                       \
     oop_field(DebugInfo, bytecodePosition, "Lcom/oracle/graal/api/code/BytecodePosition;")                                                                     \
-    oop_field(DebugInfo, registerRefMap, "Ljava/util/BitSet;")                                                                                                 \
-    oop_field(DebugInfo, frameRefMap, "Ljava/util/BitSet;")                                                                                                    \
+    oop_field(DebugInfo, referenceMap, "Lcom/oracle/graal/api/code/ReferenceMap;")                                                                             \
     oop_field(DebugInfo, calleeSaveInfo, "Lcom/oracle/graal/api/code/RegisterSaveLayout;")                                                                     \
   end_class                                                                                                                                                    \
+  start_class(ReferenceMap)                                                                                                                                    \
+    oop_field(ReferenceMap, registerRefMap, "Ljava/util/BitSet;")                                                                                              \
+    oop_field(ReferenceMap, frameRefMap, "Ljava/util/BitSet;")                                                                                                 \
+  end_class                                                                                                                                                    \
   start_class(RegisterSaveLayout)                                                                                                                              \
     oop_field(RegisterSaveLayout, registers, "[Lcom/oracle/graal/api/code/Register;")                                                                          \
     oop_field(RegisterSaveLayout, slots, "[I")                                                                                                                 \
--- a/src/share/vm/oops/instanceKlass.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/oops/instanceKlass.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -3016,9 +3016,9 @@
   if (this == SystemDictionary::String_klass()) {
     typeArrayOop value  = java_lang_String::value(obj);
     juint        offset = java_lang_String::offset(obj);
+    if (value != NULL) {
     juint        length = java_lang_String::length(obj);
-    if (value != NULL &&
-        value->is_typeArray() &&
+      if (value->is_typeArray() &&
         offset          <= (juint) value->length() &&
         offset + length <= (juint) value->length()) {
       st->print(BULLET"string: ");
@@ -3028,6 +3028,7 @@
       if (!WizardMode)  return;  // that is enough
     }
   }
+  }
 
   st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj));
   FieldPrinter print_field(st, obj);
--- a/src/share/vm/oops/method.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/oops/method.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -2025,32 +2025,3 @@
   guarantee(md == NULL ||
       md->is_methodData(), "should be method data");
 }
-
-#ifdef GRAAL
-
-// Return true if the name of the method indicates that this is a
-// lambda method other than <init>. Lambda method is one with a name 
-// that starts with lambda$ and is synthetic.
-
-bool Method::is_lambda() const {
-  Symbol * klass_name = method_holder()->name();
-  Symbol * method_name = name();
-  ResourceMark rm;
-  if (klass_name != NULL) {
-    if (klass_name != NULL && method_name != NULL) {
-      const char* lambdaPrefix = "lambda$main$";
-      char* methodPrefix = strstr(method_name->as_C_string(), lambdaPrefix);
-      if (methodPrefix != 0) {
-        if ((strncmp(lambdaPrefix, methodPrefix, strlen(lambdaPrefix)) == 0) && 
-            is_synthetic()) {
-          //tty->print_cr("[Check] %s::%s", klass_name->as_C_string(), method_name->as_C_string());
-          return true;
-        } else {
-          return false;
-        }
-      }
-    }
-    //}
-  }
-}
-#endif
--- a/src/share/vm/oops/method.hpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/oops/method.hpp	Wed Jan 22 21:34:00 2014 -0800
@@ -617,11 +617,6 @@
   // simultaneously. Use with caution.
   bool has_compiled_code() const                 { return code() != NULL; }
 
-#ifdef GRAAL
-  // Return true if the name of the method indicates that this is a
-  // lambda method other than <init>.
-  bool is_lambda() const;
-#endif
   // sizing
   static int header_size()                       { return sizeof(Method)/HeapWordSize; }
   static int size(bool is_native);
--- a/src/share/vm/runtime/compilationPolicy.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -105,30 +105,7 @@
 
   if (m->has_compiled_code()) return false;       // already compiled
 
-#ifdef GRAAL
-  // Check if this is a Lambda method that can be compiled to a GPU.
-  if (m->is_lambda()) {
-    // If GPU is available and the necessary linkage is available
-    // rerurn true indicatin that this method must be compiled.
-    if (gpu::is_available() && gpu::has_gpu_linkage()) {
-      if (TraceGPUInteraction) {
-        tty->print("Compiling Lambda method");
-        m->print_short_name();
-        switch (gpu::get_target_il_type()) {
-        case gpu::PTX :
-          tty->print_cr(" to PTX");
-          break;
-        case gpu::HSAIL :
-          tty->print_cr(" to HSAIL");
-          break;
-        default :
-          tty->print_cr(" to Unknown GPU!!!");
-        }
-      }
-      return true;
-    }
-  }
-#endif
+  if (CompilationPolicy::can_be_offloaded_to_gpu(m)) return true;
 
   if (!can_be_compiled(m, comp_level)) return false;
 
@@ -184,6 +161,58 @@
   return (result && can_be_compiled(m, comp_level));
 }
 
+bool CompilationPolicy::can_be_offloaded_to_gpu(methodHandle m) {
+#ifdef GRAAL
+  if (GPUOffload) {
+    // Check if this method can be offloaded to GPU.
+    // 1. Offload it to GPU if it is a Lambda method
+    if (m->is_synthetic()) {
+      // A lambda method is a syntheric method.
+      Symbol * klass_name = m->method_holder()->name();
+      Symbol * method_name = m->name();
+      bool offloadToGPU = false;
+      {
+        ResourceMark rm;
+        if (klass_name != NULL) {
+          if (klass_name != NULL && method_name != NULL) {
+            const char* lambdaPrefix = "lambda$";
+            char* methodPrefix = strstr(method_name->as_C_string(), lambdaPrefix);
+            if (methodPrefix != 0) {
+              if ((strncmp(lambdaPrefix, methodPrefix, strlen(lambdaPrefix)) == 0)) {
+                offloadToGPU = true;
+              }
+            }
+          }
+        }
+      }
+      if (offloadToGPU) {
+        // If GPU is available and the necessary linkage is available
+        // return true indicatin that this method must be compiled.
+        if (gpu::is_available() && gpu::has_gpu_linkage()) {
+          if (TraceGPUInteraction) {
+            tty->print("Compiling Lambda method ");
+            m->print_short_name();
+            switch (gpu::get_target_il_type()) {
+            case gpu::PTX :
+              tty->print_cr("to PTX");
+              break;
+            case gpu::HSAIL :
+              tty->print_cr("to HSAIL");
+              break;
+            default :
+              tty->print_cr("to Unknown GPU!!!");
+            }
+          }
+          return true;
+        }
+      }
+    }
+  }
+#endif
+
+  return false;
+}
+
 bool CompilationPolicy::is_compilation_enabled() {
   // NOTE: CompileBroker::should_compile_new_jobs() checks for UseCompiler
   return !delay_compilation_during_startup() && CompileBroker::should_compile_new_jobs();
--- a/src/share/vm/runtime/compilationPolicy.hpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Wed Jan 22 21:34:00 2014 -0800
@@ -58,6 +58,9 @@
   static void set_policy(CompilationPolicy* policy) { _policy = policy; }
   static CompilationPolicy* policy()                { return _policy; }
 
+  // m is allowed to be offloaded to a gpu
+  static bool can_be_offloaded_to_gpu(methodHandle m);
+
   // Profiling
   elapsedTimer* accumulated_time() { return &_accumulated_time; }
   void print_time() PRODUCT_RETURN;
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -1370,6 +1370,7 @@
     int             trap_bci    = trap_scope->bci();
 #ifdef GRAAL
     oop speculation = thread->pending_failed_speculation();
+    if (nm->is_compiled_by_graal()) {
     if (speculation != NULL) {
       oop speculation_log = nm->speculation_log();
       if (speculation_log != NULL) {
@@ -1393,6 +1394,11 @@
         tty->print_cr("No speculation");
       }
     }
+    } else {
+#ifdef ASSERT
+      assert(speculation == NULL, "There should not be a speculation for method compiled by other compilers");
+#endif
+    }
 
     if (trap_bci == SynchronizationEntryBCI) {
       trap_bci = 0;
--- a/src/share/vm/runtime/globals.hpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/runtime/globals.hpp	Wed Jan 22 21:34:00 2014 -0800
@@ -3840,9 +3840,6 @@
   product(bool , AllowNonVirtualCalls, false,                               \
           "Obey the ACC_SUPER flag and allow invokenonvirtual calls")       \
                                                                             \
-  product(bool, TraceGPUInteraction, false,                                 \
-          "Trace external GPU Interaction")                                 \
-                                                                            \
   product(bool, UseHSAILSimulator, false,                                   \
           "Run code on HSAIL Simulator")                                    \
                                                                             \
--- a/src/share/vm/runtime/sweeper.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/runtime/sweeper.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -233,7 +233,7 @@
 void NMethodSweeper::possibly_sweep() {
   assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
   // Only compiler threads are allowed to sweep
-  if (!MethodFlushing || !sweep_in_progress() || !Thread::current()->is_Compiler_thread()) {
+  if (!MethodFlushing || !sweep_in_progress() NOT_GRAAL(|| !Thread::current()->is_Compiler_thread()) GRAAL_ONLY(|| !Thread::current()->is_Java_thread())) {
     return;
   }
 
--- a/src/share/vm/runtime/thread.cpp	Wed Jan 22 21:02:06 2014 -0800
+++ b/src/share/vm/runtime/thread.cpp	Wed Jan 22 21:34:00 2014 -0800
@@ -3394,9 +3394,13 @@
   jint parse_result = Arguments::parse(args);
   if (parse_result != JNI_OK) return parse_result;
 
-  // Probe for existance of supported GPU and initialize it if one
-  // exists.
-  gpu::init();
+#ifdef GRAAL
+  if (GPUOffload) {
+    // Probe for existance of supported GPU and initialize it if one
+    // exists.
+    gpu::init();
+  }
+#endif
 
   os::init_before_ergo();