changeset 11794:b2c74b9fd4ab

Merge.
author Doug Simon <doug.simon@oracle.com>
date Tue, 24 Sep 2013 15:35:59 +0200
parents ca9c16735da8 (current diff) 5814f30f0baf (diff)
children 56c3ec12a79c
files graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCSafepointOp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java
diffstat 66 files changed, 1693 insertions(+), 1408 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MemoryMap.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,28 @@
+/*
+ * 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.api.meta;
+
+public interface MemoryMap<T> {
+
+    T getLastLocationAccess(LocationIdentity locationIdentity);
+}
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Tue Sep 24 15:35:59 2013 +0200
@@ -24,13 +24,13 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 
-import com.oracle.graal.api.code.AbstractAddress;
 import com.oracle.graal.api.code.Register;
 import com.oracle.graal.api.code.RegisterConfig;
 import com.oracle.graal.api.code.TargetDescription;
 import com.oracle.graal.api.meta.Constant;
 import com.oracle.graal.api.meta.Kind;
 import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.nodes.calc.Condition;
 import com.oracle.graal.graph.GraalInternalError;
 import com.oracle.graal.lir.Variable;
 
@@ -40,6 +40,62 @@
         super(target);
     }
 
+    public enum ConditionOperator {
+        // @formatter:off
+
+        // Signed integer operators
+        S_EQ("eq"),
+        S_NE("ne"),
+        S_LT("lt"),
+        S_LE("le"),
+        S_GT("gt"),
+        S_GE("ge"),
+
+        // Unsigned integer operators
+        U_EQ("eq"),
+        U_NE("ne"),
+        U_LO("lo"),
+        U_LS("ls"),
+        U_HI("hi"),
+        U_HS("hs"),
+
+        // Bit-size integer operators
+        B_EQ("eq"),
+        B_NE("ne"),
+
+        // Floating-point operators
+        F_EQ("eq"),
+        F_NE("ne"),
+        F_LT("lt"),
+        F_LE("le"),
+        F_GT("gt"),
+        F_GE("ge"),
+
+        // Floating-point operators accepting NaN
+        F_EQU("equ"),
+        F_NEU("neu"),
+        F_LTU("ltu"),
+        F_LEU("leu"),
+        F_GTU("gtu"),
+        F_GEU("geu"),
+
+        // Floating-point operators testing for NaN
+        F_NUM("num"),
+        F_NAN("nan");
+
+        // @formatter:on
+
+        private final String operator;
+
+        private ConditionOperator(String op) {
+            this.operator = op;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
+    }
+
     public static class StandardFormat {
 
         protected Kind valueKind;
@@ -257,10 +313,23 @@
             space = ss;
         }
 
+        public String emitAddress(Variable var, Value val) {
+            return ("[" + emitRegister(var) + " + " + val + "]");
+        }
+
         @Override
-        public String emit() {
-            return (space.getStateName() + "." + typeForKind(valueKind) +
-                    emitRegister(dest) + emitRegister(source1) + emitValue(source2) + ";");
+        public String emitRegister(Variable var) {
+            return ("%r" + var.index);
+        }
+
+        public String emit(boolean isLoad) {
+            if (isLoad) {
+                return (space.getStateName() + "." + typeForKind(valueKind) + " " +
+                        emitRegister(dest) + ", " + emitAddress(source1, source2) + ";");
+            } else {
+                return (space.getStateName() + "." + typeForKind(valueKind) + " " +
+                        emitAddress(dest, source2) + ", " + emitRegister(source1) + ";");
+            }
         }
     }
 
@@ -456,10 +525,10 @@
         }
 
         public void emit(PTXAssembler asm) {
-            asm.emitString("ld." + super.emit());
+            asm.emitString("ld." + super.emit(true));
         }
     }
-    
+
     public static class St extends LoadStoreFormat {
 
         public St(PTXStateSpace space, Variable dst, Variable src1, Value src2) {
@@ -467,102 +536,30 @@
         }
 
         public void emit(PTXAssembler asm) {
-            asm.emitString("ld." + super.emit());
+            asm.emitString("st." + super.emit(false));
         }
     }
-    
+
     public final void exit() {
         emitString("exit;" + " " + "");
     }
-/*
-    public final void ld_global_b8(Register d, Register a, long immOff) {
-        emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_b16(Register d, Register a, long immOff) {
-        emitString("ld.global.b16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_b32(Register d, Register a, long immOff) {
-        emitString("ld.global.b32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_b64(Register d, Register a, long immOff) {
-        emitString("ld.global.b64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_u8(Register d, Register a, long immOff) {
-        emitString("ld.global.u8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
 
-    public final void ld_global_u16(Register d, Register a, long immOff) {
-        emitString("ld.global.u16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_u32(Register d, Register a, long immOff) {
-        emitString("ld.global.u32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_u64(Register d, Register a, long immOff) {
-        emitString("ld.global.u64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
+    public static class Param extends SingleOperandFormat {
 
-    public final void ld_global_s8(Register d, Register a, long immOff) {
-        emitString("ld.global.s8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_s16(Register d, Register a, long immOff) {
-        emitString("ld.global.s16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_s32(Register d, Register a, long immOff) {
-        emitString("ld.global.s32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
+        private boolean lastParameter;
 
-    public final void ld_global_s64(Register d, Register a, long immOff) {
-        emitString("ld.global.s64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_f32(Register d, Register a, long immOff) {
-        emitString("ld.global.f32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_f64(Register d, Register a, long immOff) {
-        emitString("ld.global.f64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    // Load from state space to destination register
-    public final void ld_from_state_space(String s, Register d, Register a, long immOff) {
-        emitString("ld" + s + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-    // Load return address from return parameter which is in .param state space
-    public final void ld_return_address(String s, Register d, Register a, long immOff) {
-        emitString("ld.param." + s + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
- */
+        public Param(Variable d, boolean lastParam) {
+            super(d, null);
+            setLastParameter(lastParam);
+        }
 
-    public final void mov_u64(@SuppressWarnings("unused") Register d, @SuppressWarnings("unused") AbstractAddress a) {
-        // emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void param_8_decl(Register d, boolean lastParam) {
-        emitString(".param" + " " + ".s8" + " " + d + (lastParam ? "" : ","));
-    }
+        public void setLastParameter(boolean value) {
+            lastParameter = value;
+        }
 
-    public final void param_16_decl(Register d, boolean lastParam) {
-        emitString(".param" + " " + ".s16" + " " + d + (lastParam ? "" : ","));
-    }
-
-    public final void param_u16_decl(Register d, boolean lastParam) {
-        emitString(".param" + " " + ".s16" + " " + d + (lastParam ? "" : ","));
-    }
-
-    public final void param_32_decl(Register d, boolean lastParam) {
-        emitString(".param" + " " + ".s32" + " " + d + (lastParam ? "" : ","));
-    }
-
-    public final void param_64_decl(Register d, boolean lastParam) {
-        emitString(".param" + " " + ".s64" + " " + d + (lastParam ? "" : ","));
+        public void emit(PTXAssembler asm) {
+            asm.emitString(".param " + typeForKind(dest.getKind()) + emitVariable(dest)  + (lastParameter ? "" : ","));
+        }
     }
 
     public final void popc_b32(Register d, Register a) {
@@ -581,317 +578,159 @@
         emitString("ret.uni;" + " " + "");
     }
 
-    public final void setp_eq_f32(Register a, Register b, int p) {
-        emitString("setp.eq.f32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_f32(Register a, Register b, int p) {
-        emitString("setp.ne.f32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_f32(Register a, Register b, int p) {
-        emitString("setp.lt.f32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_f32(Register a, Register b, int p) {
-        emitString("setp.le.f32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
+    public static class Setp  {
 
-    public final void setp_gt_f32(Register a, Register b, int p) {
-        emitString("setp.gt.f32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_f32(Register a, Register b, int p) {
-        emitString("setp.ge.f32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_f32(float f32, Register b, int p) {
-        emitString("setp.eq.f32" + " " + "%p" + p + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_f32(float f32, Register b, int p) {
-        emitString("setp.ne.f32" + " " + "%p" + p + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_f32(float f32, Register b, int p) {
-        emitString("setp.lt.f32" + " " + "%p" + p + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
+        private ConditionOperator  operator;
+        private Value first, second;
+        private Kind kind;
+        private int predicate;
 
-    public final void setp_le_f32(float f32, Register b, int p) {
-        emitString("setp.le.f32" + " " + "%p" + p + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_f32(float f32, Register b, int p) {
-        emitString("setp.gt.f32" + " " + "%p" + p + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_f32(float f32, Register b, int p) {
-        emitString("setp.ge.f32" + " " + "%p" + p + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_f64(double f64, Register b, int p) {
-        emitString("setp.eq.f64" + " " + "%p" + p + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_f64(double f64, Register b, int p) {
-        emitString("setp.ne.f64" + " " + "%p" + p + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_f64(double f64, Register b, int p) {
-        emitString("setp.lt.f64" + " " + "%p" + p + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_f64(double f64, Register b, int p) {
-        emitString("setp.le.f64" + " " + "%p" + p + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_f64(double f64, Register b, int p) {
-        emitString("setp.gt.f64" + " " + "%p" + p + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_f64(double f64, Register b, int p) {
-        emitString("setp.ge.f64" + " " + "%p" + p + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_s64(Register a, Register b, int p) {
-        emitString("setp.eq.s64" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
+        public Setp(Condition condition, Value first, Value second, int predicateRegisterNumber) {
+            setFirst(first);
+            setSecond(second);
+            setPredicate(predicateRegisterNumber);
+            setKind();
+            setConditionOperator(operatorForConditon(condition));
+        }
 
-    public final void setp_eq_s64(long s64, Register b, int p) {
-        emitString("setp.eq.s64" + " " + "%p" + p + ", " + s64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_s32(Register a, Register b, int p) {
-        emitString("setp.eq.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_s32(Register a, Register b, int p) {
-        emitString("setp.ne.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_s32(Register a, Register b, int p) {
-        emitString("setp.lt.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_s32(Register a, Register b, int p) {
-        emitString("setp.le.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
+        public void setFirst(Value v) {
+            first = v;
+        }
 
-    public final void setp_gt_s32(Register a, Register b, int p) {
-        emitString("setp.gt.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_s32(Register a, Register b, int p) {
-        emitString("setp.ge.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_s32(Register a, int s32, int p) {
-        emitString("setp.eq.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_ne_s32(Register a, int s32, int p) {
-        emitString("setp.ne.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_lt_s32(Register a, int s32, int p) {
-        emitString("setp.lt.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
+        public void setSecond(Value v) {
+            second = v;
+        }
 
-    public final void setp_le_s32(Register a, int s32, int p) {
-        emitString("setp.le.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_gt_s32(Register a, int s32, int p) {
-        emitString("setp.gt.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_ge_s32(Register a, int s32, int p) {
-        emitString("setp.ge.s32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_eq_s32(int s32, Register b, int p) {
-        emitString("setp.eq.s32" + " " + "%p" + p + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_s32(int s32, Register b, int p) {
-        emitString("setp.ne.s32" + " " + "%p" + p + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
+        public void setPredicate(int p) {
+            predicate = p;
+        }
 
-    public final void setp_lt_s32(int s32, Register b, int p) {
-        emitString("setp.lt.s32" + " " + "%p" + p + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_s32(int s32, Register b, int p) {
-        emitString("setp.le.s32" + " " + "%p" + p + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
+        public void setConditionOperator(ConditionOperator co) {
+            operator = co;
+        }
 
-    public final void setp_gt_s32(int s32, Register b, int p) {
-        emitString("setp.gt.s32" + " " + "%p" + p + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_s32(int s32, Register b, int p) {
-        emitString("setp.ge.s32" + " " + "%p" + p + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_u32(Register a, Register b, int p) {
-        emitString("setp.eq.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
+        private ConditionOperator operatorForConditon(Condition condition) {
+            char typeChar = kind.getTypeChar();
 
-    public final void setp_ne_u32(Register a, Register b, int p) {
-        emitString("setp.ne.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_u32(Register a, Register b, int p) {
-        emitString("setp.lt.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_u32(Register a, Register b, int p) {
-        emitString("setp.le.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_u32(Register a, Register b, int p) {
-        emitString("setp.gt.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_u32(Register a, Register b, int p) {
-        emitString("setp.ge.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_u32(Register a, int u32, int p) {
-        emitString("setp.eq.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_ne_u32(Register a, int u32, int p) {
-        emitString("setp.ne.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_lt_u32(Register a, int u32, int p) {
-        emitString("setp.lt.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_le_u32(Register a, int u32, int p) {
-        emitString("setp.le.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
+            switch (typeChar) {
+                case 'z':
+                case 'c':
+                case 'a':
+                    // unsigned
+                    switch (condition) {
+                        case EQ: return ConditionOperator.U_EQ;
+                        case NE: return ConditionOperator.U_NE;
+                        case LT: return ConditionOperator.U_LO;
+                        case LE: return ConditionOperator.U_LS;
+                        case GT: return ConditionOperator.U_HI;
+                        case GE: return ConditionOperator.U_HS;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere();
+                    }
+                case 'b':
+                case 's':
+                case 'i':
+                case 'j':
+                    // signed
+                    switch (condition) {
+                        case EQ: return ConditionOperator.S_EQ;
+                        case NE: return ConditionOperator.S_NE;
+                        case LT: return ConditionOperator.S_LT;
+                        case LE: return ConditionOperator.S_LE;
+                        case GT: return ConditionOperator.S_GT;
+                        case GE: return ConditionOperator.S_GE;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere();
+                    }
+                case 'f':
+                case 'd':
+                    // floating point - do these need to accept NaN??
+                    switch (condition) {
+                        case EQ: return ConditionOperator.F_EQ;
+                        case NE: return ConditionOperator.F_NE;
+                        case LT: return ConditionOperator.F_LT;
+                        case LE: return ConditionOperator.F_LE;
+                        case GT: return ConditionOperator.F_GT;
+                        case GE: return ConditionOperator.F_GE;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere();
+                    }
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
 
-    public final void setp_gt_u32(Register a, int u32, int p) {
-        emitString("setp.gt.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_ge_u32(Register a, int u32, int p) {
-        emitString("setp.ge.u32" + " " + "%p" + p + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_eq_u32(int u32, Register b, int p) {
-        emitString("setp.eq.u32" + " " + "%p" + p + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_u32(int u32, Register b, int p) {
-        emitString("setp.ne.u32" + " " + "%p" + p + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_u32(int u32, Register b, int p) {
-        emitString("setp.lt.u32" + " " + "%p" + p + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_u32(int u32, Register b, int p) {
-        emitString("setp.le.u32" + " " + "%p" + p + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_u32(int u32, Register b, int p) {
-        emitString("setp.gt.u32" + " " + "%p" + p + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_u32(int u32, Register b, int p) {
-        emitString("setp.ge.u32" + " " + "%p" + p + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    // Store in global state space
-/*
-    public final void st_global_b8(Register a, long immOff, Register b) {
-        emitString("st.global.b8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_b16(Register a, long immOff, Register b) {
-        emitString("st.global.b16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
+        public void setKind() {
+            assert isConstant(first) && isConstant(second) == false;
 
-    public final void st_global_b32(Register a, long immOff, Register b) {
-        emitString("st.global.b32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_b64(Register a, long immOff, Register b) {
-        emitString("st.global.b64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
+            if (isConstant(first)) {
+                kind = second.getKind();
+            } else {
+                kind = first.getKind();
+            }
+        }
+        
+        public String emitValue(Value v) {
+            assert v != null;
 
-    public final void st_global_u8(Register a, long immOff, Register b) {
-        emitString("st.global.u8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_u16(Register a, long immOff, Register b) {
-        emitString("st.global.u16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
+            if (isConstant(v)) {
+                return (", " + emitConstant(v));
+            } else {
+                return (", " + emitVariable((Variable) v));
+            }
+        }
 
-    public final void st_global_u32(Register a, long immOff, Register b) {
-        emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_u64(Register a, long immOff, Register b) {
-        emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
+        public String typeForKind(Kind k) {
+            switch (k.getTypeChar()) {
+                case 'z':
+                    return "u8";
+                case 'b':
+                    return "s8";
+                case 's':
+                    return "s16";
+                case 'c':
+                    return "u16";
+                case 'i':
+                    return "s32";
+                case 'f':
+                    return "f32";
+                case 'j':
+                    return "s64";
+                case 'd':
+                    return "f64";
+                case 'a':
+                    return "u64";
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
 
-    public final void st_global_s8(Register a, long immOff, Register b) {
-        emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
+        public String emitConstant(Value v) {
+            Constant constant = (Constant) v;
 
-    public final void st_global_s16(Register a, long immOff, Register b) {
-        emitString("st.global.s16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
+            switch (v.getKind().getTypeChar()) {
+                case 'i':
+                    return (String.valueOf((int) constant.asLong()));
+                case 'f':
+                    return (String.valueOf(constant.asFloat()));
+                case 'j':
+                    return (String.valueOf(constant.asLong()));
+                case 'd':
+                    return (String.valueOf(constant.asDouble()));
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+        
+        public String emitVariable(Variable v) {
+            return ("%r" + v.index);
+        }
 
-    public final void st_global_s32(Register a, long immOff, Register b) {
-        emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_s64(Register a, long immOff, Register b) {
-        emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+        public void emit(PTXAssembler asm) {
+            asm.emitString("setp." + operator.getOperator() + "." + typeForKind(kind) +
+                           " %p" + predicate + emitValue(first) + emitValue(second) + ";");
+        }
     }
-
-    public final void st_global_f32(Register a, long immOff, Register b) {
-        emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_f64(Register a, long immOff, Register b) {
-        emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    // Store return value
-    public final void st_global_return_value_s8(Register a, long immOff, Register b) {
-        emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_s32(Register a, long immOff, Register b) {
-        emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_s64(Register a, long immOff, Register b) {
-        emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_f32(Register a, long immOff, Register b) {
-        emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_f64(Register a, long immOff, Register b) {
-        emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_u32(Register a, long immOff, Register b) {
-        emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_u64(Register a, long immOff, Register b) {
-        emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-*/
     @Override
     public PTXAddress makeAddress(Register base, int displacement) {
         throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java	Tue Sep 24 15:35:59 2013 +0200
@@ -59,9 +59,12 @@
         paramTypeMap.put("HotSpotResolvedPrimitiveType<long>", "s64");
     }
 
+    /**
+     * Use the HSAIL register set when the compilation target is HSAIL.
+     */
     @Override
     public FrameMap newFrameMap() {
-        return new HSAILFrameMap(runtime(), target, runtime().lookupRegisterConfig());
+        return new HSAILFrameMap(runtime(), target, new HSAILRegisterConfig());
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Tue Sep 24 15:35:59 2013 +0200
@@ -23,33 +23,25 @@
 
 package com.oracle.graal.compiler.hsail;
 
-import static com.oracle.graal.api.code.CodeUtil.*;
-
+import java.lang.reflect.*;
 import java.util.logging.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CallingConvention.*;
-import com.oracle.graal.api.runtime.Graal;
-import com.oracle.graal.compiler.GraalCompiler;
-import com.oracle.graal.java.GraphBuilderConfiguration;
-import com.oracle.graal.java.GraphBuilderPhase;
-import com.oracle.graal.nodes.StructuredGraph;
-import com.oracle.graal.nodes.spi.GraalCodeCacheProvider;
-import com.oracle.graal.phases.OptimisticOptimizations;
-import com.oracle.graal.phases.PhasePlan;
-import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hsail.*;
+import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.nodes.spi.Replacements;
-import com.oracle.graal.compiler.target.Backend;
-import com.oracle.graal.hsail.*;
-
-import java.lang.reflect.Method;
 
 /**
  * Class that represents a HSAIL compilation result. Includes the compiled HSAIL code.
@@ -96,6 +88,33 @@
         return getHSAILCompilationResult(graph);
     }
 
+    /**
+     * HSAIL doesn't have a calling convention as such. Function arguments are actually passed in
+     * memory but then loaded into registers in the function body. This routine makes sure that
+     * arguments to a kernel or function are loaded (by the kernel or function body) into registers
+     * of the appropriate sizes. For example, int and float parameters should appear in S registers,
+     * whereas double and long parameters should appear in d registers.
+     */
+    public static CallingConvention getHSAILCallingConvention(CallingConvention.Type type, TargetDescription target, ResolvedJavaMethod method, boolean stackOnly) {
+        Signature sig = method.getSignature();
+        JavaType retType = sig.getReturnType(null);
+        int sigCount = sig.getParameterCount(false);
+        JavaType[] argTypes;
+        int argIndex = 0;
+        if (!Modifier.isStatic(method.getModifiers())) {
+            argTypes = new JavaType[sigCount + 1];
+            argTypes[argIndex++] = method.getDeclaringClass();
+        } else {
+            argTypes = new JavaType[sigCount];
+        }
+        for (int i = 0; i < sigCount; i++) {
+            argTypes[argIndex++] = sig.getParameterType(i, null);
+        }
+
+        RegisterConfig registerConfig = new HSAILRegisterConfig();
+        return registerConfig.getCallingConvention(type, retType, argTypes, target, stackOnly);
+    }
+
     public static HSAILCompilationResult getHSAILCompilationResult(StructuredGraph graph) {
         Debug.dump(graph, "Graph");
         TargetDescription target = new TargetDescription(new HSAIL(), true, 8, 0, true);
@@ -105,7 +124,7 @@
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new HSAILPhase());
         new HSAILPhase().apply(graph);
-        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        CallingConvention cc = getHSAILCallingConvention(Type.JavaCallee, target, graph.method(), false);
         try {
             CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, hsailBackend, target, null, phasePlan, OptimisticOptimizations.NONE,
                             new SpeculationLog(), suitesProvider.getDefaultSuites(), new CompilationResult());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Sep 24 15:35:59 2013 +0200
@@ -25,9 +25,11 @@
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
+import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 
 import org.junit.*;
 import org.junit.internal.*;
@@ -169,7 +171,7 @@
         return parse(getMethod(methodName));
     }
 
-    private static int compilationId = 0;
+    private static AtomicInteger compilationId = new AtomicInteger();
 
     /**
      * Compares two given objects for {@linkplain Assert#assertEquals(Object, Object) equality}.
@@ -206,11 +208,45 @@
         }
     }
 
+    @SuppressWarnings("serial")
+    public static class MultiCauseAssertionError extends AssertionError {
+
+        private Throwable[] causes;
+
+        public MultiCauseAssertionError(String message, Throwable... causes) {
+            super(message);
+            this.causes = causes;
+        }
+
+        @Override
+        public void printStackTrace(PrintStream out) {
+            super.printStackTrace(out);
+            int num = 0;
+            for (Throwable cause : causes) {
+                if (cause != null) {
+                    out.print("cause " + (num++));
+                    cause.printStackTrace(out);
+                }
+            }
+        }
+
+        @Override
+        public void printStackTrace(PrintWriter out) {
+            super.printStackTrace(out);
+            int num = 0;
+            for (Throwable cause : causes) {
+                if (cause != null) {
+                    out.print("cause " + (num++) + ": ");
+                    cause.printStackTrace(out);
+                }
+            }
+        }
+    }
+
     protected void testN(int n, final String name, final Object... args) {
-        final Throwable[] errors = new Throwable[n];
+        final List<Throwable> errors = new ArrayList<>(n);
         Thread[] threads = new Thread[n];
         for (int i = 0; i < n; i++) {
-            final int idx = i;
             Thread t = new Thread(i + ":" + name) {
 
                 @Override
@@ -218,26 +254,23 @@
                     try {
                         test(name, args);
                     } catch (Throwable e) {
-                        errors[idx] = e;
+                        errors.add(e);
                     }
                 }
             };
             threads[i] = t;
             t.start();
         }
-        int failed = 0;
         for (int i = 0; i < n; i++) {
             try {
                 threads[i].join();
             } catch (InterruptedException e) {
-                errors[i] = e;
-            }
-            if (errors[i] != null) {
-                errors[i].printStackTrace();
-                failed++;
+                errors.add(e);
             }
         }
-        Assert.assertTrue(failed + " of " + n + " failed", failed == 0);
+        if (!errors.isEmpty()) {
+            throw new MultiCauseAssertionError(errors.size() + " failures", errors.toArray(new Throwable[errors.size()]));
+        }
     }
 
     protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
@@ -421,7 +454,7 @@
             }
         }
 
-        final int id = compilationId++;
+        final int id = compilationId.incrementAndGet();
 
         InstalledCode installedCode = Debug.scope("Compiling", new Object[]{runtime, new DebugDumpScope(String.valueOf(id), true)}, new Callable<InstalledCode>() {
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Sep 24 15:35:59 2013 +0200
@@ -81,7 +81,7 @@
 
         appendPhase(new LoopSafepointEliminationPhase());
 
-        appendPhase(new SafepointInsertionPhase());
+        appendPhase(new LoopSafepointInsertionPhase());
 
         appendPhase(new GuardLoweringPhase());
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Sep 24 15:35:59 2013 +0200
@@ -56,8 +56,8 @@
     private int deletedNodeCount;
     private GraphEventLog eventLog;
 
-    NodeChangedListener inputChanged;
-    NodeChangedListener usagesDroppedZero;
+    NodeChangedListener inputChangedListener;
+    NodeChangedListener usagesDroppedToZeroListener;
     private final HashMap<CacheEntry, Node> cachedNodes = new HashMap<>();
 
     private static final class CacheEntry {
@@ -250,24 +250,54 @@
         void nodeChanged(Node node);
     }
 
-    public void trackInputChange(NodeChangedListener inputChangedListener) {
-        assert this.inputChanged == null;
-        this.inputChanged = inputChangedListener;
+    private static class ChainedNodeChangedListener implements NodeChangedListener {
+
+        NodeChangedListener head;
+        NodeChangedListener next;
+
+        ChainedNodeChangedListener(NodeChangedListener head, NodeChangedListener next) {
+            this.head = head;
+            this.next = next;
+        }
+
+        public void nodeChanged(Node node) {
+            head.nodeChanged(node);
+            next.nodeChanged(node);
+        }
+    }
+
+    public void trackInputChange(NodeChangedListener listener) {
+        if (inputChangedListener == null) {
+            inputChangedListener = listener;
+        } else {
+            inputChangedListener = new ChainedNodeChangedListener(listener, inputChangedListener);
+        }
     }
 
     public void stopTrackingInputChange() {
-        assert inputChanged != null;
-        inputChanged = null;
+        assert inputChangedListener != null;
+        if (inputChangedListener instanceof ChainedNodeChangedListener) {
+            inputChangedListener = ((ChainedNodeChangedListener) inputChangedListener).next;
+        } else {
+            inputChangedListener = null;
+        }
     }
 
-    public void trackUsagesDroppedZero(NodeChangedListener usagesDroppedZeroListener) {
-        assert this.usagesDroppedZero == null;
-        this.usagesDroppedZero = usagesDroppedZeroListener;
+    public void trackUsagesDroppedZero(NodeChangedListener listener) {
+        if (usagesDroppedToZeroListener == null) {
+            usagesDroppedToZeroListener = listener;
+        } else {
+            usagesDroppedToZeroListener = new ChainedNodeChangedListener(listener, usagesDroppedToZeroListener);
+        }
     }
 
     public void stopTrackingUsagesDroppedZero() {
-        assert usagesDroppedZero != null;
-        usagesDroppedZero = null;
+        assert usagesDroppedToZeroListener != null;
+        if (usagesDroppedToZeroListener instanceof ChainedNodeChangedListener) {
+            usagesDroppedToZeroListener = ((ChainedNodeChangedListener) usagesDroppedToZeroListener).next;
+        } else {
+            usagesDroppedToZeroListener = null;
+        }
     }
 
     /**
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Sep 24 15:35:59 2013 +0200
@@ -433,15 +433,15 @@
                 assert assertTrue(result, "not found in usages, old input: %s", oldInput);
             }
             if (newInput != null) {
-                NodeChangedListener inputChanged = graph.inputChanged;
-                if (inputChanged != null) {
-                    inputChanged.nodeChanged(this);
+                NodeChangedListener listener = graph.inputChangedListener;
+                if (listener != null) {
+                    listener.nodeChanged(this);
                 }
                 newInput.addUsage(this);
             } else if (oldInput != null && oldInput.usages().isEmpty()) {
-                NodeChangedListener nodeChangedListener = graph.usagesDroppedZero;
-                if (nodeChangedListener != null) {
-                    nodeChangedListener.nodeChanged(oldInput);
+                NodeChangedListener listener = graph.usagesDroppedToZeroListener;
+                if (listener != null) {
+                    listener.nodeChanged(oldInput);
                 }
             }
         }
@@ -495,9 +495,9 @@
             boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
             assert assertTrue(result, "not found in inputs, usage: %s", usage);
             if (other != null) {
-                NodeChangedListener inputChanged = graph.inputChanged;
-                if (inputChanged != null) {
-                    inputChanged.nodeChanged(usage);
+                NodeChangedListener listener = graph.inputChangedListener;
+                if (listener != null) {
+                    listener.nodeChanged(usage);
                 }
                 other.addUsage(usage);
             }
@@ -542,9 +542,9 @@
         for (Node input : inputs()) {
             removeThisFromUsages(input);
             if (input.usages().isEmpty()) {
-                NodeChangedListener nodeChangedListener = graph.usagesDroppedZero;
-                if (nodeChangedListener != null) {
-                    nodeChangedListener.nodeChanged(input);
+                NodeChangedListener listener = graph.usagesDroppedToZeroListener;
+                if (listener != null) {
+                    listener.nodeChanged(input);
                 }
             }
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Sep 24 15:35:59 2013 +0200
@@ -176,7 +176,7 @@
 
     @Override
     protected void emitReturn(Value input) {
-        append(new AMD64HotSpotReturnOp(input));
+        append(new AMD64HotSpotReturnOp(input, getStub() != null));
     }
 
     @Override
@@ -287,7 +287,7 @@
     @Override
     public void visitSafepointNode(SafepointNode i) {
         LIRFrameState info = state(i);
-        append(new AMD64SafepointOp(info, runtime().config, this));
+        append(new AMD64HotSpotSafepointOp(info, runtime().config, this));
     }
 
     @SuppressWarnings("hiding")
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Tue Sep 24 15:35:59 2013 +0200
@@ -22,10 +22,16 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -36,14 +42,31 @@
 final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp {
 
     @Use({REG, ILLEGAL}) protected Value value;
+    private final boolean isStub;
 
-    AMD64HotSpotReturnOp(Value value) {
+    AMD64HotSpotReturnOp(Value value, boolean isStub) {
         this.value = value;
+        this.isStub = isStub;
     }
 
+    private static Register findPollOnReturnScratchRegister() {
+        RegisterConfig config = HotSpotGraalRuntime.graalRuntime().getRuntime().lookupRegisterConfig();
+        for (Register r : config.getAllocatableRegisters(Kind.Long)) {
+            if (r != config.getReturnRegister(Kind.Long) && r != AMD64.rbp) {
+                return r;
+            }
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    private static final Register scratchForSafepointOnReturn = findPollOnReturnScratchRegister();
+
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         leaveFrameAndRestoreRbp(tasm, masm);
+        if (!isStub && (tasm.frameContext != null || !OptEliminateSafepoints.getValue())) {
+            AMD64HotSpotSafepointOp.emitCode(tasm, masm, graalRuntime().getConfig(), true, null, scratchForSafepointOnReturn);
+        }
         masm.ret(0);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.hotspot.bridge.Marks.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Emits a safepoint poll.
+ */
+@Opcode("SAFEPOINT")
+public class AMD64HotSpotSafepointOp extends AMD64LIRInstruction {
+
+    @State protected LIRFrameState state;
+    @Temp({OperandFlag.REG}) private AllocatableValue temp;
+
+    private final HotSpotVMConfig config;
+
+    public AMD64HotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
+        this.state = state;
+        this.config = config;
+        temp = tool.newVariable(tool.target().wordKind);
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) {
+        RegisterValue scratch = (RegisterValue) temp;
+        emitCode(tasm, asm, config, false, state, scratch.getRegister());
+    }
+
+    public static void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
+        final int pos = asm.codeBuffer.position();
+        if (config.isPollingPageFar) {
+            asm.movq(scratch, config.safepointPollingAddress);
+            tasm.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR);
+            if (state != null) {
+                tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
+            }
+            asm.movq(scratch, new AMD64Address(scratch));
+        } else {
+            tasm.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR);
+            if (state != null) {
+                tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
+            }
+            // The C++ code transforms the polling page offset into an RIP displacement
+            // to the real address at that offset in the polling page.
+            asm.movq(scratch, new AMD64Address(rip, 0));
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Fri Sep 20 11:25:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.amd64;
-
-import static com.oracle.graal.amd64.AMD64.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.bridge.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * Emits a safepoint poll.
- */
-@Opcode("SAFEPOINT")
-public class AMD64SafepointOp extends AMD64LIRInstruction {
-
-    @State protected LIRFrameState state;
-    @Temp({OperandFlag.REG}) private AllocatableValue temp;
-
-    private final HotSpotVMConfig config;
-
-    public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
-        this.state = state;
-        this.config = config;
-        temp = tool.newVariable(tool.target().wordKind);
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) {
-        final int pos = asm.codeBuffer.position();
-        RegisterValue scratch = (RegisterValue) temp;
-        if (config.isPollingPageFar) {
-            asm.movq(scratch.getRegister(), config.safepointPollingAddress);
-            tasm.recordMark(Marks.MARK_POLL_FAR);
-            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
-            asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister()));
-        } else {
-            tasm.recordMark(Marks.MARK_POLL_NEAR);
-            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
-            // The C++ code transforms the polling page offset into an RIP displacement
-            // to the real address at that offset in the polling page.
-            asm.movq(scratch.getRegister(), new AMD64Address(rip, 0));
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Sep 24 15:35:59 2013 +0200
@@ -39,7 +39,10 @@
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.sparc.SPARCMove.*;
+import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp;
+import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
+import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp;
+import com.oracle.graal.lir.sparc.SPARCMove.StoreOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
@@ -103,9 +106,14 @@
     }
 
     @Override
+    protected void emitReturn(Value input) {
+        append(new SPARCHotSpotReturnOp(input, getStub() != null));
+    }
+
+    @Override
     public void visitSafepointNode(SafepointNode i) {
         LIRFrameState info = state(i);
-        append(new SPARCSafepointOp(info, runtime().config, this));
+        append(new SPARCHotSpotSafepointOp(info, runtime().config, this));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp;
+import com.oracle.graal.sparc.*;
+
+/**
+ * Returns from a function.
+ */
+@Opcode("RETURN")
+final class SPARCHotSpotReturnOp extends SPARCHotSpotEpilogueOp {
+
+    @Use({REG, ILLEGAL}) protected Value value;
+    private final boolean isStub;
+
+    SPARCHotSpotReturnOp(Value value, boolean isStub) {
+        this.value = value;
+        this.isStub = isStub;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        if (!isStub && (tasm.frameContext != null || !OptEliminateSafepoints.getValue())) {
+            // Using the same scratch register as LIR_Assembler::return_op
+            // in c1_LIRAssembler_sparc.cpp
+            SPARCHotSpotSafepointOp.emitCode(tasm, masm, graalRuntime().getConfig(), true, null, SPARC.l0);
+        }
+        ReturnOp.emitCodeHelper(tasm, masm);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011, 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.hotspot.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.hotspot.bridge.Marks.*;
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Emits a safepoint poll.
+ */
+@Opcode("SAFEPOINT")
+public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction {
+
+    @State protected LIRFrameState state;
+    @Temp({OperandFlag.REG}) private AllocatableValue temp;
+
+    private final HotSpotVMConfig config;
+
+    public SPARCHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
+        this.state = state;
+        this.config = config;
+        temp = tool.newVariable(tool.target().wordKind);
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        Register scratch = ((RegisterValue) temp).getRegister();
+        emitCode(tasm, masm, config, false, state, scratch);
+    }
+
+    public static void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
+        final int pos = masm.codeBuffer.position();
+        new Setx(config.safepointPollingAddress, scratch).emit(masm);
+        assert !config.isPollingPageFar;
+        tasm.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR);
+        if (state != null) {
+            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
+        }
+        new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCSafepointOp.java	Fri Sep 20 11:25:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2011, 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.hotspot.sparc;
-
-import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
-import static com.oracle.graal.sparc.SPARC.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * Emits a safepoint poll.
- */
-@Opcode("SAFEPOINT")
-public class SPARCSafepointOp extends SPARCLIRInstruction {
-
-    @State protected LIRFrameState state;
-    @Temp({OperandFlag.REG}) private AllocatableValue temp;
-
-    private final HotSpotVMConfig config;
-
-    public SPARCSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
-        this.state = state;
-        this.config = config;
-        temp = tool.newVariable(tool.target().wordKind);
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-        final int pos = masm.codeBuffer.position();
-        Register scratch = ((RegisterValue) temp).getRegister();
-        new Setx(config.safepointPollingAddress, scratch).emit(masm);
-        tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
-        new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm);
-    }
-}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Tue Sep 24 15:35:59 2013 +0200
@@ -175,7 +175,7 @@
         StructuredGraph result = compile("getBoxedBoolean", true);
 
         assertEquals(2, result.getNodes(FloatingReadNode.class).count());
-        assertEquals(1, result.getNodes(UnsafeCastNode.class).count());
+        assertEquals(1, result.getNodes(PiNode.class).count());
         assertEquals(1, result.getNodes().filter(ConstantNode.class).count());
         ConstantNode constant = result.getNodes().filter(ConstantNode.class).first();
         assertEquals(Kind.Long, constant.kind());
@@ -186,7 +186,7 @@
     public void testBoxedBoolean() {
         StructuredGraph result = compile("getBoxedBoolean", false);
         assertEquals(0, result.getNodes(FloatingReadNode.class).count());
-        assertEquals(0, result.getNodes(UnsafeCastNode.class).count());
+        assertEquals(0, result.getNodes(PiNode.class).count());
         assertEquals(1, result.getNodes().filter(ConstantNode.class).count());
         ConstantNode constant = result.getNodes().filter(ConstantNode.class).first();
         assertEquals(Kind.Object, constant.kind());
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Sep 24 15:35:59 2013 +0200
@@ -638,7 +638,7 @@
 
                 new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
                 new GuardLoweringPhase().apply(graph, midTierContext);
-                new SafepointInsertionPhase().apply(graph);
+                new LoopSafepointInsertionPhase().apply(graph);
                 new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
 
                 new WriteBarrierAdditionPhase().apply(graph);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -100,7 +100,7 @@
     }
 
     @Override
-    protected StructuredGraph getSnippetGraph(final LoweringTool tool) {
+    protected StructuredGraph getLoweredSnippetGraph(final LoweringTool tool) {
         if (!shouldIntrinsify(getTargetMethod())) {
             return null;
         }
@@ -119,10 +119,9 @@
             replaceSnippetInvokes(snippetGraph);
         } else {
             assert snippetGraph != null : "ArrayCopySnippets should be installed";
-
+            snippetGraph = snippetGraph.copy();
             if (getLength().isConstant() && getLength().asConstant().asInt() <= GraalOptions.MaximumEscapeAnalysisArrayLength.getValue()) {
-                final StructuredGraph copy = snippetGraph.copy();
-                snippetGraph = copy;
+                final StructuredGraph copy = snippetGraph;
                 Debug.scope("ArrayCopySnippetSpecialization", snippetGraph.method(), new Runnable() {
 
                     @Override
@@ -130,10 +129,9 @@
                         unrollFixedLengthLoop(copy, getLength().asConstant().asInt(), tool);
                     }
                 });
-
             }
         }
-        return snippetGraph;
+        return lowerReplacement(snippetGraph, tool);
     }
 
     private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Tue Sep 24 15:35:59 2013 +0200
@@ -26,8 +26,8 @@
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
+import static com.oracle.graal.nodes.PiNode.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
-import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
@@ -59,7 +59,7 @@
             }
         }
         BeginNode anchorNode = BeginNode.anchor();
-        return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
+        return piCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     public static class Templates extends AbstractTemplates {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Tue Sep 24 15:35:59 2013 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
+import static com.oracle.graal.nodes.PiNode.*;
 
 import java.lang.reflect.*;
 
@@ -96,7 +96,7 @@
                     if (superKlass.equal(0)) {
                         return null;
                     } else {
-                        return unsafeCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
+                        return piCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
                     }
                 }
             }
@@ -110,7 +110,7 @@
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
             if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
-                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
+                return piCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
             }
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Tue Sep 24 15:35:59 2013 +0200
@@ -24,7 +24,7 @@
 
 import static com.oracle.graal.hotspot.meta.HotSpotRuntime.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
+import static com.oracle.graal.nodes.PiNode.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
@@ -57,7 +57,7 @@
         Object exception = readExceptionOop(thread);
         writeExceptionOop(thread, null);
         writeExceptionPc(thread, Word.zero());
-        return unsafeCast(exception, StampFactory.forNodeIntrinsic());
+        return piCast(exception, StampFactory.forNodeIntrinsic());
     }
 
     public static class Templates extends AbstractTemplates {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Sep 24 15:35:59 2013 +0200
@@ -25,9 +25,9 @@
 import static com.oracle.graal.api.code.UnsignedMath.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.nodes.PiArrayNode.*;
+import static com.oracle.graal.nodes.PiNode.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
-import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*;
-import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*;
@@ -35,6 +35,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
@@ -87,8 +89,7 @@
             new_stub.inc();
             result = NewInstanceStubCall.call(hub);
         }
-        BeginNode anchorNode = BeginNode.anchor();
-        return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode);
+        return piCast(verifyOop(result), StampFactory.forNodeIntrinsic());
     }
 
     /**
@@ -121,8 +122,7 @@
             newarray_stub.inc();
             result = NewArrayStubCall.call(hub, length);
         }
-        BeginNode anchorNode = BeginNode.anchor();
-        return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode);
+        return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
     }
 
     public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -53,7 +53,7 @@
     }
 
     @Override
-    protected StructuredGraph getSnippetGraph(LoweringTool tool) {
+    protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
         if (!shouldIntrinsify(getTargetMethod())) {
             return null;
         }
@@ -82,7 +82,7 @@
         });
 
         assert snippetGraph != null : "ObjectCloneSnippets should be installed";
-        return snippetGraph;
+        return lowerReplacement(snippetGraph.copy(), tool);
     }
 
     private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Tue Sep 24 15:35:59 2013 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
+import static com.oracle.graal.nodes.PiNode.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
@@ -41,7 +41,7 @@
     @MethodSubstitution(isStatic = false, forced = true)
     public static Class<?> getClass(final Object thisObj) {
         Word hub = loadHub(thisObj);
-        return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
+        return piCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -112,11 +112,7 @@
 
     @Override
     public LocationIdentity getLocationIdentity() {
-        if (elementKind == null) {
-            return ANY_LOCATION;
-        } else {
-            return NamedLocationIdentity.getArrayLocation(elementKind);
-        }
+        return ANY_LOCATION;
     }
 
     @NodeIntrinsic
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.hsail;
+
+import com.oracle.graal.api.code.*;
+
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+
+import static com.oracle.graal.hsail.HSAIL.*;
+
+/**
+ * This class defines a higher level interface for the register allocator to be able to access info
+ * about the {@link HSAIL} register set.
+ * 
+ * Note: In HSAIL, the number of registers of each type is actually a variable number that must
+ * satisfy the equation: Total num of registers = No. of S registers + 2 * (No. of D registers) + 4
+ * * (No. of Q registers) = 128 In other words we can have up to 128S or 64 D or 32Q or a blend.
+ * 
+ * For now we haven't implemented support for a variable sized register file. Instead we've fixed
+ * the number of registers of each type so that they satisfy the above equation. See {@link HSAIL}
+ * for more details.
+ */
+public class HSAILRegisterConfig implements RegisterConfig {
+
+    private final Register[] allocatable = {s0, s1, s2, s3, s4, s5, s6, /* s7, */s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31,
+                    d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15};
+
+    private final Register[] regBitness32 = {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31};
+    private final Register[] regBitness64 = {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15};
+    private final RegisterAttributes[] attributesMap = RegisterAttributes.createMap(this, HSAIL.allRegisters);
+
+    @Override
+    public Register getReturnRegister(Kind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+            case Object:
+                return s0;
+            case Float:
+            case Double:
+                return d0;
+            case Void:
+            case Illegal:
+                return null;
+            default:
+                throw new UnsupportedOperationException("no return register for type " + kind);
+        }
+    }
+
+    @Override
+    public Register getFrameRegister() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
+        return callingConvention(regBitness32, regBitness64, returnType, parameterTypes, type, target, stackOnly);
+    }
+
+    private CallingConvention callingConvention(Register[] generalParameterRegisters, Register[] longParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type,
+                    TargetDescription target, boolean stackOnly) {
+        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+        int currentRegs32 = 0;
+        int currentRegs64 = 0;
+        int currentStackOffset = 0;
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            final Kind kind = parameterTypes[i].getKind();
+
+            switch (kind) {
+                case Byte:
+                case Boolean:
+                case Short:
+                case Char:
+                case Int:
+                case Float:
+
+                    if (!stackOnly && currentRegs32 < generalParameterRegisters.length) {
+                        Register register = generalParameterRegisters[currentRegs32++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                case Long:
+                case Object:
+                case Double:
+                    if (!stackOnly && currentRegs64 < longParameterRegisters.length) {
+                        Register register = longParameterRegisters[currentRegs64++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+
+            if (locations[i] == null) {
+                locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
+                currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize);
+            }
+        }
+
+        Kind returnKind = returnType == null ? Kind.Void : returnType.getKind();
+        AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind);
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
+    }
+
+    @Override
+    public Register[] getCallingConventionRegisters(Type type, Kind kind) {
+        throw new GraalInternalError("getCallingConventinoRegisters unimplemented");
+    }
+
+    @Override
+    public Register[] getAllocatableRegisters() {
+        return allocatable.clone();
+    }
+
+    @Override
+    public Register[] getAllocatableRegisters(PlatformKind kind) {
+        Kind k = (Kind) kind;
+        switch (k) {
+            case Int:
+            case Short:
+            case Byte:
+            case Float:
+                return regBitness32.clone();
+            case Long:
+            case Double:
+            case Object:
+                return regBitness64.clone();
+
+            default:
+                throw new GraalInternalError("unknown register allocation");
+        }
+    }
+
+    @Override
+    public Register[] getCallerSaveRegisters() {
+        // TODO Auto-generated method stub
+        return new Register[0];
+    }
+
+    @Override
+    public CalleeSaveLayout getCalleeSaveLayout() {
+        return null;
+    }
+
+    @Override
+    public RegisterAttributes[] getAttributesMap() {
+        return attributesMap.clone();
+    }
+
+    @Override
+    public Register getRegisterForRole(int id) {
+        throw new UnsupportedOperationException();
+    }
+
+    public HSAILRegisterConfig() {
+
+    }
+}
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Tue Sep 24 15:35:59 2013 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.lir.ptx;
 
+import static com.oracle.graal.asm.ptx.PTXAssembler.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
@@ -55,7 +55,7 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            emit(tasm, masm, opcode, condition, x, y, predRegNum);
+            emit(masm, opcode, condition, x, y, predRegNum);
         }
 
         @Override
@@ -67,42 +67,18 @@
         }
     }
 
-    public static void emit(TargetMethodAssembler tasm, PTXAssembler masm,
-                            PTXCompare opcode, Condition condition,
-                            Value x, Value y, int p) {
+    public static void emit(PTXAssembler masm, PTXCompare opcode,
+                            Condition condition, Value x, Value y, int p) {
         if (isConstant(x)) {
+            new Setp(condition, x, y, p).emit(masm);
+        } else if (isConstant(y)) {
             switch (opcode) {
                 case ICMP:
-                    emitCompareConstReg(masm, condition, tasm.asIntConst(x), asIntReg(y), p);
-                    break;
-                case FCMP:
-                    emitCompareConstReg(masm, condition, tasm.asFloatConst(x), asFloatReg(y), p);
-                    break;
-                case DCMP:
-                    emitCompareConstReg(masm, condition, tasm.asDoubleConst(x), asDoubleReg(y), p);
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
-        } else if (isConstant(y)) {
-            Register a = asIntReg(x);
-            int b = tasm.asIntConst(y);
-            switch (opcode) {
-                case ICMP:
-                    emitCompareRegConst(masm, condition, a, b, p);
+                    new Setp(condition, x, y, p).emit(masm);
                     break;
                 case ACMP:
                     if (((Constant) y).isNull()) {
-                        switch (condition) {
-                            case EQ:
-                                masm.setp_eq_s32(a, b, p);
-                                break;
-                            case NE:
-                                masm.setp_ne_s32(a, b, p);
-                                break;
-                            default:
-                                throw GraalInternalError.shouldNotReachHere();
-                        }
+                        new Setp(condition, x, y, p).emit(masm);
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons");
                     }
@@ -111,183 +87,8 @@
                     throw GraalInternalError.shouldNotReachHere();
             }
         } else {
-            switch (opcode) {
-                case ICMP:
-                    emitCompareRegReg(masm, condition, asIntReg(x), asIntReg(y), p);
-                    break;
-                case LCMP:
-                    emitCompareRegReg(masm, condition, asLongReg(x), asLongReg(y), p);
-                    break;
-                case FCMP:
-                    emitCompareRegReg(masm, condition, asFloatReg(x), asFloatReg(y), p);
-                    break;
-                case DCMP:
-                    emitCompareRegReg(masm, condition, asDoubleReg(x), asDoubleReg(y), p);
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
-            }
-        }
-    }
-
-    private static void emitCompareConstReg(PTXAssembler masm, Condition condition, float a, Register b, int p) {
-        switch (condition) {
-        case EQ:
-            masm.setp_eq_f32(a, b, p);
-            break;
-        case NE:
-            masm.setp_ne_f32(a, b, p);
-            break;
-        case LT:
-            masm.setp_lt_f32(a, b, p);
-            break;
-        case LE:
-            masm.setp_le_f32(a, b, p);
-            break;
-        case GT:
-            masm.setp_gt_f32(a, b, p);
-            break;
-        case GE:
-            masm.setp_ge_f32(a, b, p);
-            break;
-        default:
-            throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    private static void emitCompareConstReg(PTXAssembler masm, Condition condition, double a, Register b, int p) {
-        switch (condition) {
-        case EQ:
-            masm.setp_eq_f64(a, b, p);
-            break;
-        case NE:
-            masm.setp_ne_f64(a, b, p);
-            break;
-        case LT:
-            masm.setp_lt_f64(a, b, p);
-            break;
-        case LE:
-            masm.setp_le_f64(a, b, p);
-            break;
-        case GT:
-            masm.setp_gt_f64(a, b, p);
-            break;
-        case GE:
-            masm.setp_ge_f64(a, b, p);
-            break;
-        default:
-            throw GraalInternalError.shouldNotReachHere();
+            new Setp(condition, x, y, p).emit(masm);
         }
     }
 
-    private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b, int p) {
-        switch (condition) {
-            case EQ:
-                masm.setp_eq_s32(a, b, p);
-                break;
-            case NE:
-                masm.setp_ne_s32(a, b, p);
-                break;
-            case LT:
-                masm.setp_lt_s32(a, b, p);
-                break;
-            case LE:
-                masm.setp_le_s32(a, b, p);
-                break;
-            case GT:
-                masm.setp_gt_s32(a, b, p);
-                break;
-            case GE:
-                masm.setp_ge_s32(a, b, p);
-                break;
-            case AT:
-                masm.setp_gt_u32(a, b, p);
-                break;
-            case AE:
-                masm.setp_ge_u32(a, b, p);
-                break;
-            case BT:
-                masm.setp_lt_u32(a, b, p);
-                break;
-            case BE:
-                masm.setp_le_u32(a, b, p);
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    private static void emitCompareRegConst(PTXAssembler masm, Condition condition, Register a, int b, int p) {
-        switch (condition) {
-            case EQ:
-                masm.setp_eq_s32(a, b, p);
-                break;
-            case NE:
-                masm.setp_ne_s32(a, b, p);
-                break;
-            case LT:
-                masm.setp_lt_s32(a, b, p);
-                break;
-            case LE:
-                masm.setp_le_s32(a, b, p);
-                break;
-            case GT:
-                masm.setp_gt_s32(a, b, p);
-                break;
-            case GE:
-                masm.setp_ge_s32(a, b, p);
-                break;
-            case AT:
-                masm.setp_gt_u32(a, b, p);
-                break;
-            case AE:
-                masm.setp_ge_u32(a, b, p);
-                break;
-            case BT:
-                masm.setp_lt_u32(a, b, p);
-                break;
-            case BE:
-                masm.setp_le_u32(a, b, p);
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    private static void emitCompareRegReg(PTXAssembler masm, Condition condition, Register a, Register b, int p) {
-        switch (condition) {
-            case EQ:
-                masm.setp_eq_s32(a, b, p);
-                break;
-            case NE:
-                masm.setp_ne_s32(a, b, p);
-                break;
-            case LT:
-                masm.setp_lt_s32(a, b, p);
-                break;
-            case LE:
-                masm.setp_le_s32(a, b, p);
-                break;
-            case GT:
-                masm.setp_gt_s32(a, b, p);
-                break;
-            case GE:
-                masm.setp_ge_s32(a, b, p);
-                break;
-            case AT:
-                masm.setp_gt_u32(a, b, p);
-                break;
-            case AE:
-                masm.setp_ge_u32(a, b, p);
-                break;
-            case BT:
-                masm.setp_lt_u32(a, b, p);
-                break;
-            case BE:
-                masm.setp_le_u32(a, b, p);
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
 }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Tue Sep 24 15:35:59 2013 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.lir.ptx;
 
-import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.ptx.PTXAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.nodes.calc.Condition.*;
 
 import com.oracle.graal.api.code.CompilationResult.JumpTable;
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.ptx.*;
@@ -167,29 +167,20 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            if (key.getKind() == Kind.Int) {
-                Register intKey = asIntReg(key);
+            Kind keyKind = key.getKind();
+
+            if (keyKind == Kind.Int || keyKind == Kind.Long) {
                 for (int i = 0; i < keyConstants.length; i++) {
                     if (tasm.runtime.needsDataPatch(keyConstants[i])) {
                         tasm.recordDataReferenceInCode(keyConstants[i], 0, true);
                     }
-                    long lc = keyConstants[i].asLong();
-                    assert NumUtil.isInt(lc);
-                    masm.setp_eq_s32((int) lc, intKey, predRegNum);
+                    new Setp(EQ, keyConstants[i], key, predRegNum).emit(masm);
                     masm.bra(masm.nameOf(keyTargets[i].label()), predRegNum);
                 }
-            } else if (key.getKind() == Kind.Long) {
-                Register longKey = asLongReg(key);
+            } else if (keyKind == Kind.Object) {
                 for (int i = 0; i < keyConstants.length; i++) {
-                    masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]), longKey, predRegNum);
-                    masm.bra(masm.nameOf(keyTargets[i].label()), predRegNum);
-                }
-            } else if (key.getKind() == Kind.Object) {
-                Register intKey = asObjectReg(key);
-                Register temp = asObjectReg(scratch);
-                for (int i = 0; i < keyConstants.length; i++) {
-                    PTXMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
-                    masm.setp_eq_u32(intKey, temp, predRegNum);
+                    PTXMove.move(tasm, masm, scratch, keyConstants[i]);
+                    new Setp(EQ, keyConstants[i], scratch, predRegNum).emit(masm);
                     masm.bra(keyTargets[i].label().toString(), predRegNum);
                 }
             } else {
@@ -234,21 +225,21 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch), predRegNum);
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets, index, scratch, predRegNum);
         }
     }
 
     @SuppressWarnings("unused")
-    private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, Register value, Register scratch, int predNum) {
+    private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value value, Value scratch, int predNum) {
         Buffer buf = masm.codeBuffer;
         // Compare index against jump table bounds
         int highKey = lowKey + targets.length - 1;
         if (lowKey != 0) {
             // subtract the low value from the switch value
             // new Sub(value, value, lowKey).emit(masm);
-            masm.setp_gt_s32(value, highKey - lowKey, predNum);
+            new Setp(GT, value, Constant.forInt(highKey - lowKey), predNum).emit(masm);
         } else {
-            masm.setp_gt_s32(value, highKey, predNum);
+            new Setp(GT, value, Constant.forInt(highKey), predNum).emit(masm);
         }
 
         // Jump to default target if index is not within the jump table
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXParameterOp.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXParameterOp.java	Tue Sep 24 15:35:59 2013 +0200
@@ -23,12 +23,11 @@
 
 package com.oracle.graal.lir.ptx;
 
-import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.ptx.PTXAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -46,35 +45,7 @@
         // Emit parameter directives for arguments
         int argCount = params.length;
         for (int i = 0; i < argCount; i++) {
-            Kind paramKind = params[i].getKind();
-            switch (paramKind) {
-            case Byte:
-                masm.param_8_decl(asRegister(params[i]), (i == (argCount - 1)));
-                break;
-            case Short:
-                masm.param_16_decl(asRegister(params[i]), (i == (argCount - 1)));
-                break;
-            case Char:
-                masm.param_u16_decl(asRegister(params[i]), (i == (argCount - 1)));
-                break;
-            case Int:
-                masm.param_32_decl(asIntReg(params[i]), (i == (argCount - 1)));
-                break;
-            case Long:
-                masm.param_64_decl(asLongReg(params[i]), (i == (argCount - 1)));
-                break;
-            case Float:
-                masm.param_32_decl(asFloatReg(params[i]), (i == (argCount - 1)));
-                break;
-            case Double:
-                masm.param_64_decl(asDoubleReg(params[i]), (i == (argCount - 1)));
-                break;
-            case Object:
-                masm.param_64_decl(asObjectReg(params[i]), (i == (argCount - 1)));
-                break;
-            default :
-                throw GraalInternalError.shouldNotReachHere("unhandled parameter type "  + paramKind.toString());
-            }
+            new Param((Variable) params[i], (i == (argCount - 1))).emit(masm);
         }
     }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Sep 24 15:35:59 2013 +0200
@@ -247,8 +247,12 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            emitCodeHelper(tasm, masm);
+        }
+
+        public static void emitCodeHelper(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
             new Ret().emit(masm);
-            // On SPARC we always leave the frame.
+            // On SPARC we always leave the frame (in the delay slot).
             tasm.frameContext.leave(tasm);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -44,4 +44,9 @@
     public FixedWithNextNode(Stamp stamp) {
         super(stamp);
     }
+
+    @Override
+    public FixedWithNextNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -82,7 +82,7 @@
         }
         GuardingNode guard = tool.createGuard(condition, reason, action, negated);
         ValueAnchorNode anchor = graph().add(new ValueAnchorNode((ValueNode) guard));
-        PiNode pi = graph().unique(new PiNode(object, stamp(), guard));
+        PiNode pi = graph().unique(new PiNode(object, stamp(), (ValueNode) guard));
         replaceAtUsages(pi);
         graph().replaceFixedWithFixed(this, anchor);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryState.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+
+public class MemoryState extends VirtualState {
+
+    private MemoryMap<Node> memoryMap;
+    @Input private Node object;
+
+    public MemoryState(MemoryMap<Node> memoryMap, FixedNode object) {
+        this.memoryMap = memoryMap;
+        this.object = object;
+    }
+
+    public Node object() {
+        return object;
+    }
+
+    public MemoryMap<Node> getMemoryMap() {
+        return memoryMap;
+    }
+
+    @Override
+    public VirtualState duplicateWithVirtualState() {
+        throw new GraalInternalError("should not reach here");
+    }
+
+    @Override
+    public void applyToNonVirtual(NodeClosure<? super ValueNode> closure) {
+        throw new GraalInternalError("should not reach here");
+    }
+
+    @Override
+    public void applyToVirtual(VirtualClosure closure) {
+        throw new GraalInternalError("should not reach here");
+    }
+
+    @Override
+    public boolean isPartOfThisState(VirtualState state) {
+        throw new GraalInternalError("should not reach here");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * The {@code UnsafeCastNode} produces the same value as its input, but with a different type.
+ */
+public final class PiArrayNode extends PiNode implements ArrayLengthProvider {
+
+    @Input private ValueNode length;
+
+    public ValueNode length() {
+        return length;
+    }
+
+    public PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) {
+        super(object, stamp);
+        this.length = length;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (!(object() instanceof ArrayLengthProvider) || length() != ((ArrayLengthProvider) object()).length()) {
+            return this;
+        }
+        return super.canonical(tool);
+    }
+
+    @NodeIntrinsic
+    public static native <T> T piArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -49,13 +49,21 @@
         this.object = object;
     }
 
-    public PiNode(ValueNode object, Stamp stamp, GuardingNode anchor) {
-        super(stamp, anchor);
+    public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) {
+        super(stamp, (GuardingNode) anchor);
         this.object = object;
     }
 
+    public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
+        this(object, StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp())));
+    }
+
     @Override
     public void generate(LIRGeneratorTool generator) {
+        assert kind() == Kind.Object && object.kind() == Kind.Object;
+        assert ObjectStamp.typeOrNull(object) == null || ObjectStamp.typeOrNull(this).isInterface() || ObjectStamp.typeOrNull(object).isInterface() ||
+                        ObjectStamp.typeOrNull(object).isAssignableFrom(ObjectStamp.typeOrNull(this));
+
         if (object.kind() != Kind.Void && object.kind() != Kind.Illegal) {
             generator.setResult(this, generator.operand(object));
         }
@@ -63,6 +71,9 @@
 
     @Override
     public boolean inferStamp() {
+        if (stamp() == StampFactory.forNodeIntrinsic()) {
+            return false;
+        }
         return updateStamp(stamp().join(object().stamp()));
     }
 
@@ -70,14 +81,7 @@
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
         if (state != null && state.getState() == EscapeState.Virtual) {
-            ResolvedJavaType virtualObjectType = state.getVirtualObject().type();
-            if (this.kind() == Kind.Object) {
-                ObjectStamp myStamp = ((ObjectStamp) this.stamp());
-                ResolvedJavaType myType = myStamp.type();
-                if (!myType.isAssignableFrom(virtualObjectType)) {
-                    return;
-                }
-            }
+            assert ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type());
             tool.replaceWithVirtual(state.getVirtualObject());
         }
     }
@@ -95,4 +99,16 @@
     public ValueNode getOriginalValue() {
         return object;
     }
+
+    @NodeIntrinsic
+    public static native <T> T piCast(Object object, @ConstantNodeParameter Stamp stamp);
+
+    @NodeIntrinsic
+    public static native <T> T piCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor);
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static <T> T piCast(Object object, @ConstantNodeParameter Class<T> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull) {
+        return toType.cast(object);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -32,11 +32,7 @@
 public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
 
     public SafepointNode() {
-        this(StampFactory.forVoid());
-    }
-
-    public SafepointNode(Stamp stamp) {
-        super(stamp);
+        super(StampFactory.forVoid());
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -31,4 +31,9 @@
     public FloatingNode(Stamp stamp) {
         super(stamp);
     }
+
+    @Override
+    public FloatingNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -53,6 +53,11 @@
         return lastLocationAccess;
     }
 
+    public void setLastLocationAccess(Node newlla) {
+        updateUsages(lastLocationAccess, newlla);
+        lastLocationAccess = newlla;
+    }
+
     @Override
     public void generate(LIRGeneratorTool gen) {
         Value address = location().generateAddress(gen, gen.operand(object()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * The {@code UnsafeCastNode} produces the same value as its input, but with a different type.
- */
-public final class UnsafeArrayCastNode extends UnsafeCastNode implements ArrayLengthProvider {
-
-    @Input private ValueNode length;
-
-    public ValueNode length() {
-        return length;
-    }
-
-    public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp) {
-        super(object, stamp);
-        this.length = length;
-    }
-
-    public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, GuardingNode anchor) {
-        super(object, stamp, anchor);
-        this.length = length;
-    }
-
-    private UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, ValueNode anchor) {
-        this(object, length, stamp, (GuardingNode) anchor);
-    }
-
-    @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
-        if (!(object() instanceof ArrayLengthProvider) || length() != ((ArrayLengthProvider) object()).length()) {
-            return this;
-        }
-        return super.canonical(tool);
-    }
-
-    @NodeIntrinsic
-    public static native <T> T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp);
-
-    @NodeIntrinsic
-    public static native <T> T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -23,25 +23,29 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
- * The {@code UnsafeCastNode} produces the same value as its input, but with a different type.
+ * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. It
+ * allows unsafe casts "sideways" in the type hierarchy. It does not allow to "drop" type
+ * information, i.e., an unsafe cast is removed if the input object has a more precise or equal type
+ * than the type this nodes casts to.
  */
-public class UnsafeCastNode extends PiNode implements Canonicalizable, LIRLowerable {
+public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy {
+
+    @Input private ValueNode object;
 
     public UnsafeCastNode(ValueNode object, Stamp stamp) {
-        super(object, stamp);
-    }
-
-    public UnsafeCastNode(ValueNode object, Stamp stamp, GuardingNode anchor) {
-        super(object, stamp, anchor);
+        super(stamp);
+        this.object = object;
     }
 
     public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) {
-        this(object, stamp, (GuardingNode) anchor);
+        super(stamp, (GuardingNode) anchor);
+        this.object = object;
     }
 
     public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
@@ -49,66 +53,44 @@
     }
 
     @Override
-    public boolean inferStamp() {
-        if (stamp() == StampFactory.forNodeIntrinsic()) {
-            return false;
-        }
-        if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) {
-            return updateStamp(((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp()));
-        }
-        return false;
+    public ValueNode getOriginalValue() {
+        return object;
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (kind() != object().kind()) {
+        assert kind() == Kind.Object && object.kind() == Kind.Object;
+
+        ObjectStamp my = (ObjectStamp) stamp();
+        ObjectStamp other = (ObjectStamp) object.stamp();
+
+        if (my.type() == null || other.type() == null) {
+            return this;
+        }
+        if (my.isExactType() && !other.isExactType()) {
             return this;
         }
-
-        if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) {
-            ObjectStamp my = (ObjectStamp) stamp();
-            ObjectStamp other = (ObjectStamp) object().stamp();
-
-            if (my.type() == null || other.type() == null) {
-                return this;
-            }
-            if (my.isExactType() && !other.isExactType()) {
-                return this;
-            }
-            if (my.nonNull() && !other.nonNull()) {
-                return this;
-            }
-            if (!my.type().isAssignableFrom(other.type())) {
-                return this;
-            }
+        if (my.nonNull() && !other.nonNull()) {
+            return this;
+        }
+        if (!my.type().isAssignableFrom(other.type())) {
+            return this;
         }
-        return object();
+        /*
+         * The unsafe cast does not add any new type information, so it can be removed. Note that
+         * this means that the unsafe cast cannot be used to "drop" type information (in which case
+         * it must not be canonicalized in any case).
+         */
+        return object;
     }
 
     @Override
     public void generate(LIRGeneratorTool generator) {
-        if (kind() != object().kind()) {
-            assert generator.target().arch.getSizeInBytes(kind()) == generator.target().arch.getSizeInBytes(object().kind()) : "unsafe cast cannot be used to change the size of a value";
-            AllocatableValue result = generator.newVariable(kind());
-            generator.emitMove(result, generator.operand(object()));
-            generator.setResult(this, result);
-        } else {
-            // The LIR only cares about the kind of an operand, not the actual type of an object. So
-            // we do not have to
-            // introduce a new operand when the kind is the same.
-            generator.setResult(this, generator.operand(object()));
-        }
-    }
-
-    @NodeIntrinsic
-    public static native <T> T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp);
-
-    @NodeIntrinsic
-    public static native <T> T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor);
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static <T> T unsafeCast(Object object, @ConstantNodeParameter Class<T> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull) {
-        return toType.cast(object);
+        assert kind() == Kind.Object && object.kind() == Kind.Object;
+        /*
+         * The LIR only cares about the kind of an operand, not the actual type of an object. So we
+         * do not have to introduce a new operand.
+         */
+        generator.setResult(this, generator.operand(object));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Tue Sep 24 15:35:59 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.type;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -133,10 +135,12 @@
             str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
         }
         if (downMask != 0) {
-            str.append(" \u21ca").append(Long.toHexString(downMask));
+            str.append(" \u21ca");
+            new Formatter(str).format("%016x", downMask);
         }
         if (upMask != defaultMask(kind())) {
-            str.append(" \u21c8").append(Long.toHexString(upMask));
+            str.append(" \u21c8");
+            new Formatter(str).format("%016x", upMask);
         }
         return str.toString();
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Sep 24 15:35:59 2013 +0200
@@ -511,9 +511,9 @@
                     PiNode piNode;
                     if (isNull) {
                         ConstantNode nullObject = ConstantNode.forObject(null, metaAccessProvider, graph);
-                        piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), replacementAnchor));
+                        piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), replacementAnchor.asNode()));
                     } else {
-                        piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor));
+                        piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode()));
                     }
                     checkCast.replaceAtUsages(piNode);
                     if (anchor != null) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Sep 24 15:35:59 2013 +0200
@@ -27,6 +27,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.extended.*;
@@ -37,24 +38,25 @@
 
 public class FloatingReadPhase extends Phase {
 
-    private static class MemoryMap {
+    public static class MemoryMapImpl implements MemoryMap<Node> {
 
         private IdentityHashMap<LocationIdentity, ValueNode> lastMemorySnapshot;
 
-        public MemoryMap(MemoryMap memoryMap) {
+        public MemoryMapImpl(MemoryMapImpl memoryMap) {
             lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot);
         }
 
-        public MemoryMap(StartNode start) {
+        public MemoryMapImpl(StartNode start) {
             this();
             lastMemorySnapshot.put(ANY_LOCATION, start);
         }
 
-        public MemoryMap() {
+        public MemoryMapImpl() {
             lastMemorySnapshot = new IdentityHashMap<>();
         }
 
-        private ValueNode getLastLocationAccess(LocationIdentity locationIdentity) {
+        @Override
+        public ValueNode getLastLocationAccess(LocationIdentity locationIdentity) {
             ValueNode lastLocationAccess;
             if (locationIdentity == FINAL_LOCATION) {
                 return null;
@@ -74,11 +76,21 @@
         }
     }
 
+    private final boolean makeReadsFloating;
+
+    public FloatingReadPhase() {
+        this(true);
+    }
+
+    public FloatingReadPhase(boolean makeReadsFloating) {
+        this.makeReadsFloating = makeReadsFloating;
+    }
+
     @Override
     protected void run(StructuredGraph graph) {
         Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops = new IdentityHashMap<>();
         ReentrantNodeIterator.apply(new CollectMemoryCheckpointsClosure(modifiedInLoops), graph.start(), new HashSet<LocationIdentity>(), null);
-        ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops), graph.start(), new MemoryMap(graph.start()), null);
+        ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops, makeReadsFloating), graph.start(), new MemoryMapImpl(graph.start()), null);
     }
 
     private static class CollectMemoryCheckpointsClosure extends NodeIteratorClosure<Set<LocationIdentity>> {
@@ -133,17 +145,19 @@
 
     }
 
-    private static class FloatingReadClosure extends NodeIteratorClosure<MemoryMap> {
+    private static class FloatingReadClosure extends NodeIteratorClosure<MemoryMapImpl> {
 
         private final Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops;
+        private final boolean makeReadsFloating;
 
-        public FloatingReadClosure(Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops) {
+        public FloatingReadClosure(Map<LoopBeginNode, Set<LocationIdentity>> modifiedInLoops, boolean makeFloating) {
             this.modifiedInLoops = modifiedInLoops;
+            this.makeReadsFloating = makeFloating;
         }
 
         @Override
-        protected MemoryMap processNode(FixedNode node, MemoryMap state) {
-            if (node instanceof FloatableAccessNode) {
+        protected MemoryMapImpl processNode(FixedNode node, MemoryMapImpl state) {
+            if (node instanceof FloatableAccessNode && makeReadsFloating) {
                 processFloatable((FloatableAccessNode) node, state);
             } else if (node instanceof MemoryCheckpoint.Single) {
                 processCheckpoint((MemoryCheckpoint.Single) node, state);
@@ -151,27 +165,31 @@
                 processCheckpoint((MemoryCheckpoint.Multi) node, state);
             }
             assert MemoryCheckpoint.TypeAssertion.correctType(node) : node;
+
+            if (!makeReadsFloating && node instanceof ReturnNode) {
+                node.graph().add(new MemoryState(new MemoryMapImpl(state), node));
+            }
             return state;
         }
 
-        private static void processCheckpoint(MemoryCheckpoint.Single checkpoint, MemoryMap state) {
-            LocationIdentity identity = checkpoint.getLocationIdentity();
+        private static void processCheckpoint(MemoryCheckpoint.Single checkpoint, MemoryMapImpl state) {
+            processIdentity(checkpoint.getLocationIdentity(), checkpoint, state);
+        }
+
+        private static void processCheckpoint(MemoryCheckpoint.Multi checkpoint, MemoryMapImpl state) {
+            for (LocationIdentity identity : checkpoint.getLocationIdentities()) {
+                processIdentity(identity, checkpoint, state);
+            }
+        }
+
+        private static void processIdentity(LocationIdentity identity, MemoryCheckpoint checkpoint, MemoryMapImpl state) {
             if (identity == ANY_LOCATION) {
                 state.lastMemorySnapshot.clear();
             }
             state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint);
         }
 
-        private static void processCheckpoint(MemoryCheckpoint.Multi checkpoint, MemoryMap state) {
-            for (LocationIdentity identity : checkpoint.getLocationIdentities()) {
-                if (identity == ANY_LOCATION) {
-                    state.lastMemorySnapshot.clear();
-                }
-                state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint);
-            }
-        }
-
-        private static void processFloatable(FloatableAccessNode accessNode, MemoryMap state) {
+        private static void processFloatable(FloatableAccessNode accessNode, MemoryMapImpl state) {
             StructuredGraph graph = accessNode.graph();
             assert accessNode.getNullCheck() == false;
             LocationIdentity locationIdentity = accessNode.location().getLocationIdentity();
@@ -190,11 +208,11 @@
         }
 
         @Override
-        protected MemoryMap merge(MergeNode merge, List<MemoryMap> states) {
-            MemoryMap newState = new MemoryMap();
+        protected MemoryMapImpl merge(MergeNode merge, List<MemoryMapImpl> states) {
+            MemoryMapImpl newState = new MemoryMapImpl();
 
             Set<LocationIdentity> keys = new HashSet<>();
-            for (MemoryMap other : states) {
+            for (MemoryMapImpl other : states) {
                 keys.addAll(other.lastMemorySnapshot.keySet());
             }
             assert !keys.contains(FINAL_LOCATION);
@@ -203,7 +221,7 @@
                 int mergedStatesCount = 0;
                 boolean isPhi = false;
                 ValueNode merged = null;
-                for (MemoryMap state : states) {
+                for (MemoryMapImpl state : states) {
                     ValueNode last = state.getLastLocationAccess(key);
                     if (isPhi) {
                         ((PhiNode) merged).addInput(last);
@@ -230,8 +248,8 @@
         }
 
         @Override
-        protected MemoryMap afterSplit(AbstractBeginNode node, MemoryMap oldState) {
-            MemoryMap result = new MemoryMap(oldState);
+        protected MemoryMapImpl afterSplit(AbstractBeginNode node, MemoryMapImpl oldState) {
+            MemoryMapImpl result = new MemoryMapImpl(oldState);
             if (node.predecessor() instanceof InvokeWithExceptionNode) {
                 /*
                  * InvokeWithException cannot be the lastLocationAccess for a FloatingReadNode.
@@ -247,7 +265,7 @@
         }
 
         @Override
-        protected Map<LoopExitNode, MemoryMap> processLoop(LoopBeginNode loop, MemoryMap initialState) {
+        protected Map<LoopExitNode, MemoryMapImpl> processLoop(LoopBeginNode loop, MemoryMapImpl initialState) {
             Set<LocationIdentity> modifiedLocations = modifiedInLoops.get(loop);
             if (modifiedLocations.contains(ANY_LOCATION)) {
                 // create phis for all locations if ANY is modified in the loop
@@ -263,9 +281,9 @@
                 initialState.lastMemorySnapshot.put(location, phi);
             }
 
-            LoopInfo<MemoryMap> loopInfo = ReentrantNodeIterator.processLoop(this, loop, initialState);
+            LoopInfo<MemoryMapImpl> loopInfo = ReentrantNodeIterator.processLoop(this, loop, initialState);
 
-            for (Map.Entry<LoopEndNode, MemoryMap> entry : loopInfo.endStates.entrySet()) {
+            for (Map.Entry<LoopEndNode, MemoryMapImpl> entry : loopInfo.endStates.entrySet()) {
                 int endIndex = loop.phiPredecessorIndex(entry.getKey());
                 for (Map.Entry<LocationIdentity, PhiNode> phiEntry : phis.entrySet()) {
                     LocationIdentity key = phiEntry.getKey();
@@ -273,9 +291,9 @@
                     phi.initializeValueAt(endIndex, entry.getValue().getLastLocationAccess(key));
                 }
             }
-            for (Map.Entry<LoopExitNode, MemoryMap> entry : loopInfo.exitStates.entrySet()) {
+            for (Map.Entry<LoopExitNode, MemoryMapImpl> entry : loopInfo.exitStates.entrySet()) {
                 LoopExitNode exit = entry.getKey();
-                MemoryMap state = entry.getValue();
+                MemoryMapImpl state = entry.getValue();
                 for (LocationIdentity location : modifiedLocations) {
                     ValueNode lastAccessAtExit = state.lastMemorySnapshot.get(location);
                     if (lastAccessAtExit != null) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Tue Sep 24 15:35:59 2013 +0200
@@ -637,10 +637,15 @@
             }
         }
 
+        private static final Object[] NO_CONTEXT = {};
+
         /**
-         * Gets the call hierarchy of this inling from outer most call to inner most callee.
+         * Gets the call hierarchy of this inlining from outer most call to inner most callee.
          */
         public Object[] inliningContext() {
+            if (!Debug.isDumpEnabled()) {
+                return NO_CONTEXT;
+            }
             Object[] result = new Object[graphQueue.size()];
             int i = 0;
             for (GraphInfo g : graphQueue) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, 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.phases.common;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Adds safepoints to loops.
+ */
+public class LoopSafepointInsertionPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        if (GenLoopSafepoints.getValue()) {
+            for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) {
+                if (loopEndNode.canSafepoint()) {
+                    SafepointNode safepointNode = graph.add(new SafepointNode());
+                    graph.addBeforeFixed(loopEndNode, safepointNode);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java	Fri Sep 20 11:25:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2011, 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.phases.common;
-
-import static com.oracle.graal.phases.GraalOptions.*;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-
-/**
- * Adds safepoints to loops and return points.
- */
-public class SafepointInsertionPhase extends Phase {
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        final boolean addLoopSafepoints = GenLoopSafepoints.getValue();
-        if (addLoopSafepoints && !GenSafepoints.getValue()) {
-            // Use (faster) typed node iteration if we are not adding return safepoints
-            for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) {
-                addLoopSafepoint(graph, loopEndNode);
-            }
-        }
-
-        if (GenSafepoints.getValue()) {
-            List<ReturnNode> returnNodes = new ArrayList<>();
-            boolean addReturnSafepoints = !OptEliminateSafepoints.getValue();
-            for (Node n : graph.getNodes()) {
-                if (addLoopSafepoints && n instanceof LoopEndNode) {
-                    addLoopSafepoint(graph, (LoopEndNode) n);
-                } else if (n instanceof ReturnNode) {
-                    returnNodes.add((ReturnNode) n);
-                } else {
-                    if (!addReturnSafepoints && n instanceof LoweredCallTargetNode) {
-                        addReturnSafepoints = true;
-                    }
-                }
-            }
-            if (addReturnSafepoints) {
-                for (ReturnNode returnNode : returnNodes) {
-                    SafepointNode safepoint = graph.add(new SafepointNode());
-                    graph.addBeforeFixed(returnNode, safepoint);
-                }
-            }
-        }
-    }
-
-    private static void addLoopSafepoint(StructuredGraph graph, LoopEndNode loopEndNode) {
-        if (loopEndNode.canSafepoint()) {
-            SafepointNode safepointNode = graph.add(new SafepointNode());
-            graph.addBeforeFixed(loopEndNode, safepointNode);
-        }
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Tue Sep 24 15:35:59 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.*;
 import com.oracle.graal.word.*;
+import com.oracle.graal.word.nodes.*;
 
 /**
  * Tests for the {@link Pointer} read and write operations.
@@ -103,11 +104,13 @@
     }
 
     private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
-        ReadNode read = (ReadNode) graph.start().next();
+        WordCastNode cast = (WordCastNode) graph.start().next();
+
+        ReadNode read = (ReadNode) cast.next();
         Assert.assertEquals(kind.getStackKind(), read.kind());
 
-        UnsafeCastNode cast = (UnsafeCastNode) read.object();
-        Assert.assertEquals(graph.getLocal(0), cast.object());
+        Assert.assertEquals(cast, read.object());
+        Assert.assertEquals(graph.getLocal(0), cast.getInput());
         Assert.assertEquals(target.wordKind, cast.kind());
 
         IndexedLocationNode location = (IndexedLocationNode) read.location();
@@ -128,13 +131,15 @@
     }
 
     private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
-        WriteNode write = (WriteNode) graph.start().next();
+        WordCastNode cast = (WordCastNode) graph.start().next();
+
+        WriteNode write = (WriteNode) cast.next();
         Assert.assertEquals(graph.getLocal(2), write.value());
         Assert.assertEquals(Kind.Void, write.kind());
         Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci);
 
-        UnsafeCastNode cast = (UnsafeCastNode) write.object();
-        Assert.assertEquals(graph.getLocal(0), cast.object());
+        Assert.assertEquals(cast, write.object());
+        Assert.assertEquals(graph.getLocal(0), cast.getInput());
         Assert.assertEquals(target.wordKind, cast.kind());
 
         IndexedLocationNode location = (IndexedLocationNode) write.location();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Tue Sep 24 15:35:59 2013 +0200
@@ -79,49 +79,49 @@
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
     public static Boolean booleanValueOf(boolean value) {
         valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic());
+        return PiNode.piCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
     public static Byte byteValueOf(byte value) {
         valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic());
+        return PiNode.piCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
     public static Character charValueOf(char value) {
         valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic());
+        return PiNode.piCast(Character.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
     public static Double doubleValueOf(double value) {
         valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic());
+        return PiNode.piCast(Double.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
     public static Float floatValueOf(float value) {
         valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic());
+        return PiNode.piCast(Float.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
     public static Integer intValueOf(int value) {
         valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic());
+        return PiNode.piCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
     public static Long longValueOf(long value) {
         valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic());
+        return PiNode.piCast(Long.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
     public static Short shortValueOf(short value) {
         valueOfCounter.inc();
-        return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic());
+        return PiNode.piCast(Short.valueOf(value), StampFactory.forNodeIntrinsic());
     }
 
     @Snippet(inlining = BoxingSnippetInliningPolicy.class)
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue Sep 24 15:35:59 2013 +0200
@@ -206,7 +206,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap<Node> mmap) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
@@ -238,7 +238,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap<Node> mmap) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java	Tue Sep 24 15:35:59 2013 +0200
@@ -36,8 +36,8 @@
  * Substitutions for improving the performance of some critical methods in {@link NodeClass}
  * methods. These substitutions improve the performance by forcing the relevant methods to be
  * inlined (intrinsification being a special form of inlining) and removing a checked cast. The
- * latter cannot be done directly in Java code as {@link UnsafeCastNode} is not available to the
- * project containing {@link NodeClass}.
+ * latter cannot be done directly in Java code as {@link PiNode} is not available to the project
+ * containing {@link NodeClass}.
  */
 @ClassSubstitution(NodeClass.class)
 public class NodeClassSubstitutions {
@@ -64,12 +64,12 @@
 
     @MethodSubstitution
     private static Node getNode(Node node, long offset) {
-        return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false);
+        return PiNode.piCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false);
     }
 
     @MethodSubstitution
     private static NodeList getNodeList(Node node, long offset) {
-        return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false);
+        return PiNode.piCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false);
     }
 
     @MethodSubstitution
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Sep 24 15:35:59 2013 +0200
@@ -34,7 +34,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.StructuredGraph.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -532,13 +532,16 @@
         }
 
         new DeadCodeEliminationPhase().apply(snippetCopy);
+        new CanonicalizerPhase(true).apply(snippetCopy, context);
 
         assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders);
 
+        new FloatingReadPhase(false).apply(snippetCopy);
+        this.memoryMap = null;
+
         this.snippet = snippetCopy;
         ReturnNode retNode = null;
         StartNode entryPointNode = snippet.start();
-
         nodes = new ArrayList<>(snippet.getNodeCount());
         for (Node node : snippet.getNodes()) {
             if (node == entryPointNode || node == entryPointNode.stateAfter()) {
@@ -547,9 +550,15 @@
                 nodes.add(node);
                 if (node instanceof ReturnNode) {
                     retNode = (ReturnNode) node;
+                    for (MemoryState memstate : retNode.usages().filter(MemoryState.class).snapshot()) {
+                        this.memoryMap = memstate.getMemoryMap();
+                        memstate.safeDelete();
+                    }
+                    assert snippet.getNodes().filter(ReturnNode.class).count() == 1;
                 }
             }
         }
+        assert !containsMemoryState(snippet);
 
         this.sideEffectNodes = curSideEffectNodes;
         this.deoptNodes = curDeoptNodes;
@@ -560,6 +569,10 @@
         this.instantiationTimer = Debug.timer("SnippetInstantiationTime[" + method.getName() + "]");
     }
 
+    private static boolean containsMemoryState(StructuredGraph snippet) {
+        return snippet.getNodes().filter(MemoryState.class).count() > 0;
+    }
+
     private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, ConstantNode[] placeholders) {
         for (int i = 0; i < parameterCount; i++) {
             if (placeholders[i] != null) {
@@ -633,6 +646,11 @@
     private final ArrayList<Node> nodes;
 
     /**
+     * mapping of killing locations to memory checkpoints (nodes).
+     */
+    private MemoryMap<Node> memoryMap;
+
+    /**
      * Gets the instantiation-time bindings to this template's parameters.
      * 
      * @return the map that will be used to bind arguments to parameters when inlining this template
@@ -724,7 +742,7 @@
         /**
          * Replaces all usages of {@code oldNode} with direct or indirect usages of {@code newNode}.
          */
-        void replace(ValueNode oldNode, ValueNode newNode);
+        void replace(ValueNode oldNode, ValueNode newNode, MemoryMap<Node> mmap);
     }
 
     /**
@@ -734,11 +752,51 @@
     public static final UsageReplacer DEFAULT_REPLACER = new UsageReplacer() {
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap<Node> mmap) {
             oldNode.replaceAtUsages(newNode);
+            if (mmap == null || newNode == null) {
+                return;
+            }
+            for (Node usage : newNode.usages().snapshot()) {
+                if (usage instanceof FloatingReadNode && ((FloatingReadNode) usage).lastLocationAccess() == newNode) {
+                    // TODO: add graph state for FloatingReadPhase
+                    assert newNode.graph().getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal();
+
+                    // lastLocationAccess points into the snippet graph. find a proper
+                    // MemoryCheckPoint inside the snippet graph
+                    FloatingReadNode frn = (FloatingReadNode) usage;
+                    Node newlla = mmap.getLastLocationAccess(frn.location().getLocationIdentity());
+
+                    assert newlla != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)";
+                    frn.setLastLocationAccess(newlla);
+                }
+            }
         }
     };
 
+    private class DuplicateMapper implements MemoryMap<Node> {
+
+        Map<Node, Node> duplicates;
+        StartNode replaceeStart;
+
+        public DuplicateMapper(Map<Node, Node> duplicates, StartNode replaceeStart) {
+            this.duplicates = duplicates;
+            this.replaceeStart = replaceeStart;
+        }
+
+        @Override
+        public Node getLastLocationAccess(LocationIdentity locationIdentity) {
+            assert memoryMap != null : "no memory map stored for this snippet graph (snippet doesn't have a ReturnNode?)";
+            Node lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity);
+            assert lastLocationAccess != null;
+            if (lastLocationAccess instanceof StartNode) {
+                return replaceeStart;
+            } else {
+                return duplicates.get(lastLocationAccess);
+            }
+        }
+    }
+
     /**
      * Replaces a given fixed node with this specialized snippet.
      * 
@@ -756,6 +814,7 @@
             FixedNode firstCFGNode = entryPointNode.next();
             StructuredGraph replaceeGraph = replacee.graph();
             IdentityHashMap<Node, Node> replacements = bind(replaceeGraph, runtime, args);
+            replacements.put(entryPointNode, replaceeGraph.start());
             Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements);
             Debug.dump(replaceeGraph, "After inlining snippet %s", snippet.method());
 
@@ -801,12 +860,12 @@
                     returnValue = (ValueNode) duplicates.get(returnNode.result());
                 }
                 Node returnDuplicate = duplicates.get(returnNode);
+                MemoryMap<Node> mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
                 if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
-                    replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor());
+                    replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap);
                 } else {
                     assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages();
-                    replacer.replace(replacee, returnValue);
-
+                    replacer.replace(replacee, returnValue, mmap);
                 }
                 if (returnDuplicate.isAlive()) {
                     returnDuplicate.clearInputs();
@@ -850,6 +909,7 @@
             FixedNode firstCFGNode = entryPointNode.next();
             StructuredGraph replaceeGraph = replacee.graph();
             IdentityHashMap<Node, Node> replacements = bind(replaceeGraph, runtime, args);
+            replacements.put(entryPointNode, replaceeGraph.start());
             Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements);
             Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method());
 
@@ -881,7 +941,7 @@
                 returnValue = (ValueNode) duplicates.get(returnNode.result());
             }
             assert returnValue != null || replacee.usages().isEmpty();
-            replacer.replace(replacee, returnValue);
+            replacer.replace(replacee, returnValue, new DuplicateMapper(duplicates, replaceeGraph.start()));
 
             Node returnDuplicate = duplicates.get(returnNode);
             if (returnDuplicate.isAlive()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -25,6 +25,7 @@
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -64,33 +65,51 @@
     }
 
     /**
-     * Gets a snippet to be used for lowering this macro node. The returned graph (if non-null) is
-     * not shared and can be modified by the caller.
+     * Gets a snippet to be used for lowering this macro node. The returned graph (if non-null) must
+     * have been {@linkplain #lowerReplacement(StructuredGraph, LoweringTool) lowered}.
      */
     @SuppressWarnings("unused")
-    protected StructuredGraph getSnippetGraph(LoweringTool tool) {
+    protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
         return null;
     }
 
     /**
      * Gets a normal method substitution to be used for lowering this macro node. This is only
-     * called if {@link #getSnippetGraph(LoweringTool)} returns null. The returned graph (if
-     * non-null) is not shared and can be modified by the caller.
+     * called if {@link #getLoweredSnippetGraph(LoweringTool)} returns null. The returned graph (if
+     * non-null) must have been {@linkplain #lowerReplacement(StructuredGraph, LoweringTool)
+     * lowered}.
      */
-    protected StructuredGraph getSubstitutionGraph(LoweringTool tool) {
+    protected StructuredGraph getLoweredSubstitutionGraph(LoweringTool tool) {
         StructuredGraph methodSubstitution = tool.getReplacements().getMethodSubstitution(getTargetMethod());
         if (methodSubstitution != null) {
-            methodSubstitution = methodSubstitution.copy();
+            return lowerReplacement(methodSubstitution.copy(), tool);
         }
-        return methodSubstitution;
+        return null;
+    }
+
+    /**
+     * Applies {@linkplain LoweringPhase lowering} to a replacement graph.
+     * 
+     * @param replacementGraph a replacement (i.e., snippet or method substitution) graph
+     */
+    protected StructuredGraph lowerReplacement(final StructuredGraph replacementGraph, LoweringTool tool) {
+        replacementGraph.setGuardsStage(graph().getGuardsStage());
+        final PhaseContext c = new PhaseContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements());
+        Debug.scope("LoweringReplacement", replacementGraph, new Runnable() {
+
+            public void run() {
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(replacementGraph, c);
+            }
+        });
+        return replacementGraph;
     }
 
     @Override
     public void lower(LoweringTool tool) {
         boolean nullCheck = false;
-        StructuredGraph replacementGraph = getSnippetGraph(tool);
+        StructuredGraph replacementGraph = getLoweredSnippetGraph(tool);
         if (replacementGraph == null) {
-            replacementGraph = getSubstitutionGraph(tool);
+            replacementGraph = getLoweredSubstitutionGraph(tool);
             nullCheck = true;
         }
 
@@ -98,10 +117,6 @@
         assert invoke.verify();
 
         if (replacementGraph != null) {
-            // Lower the (non-shared) replacement graph
-            replacementGraph.setGuardsStage(graph().getGuardsStage());
-            PhaseContext c = new PhaseContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements());
-            new LoweringPhase(new CanonicalizerPhase(true)).apply(replacementGraph, c);
             InliningUtil.inline(invoke, replacementGraph, nullCheck);
         }
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -62,8 +62,8 @@
     public void lower(LoweringTool tool) {
         if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) {
             ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode(null));
-            UnsafeCastNode unsafeCast = graph().unique(new UnsafeCastNode(object, this.stamp(), (GuardingNode) valueAnchorNode));
-            this.replaceAtUsages(unsafeCast);
+            PiNode piCast = graph().unique(new PiNode(object, this.stamp(), valueAnchorNode));
+            this.replaceAtUsages(piCast);
             graph().replaceFixedWithFixed(this, valueAnchorNode);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Tue Sep 24 15:35:59 2013 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 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.word.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.word.phases.*;
+
+/**
+ * Cast between Word and Object that is introduced by the {@link WordTypeRewriterPhase}. It has an
+ * impact on the pointer maps for the GC, so it must not be scheduled or optimized away.
+ */
+public final class WordCastNode extends FixedWithNextNode implements LIRLowerable {
+
+    public static WordCastNode wordToObject(ValueNode input, Kind wordKind) {
+        assert input.kind() == wordKind;
+        return new WordCastNode(StampFactory.object(), input);
+    }
+
+    public static WordCastNode objectToWord(ValueNode input, Kind wordKind) {
+        assert input.kind() == Kind.Object;
+        return new WordCastNode(StampFactory.forKind(wordKind), input);
+    }
+
+    @Input private ValueNode input;
+
+    private WordCastNode(Stamp stamp, ValueNode input) {
+        super(stamp);
+        this.input = input;
+    }
+
+    public ValueNode getInput() {
+        return input;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        assert kind() != input.kind();
+        assert generator.target().arch.getSizeInBytes(kind()) == generator.target().arch.getSizeInBytes(input.kind());
+
+        AllocatableValue result = generator.newVariable(kind());
+        generator.emitMove(result, generator.operand(input));
+        generator.setResult(this, result);
+    }
+}
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Tue Sep 24 15:35:59 2013 +0200
@@ -39,6 +39,7 @@
 import com.oracle.graal.word.*;
 import com.oracle.graal.word.Word.Opcode;
 import com.oracle.graal.word.Word.Operation;
+import com.oracle.graal.word.nodes.*;
 
 /**
  * Transforms all uses of the {@link Word} class into unsigned operations on {@code int} or
@@ -129,8 +130,6 @@
     protected void rewriteNode(StructuredGraph graph, Node node) {
         if (node instanceof CheckCastNode) {
             rewriteCheckCast(graph, (CheckCastNode) node);
-        } else if (node instanceof UnsafeCastNode) {
-            rewriteUnsafeCast(graph, (UnsafeCastNode) node);
         } else if (node instanceof LoadFieldNode) {
             rewriteLoadField(graph, (LoadFieldNode) node);
         } else if (node instanceof AccessIndexedNode) {
@@ -151,16 +150,6 @@
     }
 
     /**
-     * Remove unnecessary/redundant unsafe casts.
-     */
-    protected void rewriteUnsafeCast(StructuredGraph graph, UnsafeCastNode node) {
-        if (node.object().stamp() == node.stamp()) {
-            node.replaceAtUsages(node.object());
-            graph.removeFloating(node);
-        }
-    }
-
-    /**
      * Fold constant field reads, e.g. enum constants.
      */
     protected void rewriteLoadField(StructuredGraph graph, LoadFieldNode node) {
@@ -295,7 +284,9 @@
 
             case FROM_OBJECT:
                 assert arguments.size() == 1;
-                replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), StampFactory.forKind(wordKind))));
+                WordCastNode objectToWord = graph.add(WordCastNode.objectToWord(arguments.get(0), wordKind));
+                graph.addBeforeFixed(invoke.asNode(), objectToWord);
+                replace(invoke, objectToWord);
                 break;
 
             case FROM_ARRAY:
@@ -305,7 +296,9 @@
 
             case TO_OBJECT:
                 assert arguments.size() == 1;
-                replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.asNode().stamp())));
+                WordCastNode wordToObject = graph.add(WordCastNode.wordToObject(arguments.get(0), wordKind));
+                graph.addBeforeFixed(invoke.asNode(), wordToObject);
+                replace(invoke, wordToObject);
                 break;
 
             default:
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Tue Sep 24 15:35:59 2013 +0200
@@ -56,6 +56,7 @@
     private final TypeMirror compilerDirectives;
     private final TypeMirror compilerAsserts;
     private final DeclaredType slowPath;
+    private final DeclaredType sourceSection;
     private final DeclaredType truffleOptions;
     private final TypeElement expectError;
 
@@ -75,6 +76,7 @@
         nodeInfoAnnotation = getRequired(context, NodeInfo.class);
         nodeInfoKind = getRequired(context, NodeInfo.Kind.class);
         slowPath = getRequired(context, SlowPath.class);
+        sourceSection = getRequired(context, SourceSection.class);
         truffleOptions = getRequired(context, TruffleOptions.class);
         expectError = (TypeElement) getRequired(context, ExpectError.class).asElement();
     }
@@ -158,4 +160,8 @@
     public DeclaredType getSlowPath() {
         return slowPath;
     }
+
+    public DeclaredType getSourceSection() {
+        return sourceSection;
+    }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Sep 24 15:35:59 2013 +0200
@@ -1102,15 +1102,19 @@
 
         private void createConstructors(NodeData node, CodeTypeElement clazz) {
             List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
+            ExecutableElement sourceSectionConstructor = null;
             if (constructors.isEmpty()) {
                 clazz.add(createUserConstructor(clazz, null));
             } else {
                 for (ExecutableElement constructor : constructors) {
                     clazz.add(createUserConstructor(clazz, constructor));
+                    if (NodeParser.isSourceSectionConstructor(context, constructor)) {
+                        sourceSectionConstructor = constructor;
+                    }
                 }
             }
             if (node.needsRewrites(getContext())) {
-                clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType())));
+                clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()), sourceSectionConstructor));
             }
         }
 
@@ -1181,31 +1185,15 @@
             return builder.getRoot();
         }
 
-        private CodeTree createCopyArray(CodeTreeBuilder parent, NodeChildData child, TypeMirror arrayType, CodeBlock<String> accessElement) {
-            CodeTreeBuilder builder = parent.create();
-            NodeData node = getModel().getNode();
-            builder.string("new ").type(arrayType).string(" {");
-            builder.startCommaGroup();
-            for (ActualParameter parameter : getModel().getParameters()) {
-                NodeChildData foundChild = node.findChild(parameter.getSpecification().getName());
-                if (foundChild == child) {
-                    builder.startGroup();
-                    builder.tree(accessElement.create(builder, String.valueOf(parameter.getIndex())));
-                    builder.end();
-                }
-            }
-            builder.end();
-            builder.end().string("}");
-            return builder.getRoot();
-        }
-
-        private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
+        private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) {
             CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
             CodeTreeBuilder builder = method.createBuilder();
             method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
 
             if (superConstructor != null) {
                 builder.startStatement().startSuperCall().string("copy").end().end();
+            } else if (sourceSectionConstructor != null) {
+                builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end();
             }
 
             for (VariableElement var : type.getFields()) {
@@ -1213,18 +1201,11 @@
                 final String varName = var.getSimpleName().toString();
                 final TypeMirror varType = var.asType();
 
-                final String copyAccess = "copy." + varName;
-                CodeTree init = CodeTreeBuilder.singleString(copyAccess);
-                if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
-                    NodeChildData child = getModel().getNode().findChild(varName);
-                    init = createCopyArray(builder, child, varType, new CodeBlock<String>() {
-
-                        public CodeTree create(CodeTreeBuilder parent, String index) {
-                            return CodeTreeBuilder.singleString(copyAccess + "[" + index + "]");
-                        }
-                    });
+                String copyAccess = "copy." + varName;
+                if (Utils.isAssignable(getContext(), varType, getContext().getTruffleTypes().getNodeArray())) {
+                    copyAccess += ".clone()";
                 }
-                init = createAdoptChild(builder, varType, init);
+                CodeTree init = createAdoptChild(builder, varType, CodeTreeBuilder.singleString(copyAccess));
                 builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end();
             }
             if (getModel().getNode().isPolymorphic()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Fri Sep 20 11:25:53 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Sep 24 15:35:59 2013 +0200
@@ -1052,7 +1052,7 @@
 
         boolean parametersFound = false;
         for (ExecutableElement constructor : constructors) {
-            if (!constructor.getParameters().isEmpty()) {
+            if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) {
                 parametersFound = true;
             }
         }
@@ -1077,6 +1077,10 @@
         nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type));
     }
 
+    static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) {
+        return constructor.getParameters().size() == 1 && Utils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection());
+    }
+
     private static boolean verifySpecializationParameters(NodeData nodeData) {
         boolean valid = true;
         int args = -1;
--- a/mx/commands.py	Fri Sep 20 11:25:53 2013 +0200
+++ b/mx/commands.py	Tue Sep 24 15:35:59 2013 +0200
@@ -945,31 +945,103 @@
     allDuration = datetime.timedelta(seconds=time.time() - allStart)
     mx.log('TOTAL TIME:   ' + '[' + str(allDuration) + ']')
 
-def gate(args):
+class Task:
+    def __init__(self, title):
+        self.start = time.time()
+        self.title = title
+        self.end = None
+        self.duration = None
+        mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title)
+    def stop(self):
+        self.end = time.time()
+        self.duration = datetime.timedelta(seconds=self.end - self.start)
+        mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END:   ') + self.title + ' [' + str(self.duration) + ']')
+        return self
+    def abort(self, codeOrMessage):
+        self.end = time.time()
+        self.duration = datetime.timedelta(seconds=self.end - self.start)
+        mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']')
+        mx.abort(codeOrMessage)
+        return self
+
+def _basic_gate_body(args, tasks):
+    t = Task('BuildHotSpotGraal: fastdebug,product')
+    buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product'])
+    tasks.append(t.stop())
+
+    with VM('graal', 'fastdebug'):
+        t = Task('BootstrapWithSystemAssertions:fastdebug')
+        vm(['-esa', '-version'])
+        tasks.append(t.stop())
+
+    with VM('graal', 'product'):
+        t = Task('BootstrapWithGCVerification:product')
+        vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
+        tasks.append(t.stop())
+
+    with VM('graal', 'product'):
+        t = Task('BootstrapWithG1GCVerification:product')
+        vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
+        tasks.append(t.stop())
+
+    with VM('graal', 'product'):
+        t = Task('BootstrapWithRegisterPressure:product')
+        vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version'])
+        tasks.append(t.stop())
+
+    with VM('graal', 'product'):
+        t = Task('BootstrapWithAOTConfiguration:product')
+        vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version'])
+        tasks.append(t.stop())
+
+    with VM('server', 'product'):  # hosted mode
+        t = Task('UnitTests:hosted-product')
+        unittest([])
+        tasks.append(t.stop())
+
+    for vmbuild in ['fastdebug', 'product']:
+        for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild):
+            t = Task(str(test) + ':' + vmbuild)
+            if not test.test('graal'):
+                t.abort(test.name + ' Failed')
+            tasks.append(t.stop())
+
+    if args.jacocout is not None:
+        jacocoreport([args.jacocout])
+
+    global _jacoco
+    _jacoco = 'off'
+
+    t = Task('CleanAndBuildGraalVisualizer')
+    mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build'])
+    tasks.append(t.stop())
+
+    # Prevent Graal modifications from breaking the standard builds
+    if args.buildNonGraal:
+        t = Task('BuildHotSpotVarieties')
+        buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product'])
+        buildvms(['--vms', 'server-nograal', '--builds', 'product'])
+        buildvms(['--vms', 'server-nograal', '--builds', 'optimized'])
+        tasks.append(t.stop())
+
+        for vmbuild in ['product', 'fastdebug']:
+            for theVm in ['client', 'server']:
+                with VM(theVm, vmbuild):
+                    t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
+                    dacapo(['pmd'])
+                    tasks.append(t.stop())
+
+                    t = Task('UnitTests:' + theVm + ':' + vmbuild)
+                    unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api'])
+                    tasks.append(t.stop())
+
+
+def gate(args, gate_body=_basic_gate_body):
     """run the tests used to validate a push
 
     If this command exits with a 0 exit code, then the source code is in
     a state that would be accepted for integration into the main repository."""
 
-    class Task:
-        def __init__(self, title):
-            self.start = time.time()
-            self.title = title
-            self.end = None
-            self.duration = None
-            mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title)
-        def stop(self):
-            self.end = time.time()
-            self.duration = datetime.timedelta(seconds=self.end - self.start)
-            mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END:   ') + self.title + ' [' + str(self.duration) + ']')
-            return self
-        def abort(self, codeOrMessage):
-            self.end = time.time()
-            self.duration = datetime.timedelta(seconds=self.end - self.start)
-            mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']')
-            mx.abort(codeOrMessage)
-            return self
-
     parser = ArgumentParser(prog='mx gate')
     parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code')
     parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code')
@@ -1032,74 +1104,7 @@
         else:
             _jacoco = 'off'
 
-        t = Task('BuildHotSpotGraal: fastdebug,product')
-        buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product'])
-        tasks.append(t.stop())
-
-        with VM('graal', 'fastdebug'):
-            t = Task('BootstrapWithSystemAssertions:fastdebug')
-            vm(['-esa', '-version'])
-            tasks.append(t.stop())
-
-        with VM('graal', 'product'):
-            t = Task('BootstrapWithGCVerification:product')
-            vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
-            tasks.append(t.stop())
-
-        with VM('graal', 'product'):
-            t = Task('BootstrapWithG1GCVerification:product')
-            vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
-            tasks.append(t.stop())
-
-        with VM('graal', 'product'):
-            t = Task('BootstrapWithRegisterPressure:product')
-            vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version'])
-            tasks.append(t.stop())
-
-        with VM('graal', 'product'):
-            t = Task('BootstrapWithAOTConfiguration:product')
-            vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version'])
-            tasks.append(t.stop())
-
-        with VM('server', 'product'):  # hosted mode
-            t = Task('UnitTests:hosted-product')
-            unittest([])
-            tasks.append(t.stop())
-
-        for vmbuild in ['fastdebug', 'product']:
-            for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild):
-                t = Task(str(test) + ':' + vmbuild)
-                if not test.test('graal'):
-                    t.abort(test.name + ' Failed')
-                tasks.append(t.stop())
-
-        if args.jacocout is not None:
-            jacocoreport([args.jacocout])
-
-        _jacoco = 'off'
-
-        t = Task('CleanAndBuildGraalVisualizer')
-        mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build'])
-        tasks.append(t.stop())
-
-        # Prevent Graal modifications from breaking the standard builds
-        if args.buildNonGraal:
-            t = Task('BuildHotSpotVarieties')
-            buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product'])
-            buildvms(['--vms', 'server-nograal', '--builds', 'product'])
-            buildvms(['--vms', 'server-nograal', '--builds', 'optimized'])
-            tasks.append(t.stop())
-
-            for vmbuild in ['product', 'fastdebug']:
-                for theVm in ['client', 'server']:
-                    with VM(theVm, vmbuild):
-                        t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
-                        dacapo(['pmd'])
-                        tasks.append(t.stop())
-
-                        t = Task('UnitTests:' + theVm + ':' + vmbuild)
-                        unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api'])
-                        tasks.append(t.stop())
+        gate_body(args, tasks)
 
     except KeyboardInterrupt:
         total.abort(1)
--- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Fri Sep 20 11:25:53 2013 +0200
+++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Tue Sep 24 15:35:59 2013 +0200
@@ -157,7 +157,7 @@
 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
 org.eclipse.jdt.core.formatter.blank_lines_after_package=1
 org.eclipse.jdt.core.formatter.blank_lines_before_field=0
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
 org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
 org.eclipse.jdt.core.formatter.blank_lines_before_method=1
--- a/mxtool/mx.py	Fri Sep 20 11:25:53 2013 +0200
+++ b/mxtool/mx.py	Tue Sep 24 15:35:59 2013 +0200
@@ -39,8 +39,8 @@
 The configuration information for a suite lives in an 'mx' sub-directory
 at the top level of the suite. A suite is given a name by a 'suite=name'
 property in the 'mx/projects' file (if omitted the name is suite directory).
-An 'mx' subdirectory can be named as plain 'mx' or 'mxbasename', where
-'basename' is the os.path.basename of the suite directory.
+An 'mx' subdirectory can be named as plain 'mx' or 'mx.name', where
+'name' is typically the name as the suite name.
 The latter is useful to avoid clashes in IDE project names.
 
 When launched, mx treats the current working directory as a suite.
@@ -158,6 +158,8 @@
 _mainSuite = None
 _opts = None
 _java = None
+_check_global_structures = True # can be set False to allow suites with duplicate definitions to load without aborting
+
 
 """
 A distribution is a jar or zip file containing the output from one or more Java projects.
@@ -516,6 +518,13 @@
         projectsFile = join(mxDir, 'projects')
         if not exists(projectsFile):
             return
+
+        def _find_suite_key():
+            for items in _suites.items():
+                if items[1].dir == self.dir:
+                    return items[0]
+            raise KeyError
+
         with open(projectsFile) as f:
             for line in f:
                 line = line.strip()
@@ -527,7 +536,11 @@
                     if len(parts) == 1:
                         if parts[0] != 'suite':
                             abort('Single part property must be "suite": ' + key)
-                        self.name = value
+                        if self.name != value:
+                            currentKey = _find_suite_key()
+                            _suites.pop(currentKey)
+                            self.name = value
+                            _suites[value] = self
                         continue
                     if len(parts) != 3:
                         abort('Property name does not have 3 parts separated by "@": ' + key)
@@ -639,24 +652,29 @@
                             abort(e + ':' + str(lineNum) + ': line does not match pattern "key=value"')
                         key, value = line.split('=', 1)
                         os.environ[key.strip()] = expandvars_in_property(value.strip())
+
     def _post_init(self, opts):
         self._load_projects(self.mxDir)
+        # set the global data structures, checking for conflicts unless _global_structures is False
         for p in self.projects:
             existing = _projects.get(p.name)
-            if existing is not None:
+            if existing is not None and _check_global_structures:
                 abort('cannot override project  ' + p.name + ' in ' + p.dir + " with project of the same name in  " + existing.dir)
             if not p.name in _opts.ignored_projects:
                 _projects[p.name] = p
         for l in self.libs:
             existing = _libs.get(l.name)
             # Check that suites that define same library are consistent
-            if existing is not None and existing != l:
+            if existing is not None and existing != l and _check_global_structures:
                 abort('inconsistent library redefinition of ' + l.name + ' in ' + existing.suite.dir + ' and ' + l.suite.dir)
             _libs[l.name] = l
         for d in self.dists:
             existing = _dists.get(d.name)
-            if existing is not None:
-                abort('cannot redefine distribution  ' + d.name)
+            if existing is not None and _check_global_structures:
+                # allow redefinition, so use path from existing
+                # abort('cannot redefine distribution  ' + d.name)
+                print('WARNING: distribution ' + d.name + ' redefined')
+                d.path = existing.path
             _dists[d.name] = d
         if hasattr(self, 'mx_post_parse_cmd_line'):
             self.mx_post_parse_cmd_line(opts)
@@ -754,11 +772,11 @@
 
 def _loadSuite(d, primary=False):
     """
-    Load a suite from the 'mx' or 'mxbbb' subdirectory of d, where 'bbb' is basename of d
+    Load a suite from the 'mx' or 'mx.bbb' subdirectory of d, where 'bbb' is basename of d
     """
     mxDefaultDir = join(d, 'mx')
     name = os.path.basename(d)
-    mxTaggedDir = mxDefaultDir + name
+    mxTaggedDir = mxDefaultDir + '.' + name
     mxDir = None
     if exists(mxTaggedDir) and isdir(mxTaggedDir):
         mxDir = mxTaggedDir
@@ -771,14 +789,22 @@
         return None
     if len([s for s in _suites.itervalues() if s.dir == d]) == 0:
         s = Suite(d, mxDir, primary)
+        # N.B. this will be updated once the projects file has been read
         _suites[name] = s
         return s
 
-def suites():
+def suites(opt_limit_to_suite=False):
     """
     Get the list of all loaded suites.
     """
-    return _suites.values()
+    if opt_limit_to_suite and _opts.specific_suites:
+        result = []
+        for s in _suites:
+            if s.name in _opts.specific_suites:
+                result.append(s)
+        return result
+    else:
+        return _suites.values()
 
 def suite(name, fatalIfMissing=True):
     """
@@ -789,11 +815,41 @@
         abort('suite named ' + name + ' not found')
     return s
 
-def projects():
+def projects_from_names(projectNames):
+    """
+    Get the list of projects corresponding to projectNames; all projects if None
+    """
+    if projectNames is None:
+        return projects()
+    else:
+        return [project(name) for name in projectNames]
+
+def projects(opt_limit_to_suite=False):
+    """
+    Get the list of all loaded projects limited by --suite option if opt_limit_to_suite == True
     """
-    Get the list of all loaded projects.
+
+    if opt_limit_to_suite:
+        return _projects_opt_limit_to_suites(_projects.values())
+    else:
+        return _projects.values()
+
+def projects_opt_limit_to_suites():
+    """
+    Get the list of all loaded projects optionally limited by --suite option
     """
-    return _projects.values()
+    return projects(True)
+
+def _projects_opt_limit_to_suites(projects):
+    if not _opts.specific_suites:
+        return projects
+    else:
+        result = []
+        for p in projects:
+            s = p.suite
+            if s.name in _opts.specific_suites:
+                result.append(p)
+        return result
 
 def annotation_processors():
     """
@@ -914,27 +970,16 @@
     are before the projects that depend on them. Unless 'includeLibs' is
     true, libraries are omitted from the result.
     """
+    projects = projects_from_names(projectNames)
+
+    return sorted_project_deps(projects, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
+
+def sorted_project_deps(projects, includeLibs=False, includeAnnotationProcessors=False):
     deps = []
-    if projectNames is None:
-        projects = opt_limit_to_suite(_projects.values())
-    else:
-        projects = [project(name) for name in projectNames]
-
     for p in projects:
         p.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
     return deps
 
-def opt_limit_to_suite(projects):
-    if _opts.specific_suite is None:
-        return projects
-    else:
-        result = []
-        for p in projects:
-            s = p.suite
-            if s.name == _opts.specific_suite:
-                result.append(p)
-        return result
-
 def _handle_missing_java_home():
     if not sys.stdout.isatty():
         abort('Could not find bootstrap JDK. Use --java-home option or ensure JAVA_HOME environment variable is set.')
@@ -999,7 +1044,7 @@
         self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
         self.add_argument('--java-home', help='bootstrap JDK installation directory (must be JDK 6 or later)', metavar='<path>')
         self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
-        self.add_argument('--suite', dest='specific_suite', help='limit command to given suite', default=None)
+        self.add_argument('--suite', action='append', dest='specific_suites', help='limit command to given suite', default=[])
         if get_os() != 'windows':
             # Time outs are (currently) implemented with Unix specific functionality
             self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='<secs>')
@@ -1553,14 +1598,18 @@
 
     built = set()
 
-    projects = None
-    if args.projects is not None:
-        projects = args.projects.split(',')
-
     if args.only is not None:
+        # N.B. This build will not include dependencies including annotation processor dependencies
         sortedProjects = [project(name) for name in args.only.split(',')]
     else:
-        sortedProjects = sorted_deps(projects, includeAnnotationProcessors=True)
+        if args.projects is not None:
+            projectNames = args.projects.split(',')
+        else:
+            projectNames = None
+
+        projects = _projects_opt_limit_to_suites(projects_from_names(projectNames))
+        # N.B. Limiting to a suite only affects the starting set of projects. Dependencies in other suites will still be compiled
+        sortedProjects = sorted_project_deps(projects, includeAnnotationProcessors=True)
 
     if args.java:
         ideinit([], refreshOnly=True, buildProcessorJars=False)
@@ -2060,7 +2109,7 @@
     args = parser.parse_args(args)
 
     totalErrors = 0
-    for p in sorted_deps():
+    for p in projects_opt_limit_to_suites():
         if p.native:
             continue
         sourceDirs = p.source_dirs()
@@ -2191,7 +2240,7 @@
 
     args = parser.parse_args(args)
 
-    for p in projects():
+    for p in projects_opt_limit_to_suites():
         if p.native:
             if args.native:
                 run([gmake_cmd(), '-C', p.dir, 'clean'])
@@ -2283,7 +2332,7 @@
     slm.close('sourceLookupDirector')
     return slm
 
-def make_eclipse_attach(hostname, port, name=None, deps=None):
+def make_eclipse_attach(suite, hostname, port, name=None, deps=None):
     """
     Creates an Eclipse launch configuration file for attaching to a Java process.
     """
@@ -2305,8 +2354,12 @@
     launch = launch.xml(newl='\n', standalone='no') % slm.xml(escape=True, standalone='no')
 
     if name is None:
-        name = 'attach-' + hostname + '-' + port
-    eclipseLaunches = join('mx', 'eclipse-launches')
+        if len(suites()) == 1:
+            suitePrefix = ''
+        else:
+            suitePrefix = suite.name + '-'
+        name = suitePrefix + 'attach-' + hostname + '-' + port
+    eclipseLaunches = join(suite.mxDir, 'eclipse-launches')
     if not exists(eclipseLaunches):
         os.makedirs(eclipseLaunches)
     return update_file(join(eclipseLaunches, name + '.launch'), launch)
@@ -2378,12 +2431,15 @@
         os.makedirs(eclipseLaunches)
     return update_file(join(eclipseLaunches, name + '.launch'), launch)
 
-def eclipseinit(args, suite=None, buildProcessorJars=True, refreshOnly=False):
+def eclipseinit(args, buildProcessorJars=True, refreshOnly=False):
     """(re)generate Eclipse project configurations and working sets"""
-
-    if suite is None:
-        suite = _mainSuite
-
+    for s in suites(True):
+        _eclipseinit_suite(args, s, buildProcessorJars, refreshOnly)
+
+    generate_eclipse_workingsets()
+
+
+def _eclipseinit_suite(args, suite, buildProcessorJars=True, refreshOnly=False):
     projectsFile = join(suite.mxDir, 'projects')
     timestamp = TimeStampFile(join(suite.mxDir, 'eclipseinit.timestamp'))
     if refreshOnly and not timestamp.exists():
@@ -2394,6 +2450,7 @@
         return
 
     if buildProcessorJars:
+        ## todo suite specific
         processorjars()
 
     projToDist = dict()
@@ -2402,7 +2459,7 @@
         for p in distDeps:
             projToDist[p.name] = (dist, [dep.name for dep in distDeps])
 
-    for p in projects():
+    for p in suite.projects:
         if p.native:
             continue
 
@@ -2577,8 +2634,7 @@
             out.close('factorypath')
             update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n'))
 
-    make_eclipse_attach('localhost', '8000', deps=projects())
-    generate_eclipse_workingsets(suite)
+    make_eclipse_attach(suite, 'localhost', '8000', deps=projects())
     timestamp.touch()
 
 def _isAnnotationProcessorDependency(p):
@@ -2636,20 +2692,27 @@
     dotProjectDoc.close('arguments')
     dotProjectDoc.close('buildCommand')
 
-def generate_eclipse_workingsets(suite):
+def generate_eclipse_workingsets():
     """
-    Populate the workspace's working set configuration with working sets generated from project data.
+    Populate the workspace's working set configuration with working sets generated from project data for the primary suite
     If the workspace already contains working set definitions, the existing ones will be retained and extended.
-    In case mx/env does not contain a WORKSPACE definition pointing to the workspace root directory, the Graal project root directory will be assumed.
-    If no workspace root directory can be identified, the Graal project root directory is used and the user has to place the workingsets.xml file by hand.
+    In case mx/env does not contain a WORKSPACE definition pointing to the workspace root directory, a parent search from the primary suite directory is performed.
+    If no workspace root directory can be identified, the primary suite directory is used and the user has to place the workingsets.xml file by hand.
     """
 
     # identify the location where to look for workingsets.xml
     wsfilename = 'workingsets.xml'
     wsloc = '.metadata/.plugins/org.eclipse.ui.workbench'
-    wsroot = suite.dir
     if os.environ.has_key('WORKSPACE'):
-        wsroot = os.environ['WORKSPACE']
+        expected_wsroot = os.environ['WORKSPACE']
+    else:
+        expected_wsroot = _mainSuite.dir
+
+    wsroot = _find_eclipse_wsroot(expected_wsroot)
+    if wsroot is None:
+        # failed to find it
+        wsroot = expected_wsroot
+
     wsdir = join(wsroot, wsloc)
     if not exists(wsdir):
         wsdir = wsroot
@@ -2674,6 +2737,20 @@
 
     update_file(wspath, wsdoc.xml(newl='\n'))
 
+def _find_eclipse_wsroot(wsdir):
+    md = join(wsdir, '.metadata')
+    if exists(md):
+        return wsdir
+    split = os.path.split(wsdir)
+    # How to do this for Windows?
+    if split[0] == '/':
+        return None
+    else:
+        return _find_eclipse_wsroot(split[0])
+
+def _foobar(val):
+    print(val)
+
 def _make_workingset_xml(workingSets):
     wsdoc = XMLDoc()
     wsdoc.open('workingSetManager')
@@ -2756,12 +2833,13 @@
 def _workingset_element(wsdoc, p):
     wsdoc.element('item', {'elementID': '=' + p, 'factoryID': 'org.eclipse.jdt.ui.PersistableJavaElementFactory'})
 
-def netbeansinit(args, suite=None, refreshOnly=False, buildProcessorJars=True):
+def netbeansinit(args, refreshOnly=False, buildProcessorJars=True):
     """(re)generate NetBeans project configurations"""
 
-    if suite is None:
-        suite = _mainSuite
-
+    for suite in suites(True):
+        _netbeansinit_suite(args, suite, refreshOnly, buildProcessorJars)
+
+def _netbeansinit_suite(args, suite, refreshOnly=False, buildProcessorJars=True):
     projectsFile = join(suite.mxDir, 'projects')
     timestamp = TimeStampFile(join(suite.mxDir, 'netbeansinit.timestamp'))
     if refreshOnly and not timestamp.exists():
@@ -2772,7 +2850,7 @@
         return
 
     updated = False
-    for p in projects():
+    for p in suite.projects:
         if p.native:
             continue
 
@@ -2988,7 +3066,7 @@
 
     timestamp.touch()
 
-def ideclean(args, suite=None):
+def ideclean(args):
     """remove all Eclipse and NetBeans project configurations"""
     def rm(path):
         if exists(path):
@@ -3016,16 +3094,16 @@
             log("Error removing {0}".format(p.name + '.jar'))
 
 
-def ideinit(args, suite=None, refreshOnly=False, buildProcessorJars=True):
+def ideinit(args, refreshOnly=False, buildProcessorJars=True):
     """(re)generate Eclipse and NetBeans project configurations"""
-    eclipseinit(args, suite, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
-    netbeansinit(args, suite, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
+    eclipseinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
+    netbeansinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars)
     if not refreshOnly:
         fsckprojects([])
 
 def fsckprojects(args):
     """find directories corresponding to deleted Java projects and delete them"""
-    for suite in suites():
+    for suite in suites(True):
         projectDirs = [p.dir for p in suite.projects]
         for root, dirnames, files in os.walk(suite.dir):
             currentDir = join(suite.dir, root)
@@ -3058,9 +3136,10 @@
     args = parser.parse_args(args)
 
     # build list of projects to be processed
-    candidates = sorted_deps()
     if args.projects is not None:
         candidates = [project(name) for name in args.projects.split(',')]
+    else:
+        candidates = projects_opt_limit_to_suites()
 
     # optionally restrict packages within a project
     packages = []
@@ -3588,7 +3667,7 @@
 def _findPrimarySuite():
     def is_suite_dir(d):
         for f in os.listdir(d):
-            if fnmatch.fnmatch(f, 'mx*'):
+            if f == 'mx' or fnmatch.fnmatch(f, 'mx.*'):
                 mxDir = join(d, f)
                 if exists(mxDir) and isdir(mxDir) and exists(join(mxDir, 'projects')):
                     return dirname(mxDir)
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Fri Sep 20 11:25:53 2013 +0200
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Tue Sep 24 15:35:59 2013 +0200
@@ -182,9 +182,4 @@
   }
 }
 
-inline int32_t* CodeInstaller::pd_locate_operand(address instruction) {
-  fatal("CodeInstaller::pd_locate_operand - sparc unimp");
-  return (int32_t*)0;
-}
-
 #endif // CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
--- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Fri Sep 20 11:25:53 2013 +0200
+++ b/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Tue Sep 24 15:35:59 2013 +0200
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-#ifndef CPU_SPARC_VM_CODEINSTALLER_X86_HPP
-#define CPU_SPARC_VM_CODEINSTALLER_X86_HPP
+#ifndef CPU_X86_VM_CODEINSTALLER_X86_HPP
+#define CPU_X86_VM_CODEINSTALLER_X86_HPP
 
 #include "compiler/disassembler.hpp"
 #include "runtime/javaCalls.hpp"
@@ -207,9 +207,35 @@
   }
 }
 
-inline int32_t* CodeInstaller::pd_locate_operand(address instruction) {
-  return (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+  switch (mark) {
+    case MARK_POLL_NEAR: {
+      NativeInstruction* ni = nativeInstruction_at(pc);
+      int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
+      // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+      int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
+      intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
+      *disp = (int32_t)new_disp;
+    }
+    case MARK_POLL_FAR:
+      _instructions->relocate(pc, relocInfo::poll_type);
+      break;
+    case MARK_POLL_RETURN_NEAR: {
+      NativeInstruction* ni = nativeInstruction_at(pc);
+      int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
+      // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+      int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
+      intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
+      *disp = (int32_t)new_disp;
+    }
+    case MARK_POLL_RETURN_FAR:
+      _instructions->relocate(pc, relocInfo::poll_return_type);
+      break;
+    default:
+      ShouldNotReachHere();
+      break;
+  }
 }
 
-#endif // CPU_SPARC_VM_CODEINSTALLER_X86_HPP
+#endif // CPU_X86_VM_CODEINSTALLER_X86_HPP
 
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Sep 20 11:25:53 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Sep 24 15:35:59 2013 +0200
@@ -810,27 +810,11 @@
         _next_call_type = (MarkId) id;
         _invoke_mark_pc = pc;
         break;
-      case MARK_POLL_NEAR: {
-        NativeInstruction* ni = nativeInstruction_at(pc);
-        int32_t* disp = (int32_t*) pd_locate_operand(pc);
-        // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
-        int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
-        intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
-        *disp = (int32_t)new_disp;
-      }
+      case MARK_POLL_NEAR:
       case MARK_POLL_FAR:
-        _instructions->relocate(pc, relocInfo::poll_type);
-        break;
-      case MARK_POLL_RETURN_NEAR: {
-        NativeInstruction* ni = nativeInstruction_at(pc);
-        int32_t* disp = (int32_t*) pd_locate_operand(pc);
-        // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
-        int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
-        intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
-        *disp = (int32_t)new_disp;
-      }
+      case MARK_POLL_RETURN_NEAR:
       case MARK_POLL_RETURN_FAR:
-        _instructions->relocate(pc, relocInfo::poll_return_type);
+        pd_relocate_poll(pc, id);
         break;
       default:
         ShouldNotReachHere();
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Fri Sep 20 11:25:53 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Tue Sep 24 15:35:59 2013 +0200
@@ -80,7 +80,7 @@
   void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst);
   void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination);
   void pd_relocate_JavaMethod(oop method, jint pc_offset);
-  int32_t* pd_locate_operand(address instruction);
+  void pd_relocate_poll(address pc, jint mark);
 
 public: