changeset 10773:fbeda94727f8

Merge
author twisti
date Mon, 15 Jul 2013 17:58:17 -0700
parents dfc4b73e79e8 (current diff) 395d34c10e26 (diff)
children 0f8d0c86611d c0ce8e825f30
files
diffstat 59 files changed, 1569 insertions(+), 213 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Mon Jul 15 17:58:17 2013 -0700
@@ -79,13 +79,15 @@
      * created by JNI since these JNI global references do not move.
      */
     public final void mov(Register a, Object obj) {
+        String regName = "$d" + a.encoding();
         if (obj instanceof Class) {
             Class<?> clazz = (Class<?>) obj;
             long refHandle = OkraUtil.getRefHandle(clazz);
             String className = clazz.getName();
-            String regName = "$d" + a.encoding();
             emitString("mov_b64 " + regName + ", 0x" + Long.toHexString(refHandle) + ";  // handle for " + className);
             emitString("ld_global_u64 " + regName + ", [" + regName + "];");
+        } else if (obj == null) {
+            emitString("mov_b64 " + regName + ", 0x0;  // null object");
         } else {
             throw GraalInternalError.shouldNotReachHere("mov from object not a class");
         }
@@ -101,16 +103,32 @@
         }
     }
 
+    private void emitAddrOp(String instr, Value reg, HSAILAddress addr) {
+        emitString(instr + " " + HSAIL.mapRegister(reg) + ", " + mapAddress(addr) + ";");
+    }
+
     public final void emitLoad(Value dest, HSAILAddress addr) {
-        emitString("ld_global_" + getArgType(dest) + " " + HSAIL.mapRegister(dest) + ", " + mapAddress(addr) + ";");
+        emitLoad(dest, addr, getArgType(dest));
+    }
+
+    public final void emitLoad(Value dest, HSAILAddress addr, String argTypeStr) {
+        emitAddrOp("ld_global_" + argTypeStr, dest, addr);
+    }
+
+    public final void emitLda(Value dest, HSAILAddress addr) {
+        emitAddrOp("lda_global_u64", dest, addr);
+    }
+
+    public final void emitStore(Value src, HSAILAddress addr) {
+        emitStore(src, addr, getArgType(src));
+    }
+
+    public final void emitStore(Value dest, HSAILAddress addr, String argTypeStr) {
+        emitAddrOp("st_global_" + argTypeStr, dest, addr);
     }
 
     public final void emitSpillLoad(Value dest, Value src) {
-        emitString("ld_spill_" + getArgType(dest) + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapStackSlot(src) + ";");
-    }
-
-    public final void emitStore(Value src, HSAILAddress addr) {
-        emitString("st_global_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapAddress(addr) + ";");
+        emitString("ld_spill_" + getArgType(dest) + " " + HSAIL.mapRegister(dest) + ", " + mapStackSlot(src, getArgSize(dest)) + ";");
     }
 
     public final void emitSpillStore(Value src, Value dest) {
@@ -122,7 +140,21 @@
         if (maxStackOffset < stackoffset) {
             maxStackOffset = stackoffset;
         }
-        emitString("st_spill_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + HSAIL.mapStackSlot(dest) + ";");
+        emitString("st_spill_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSize(src)) + ";");
+    }
+
+    /**
+     * The mapping to stack slots is always relative to the beginning
+     * of the spillseg.  HSAIL.getStackOffset returns the positive
+     * version of the originally negative offset.  Then we back up
+     * from that by the argSize in bytes.  This ensures that slots of
+     * different size do not overlap, even though we have converted
+     * from negative to positive offsets.
+     */
+    public static String mapStackSlot(Value reg, int argSize) {
+        long offset = HSAIL.getStackOffset(reg);
+        int argSizeBytes = argSize / 8;
+        return "[%spillseg]" + "[" + (offset - argSizeBytes) + "]";
     }
 
     public void cbr(String target1) {
@@ -181,7 +213,9 @@
 
     public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) {
         String prefix = "cmp_" + condition + (unordered ? "u" : "") + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : getArgType(src1));
-        emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";");
+        String comment = (isConstant(src1) && (src1.getKind() == Kind.Object)
+                          && (asConstant(src1).asObject() == null) ? " // null test " : "");
+        emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";" + comment);
     }
 
     public void emitConvert(Value dest, Value src) {
@@ -210,7 +244,14 @@
                 case Double:
                     return Double.toString(consrc.asDouble());
                 case Long:
-                    return Long.toString(consrc.asLong());
+                    return "0x" + Long.toHexString(consrc.asLong());
+                case Object:
+                    Object obj = consrc.asObject();
+                    if (obj == null) {
+                        return "0";
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("unknown type: " + src);
+                    }
                 default:
                     throw GraalInternalError.shouldNotReachHere("unknown type: " + src);
             }
@@ -223,14 +264,68 @@
         emit(mnemonic + "_" + prefix, dest, "", src0, src1);
     }
 
+    public final void emitForceUnsigned(String mnemonic, Value dest, Value src0, Value src1) {
+        String prefix = getArgTypeForceUnsigned(dest);
+        emit(mnemonic + "_" + prefix, dest, "", src0, src1);
+    }
+
+
     private void emit(String instr, Value dest, String controlRegString, Value src0, Value src1) {
         assert (!isConstant(dest));
         emitString(String.format("%s %s, %s%s, %s;", instr, HSAIL.mapRegister(dest), controlRegString, mapRegOrConstToString(src0), mapRegOrConstToString(src1)));
     }
 
+    private void emit(String instr, Value dest, Value src0, Value src1, Value src2) {
+        assert (!isConstant(dest));
+        emitString(String.format("%s %s, %s, %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(src0),
+                                 mapRegOrConstToString(src1), mapRegOrConstToString(src2)));
+    }
+
+
     public final void cmovCommon(Value dest, Value trueReg, Value falseReg, int width) {
         String instr = (width == 32 ? "cmov_b32" : "cmov_b64");
         emit(instr, dest, "$c0, ", trueReg, falseReg);
     }
 
+
+    /**
+     * Emit code to build a 64-bit pointer from a compressed-oop and the associated base and shift.
+     * We only emit this if base and shift are not both zero.
+     */
+    public void emitCompressedOopDecode(Value result, long narrowOopBase, int narrowOopShift) {
+        if (narrowOopBase == 0) {
+            emit("shl", result, result, Constant.forInt(narrowOopShift));
+        } else if (narrowOopShift == 0) {
+            // only use add if result is not starting as null (unsigned compare)
+            emitCompare(result, Constant.forLong(0), "eq", false, true);
+            emit("add", result, result, Constant.forLong(narrowOopBase));
+            cmovCommon(result, Constant.forLong(0), result, 64);
+        } else {
+            // only use mad if result is not starting as null (unsigned compare)
+            emitCompare(result, Constant.forLong(0), "eq", false, true);
+            emit("mad_u64 ", result, result, Constant.forInt(1 << narrowOopShift), Constant.forLong(narrowOopBase));
+            cmovCommon(result, Constant.forLong(0), result, 64);
+        }
+    }
+
+    /**
+     * Emit code to build a 32-bit compressed pointer from a full
+     * 64-bit pointer using the associated base and shift.  We only
+     * emit this if base and shift are not both zero.
+     */
+    public void emitCompressedOopEncode(Value result, long narrowOopBase, int narrowOopShift) {
+        if (narrowOopBase != 0) {
+            // only use sub if result is not starting as null (unsigned compare)
+            emitCompare(result, Constant.forLong(0), "eq", false, true);
+            emit("sub", result, result, Constant.forLong(narrowOopBase));
+            cmovCommon(result, Constant.forLong(0), result, 64);
+        }
+        if (narrowOopShift != 0) {
+            emit("shr", result, result, Constant.forInt(narrowOopShift));
+        }
+    }
+
+    public void emitComment(String comment) {
+        emitString(comment);
+    }
 }
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Mon Jul 15 17:58:17 2013 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.compiler.hsail.HSAILCompilationResult;
 import java.lang.reflect.Method;
 import java.io.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 public abstract class GraalKernelTester extends KernelTester {
 
@@ -61,4 +62,15 @@
         return hsailSource;
     }
 
+    public boolean aggressiveInliningEnabled() {
+        return (InlineEverything.getValue());
+    }
+
+    public boolean canHandleHSAILMethodCalls() {
+        // needs 2 things, backend needs to be able to generate such calls, and target needs to be
+        // able to run them
+        boolean canGenerateCalls = false;   // not implemented yet
+        boolean canExecuteCalls = runningOnSimulator();
+        return (canGenerateCalls && canExecuteCalls);
+    }
 }
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java	Mon Jul 15 17:58:17 2013 -0700
@@ -150,6 +150,12 @@
     }
 
     private boolean compareObjects(Object first, Object second) {
+        if (first == null) {
+            return (second == null);
+        }
+        if (second == null) {
+            return (first == null);
+        }
         Class<?> clazz = first.getClass();
         if (clazz != second.getClass()) {
             return false;
@@ -265,6 +271,11 @@
         Object getElement(Object ary, int index) {
             return Array.get(ary, index);
         }
+
+        @Override
+        boolean isEquals(Object firstElement, Object secondElement) {
+            return compareObjects(firstElement, secondElement);
+        }
     }
 
     /**
@@ -496,7 +507,7 @@
         String hsailSource = getHSAILSource(testMethod);
         if (!okraLibExists) {
             if (!gaveNoOkraWarning) {
-                logger.fine("No Okra library detected, skipping all KernelTester tests in " + this.getClass().getPackage().getName());
+                logger.severe("No Okra library detected, skipping all KernelTester tests in " + this.getClass().getPackage().getName());
                 gaveNoOkraWarning = true;
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/Float2DMatrixBase.java	Mon Jul 15 17:58:17 2013 -0700
@@ -0,0 +1,51 @@
+/*
+ * 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.compiler.hsail.test;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+/**
+ * Base class used by other Float2DMatrix tests.
+ */
+public abstract class Float2DMatrixBase extends GraalKernelTester {
+
+    float[][] matrixA;
+    float[][] matrixB;
+    @Result float[][] outMatrix;
+
+    public void setupArrays(int range) {
+        matrixA = new float[range][];
+        matrixB = new float[range][];
+        outMatrix = new float[range][];
+        for (int j = 0; j < range; j++) {
+            matrixA[j] = new float[range];
+            matrixB[j] = new float[range];
+            outMatrix[j] = new float[range];
+            for (int k = 0; k < range; k++) {
+                matrixA[j][k] = (j + k) % 7;
+                matrixB[j][k] = (j + k + 1) % 8;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/Float2DMatrixMultiplyRangeFinalTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests the mixing of 32-bit and 64-bit spills caused by loop unrolling.
+ */
+public class Float2DMatrixMultiplyRangeFinalTest extends Float2DMatrixBase {
+
+    static final int range = 6;
+
+    public void run(int gid) {
+        for (int j = 0; j < range; j++) {
+            float sum = 0;
+            for (int k = 0; k < range; k++) {
+                sum += (matrixA[gid][k] * matrixB[k][j]);
+            }
+            outMatrix[gid][j] = sum;
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays(range);
+        dispatchMethodKernel(range);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/Float2DMatrixMultiplyTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -0,0 +1,53 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.Test;
+
+/**
+ * Tests 2D array access for Matrix Multiplication.
+ */
+public class Float2DMatrixMultiplyTest extends Float2DMatrixBase {
+    int range = 20;
+
+    public void run(int gid) {
+        for (int j = 0; j < range; j++) {
+            float sum = 0;
+            for (int k = 0; k < range; k++) {
+                sum += (matrixA[gid][k] * matrixB[k][j]);
+            }
+            outMatrix[gid][j] = sum;
+        }
+    }
+    @Override
+    public void runTest() {
+        setupArrays(range);
+        dispatchMethodKernel(range);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjectStoreNullTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -0,0 +1,44 @@
+/*
+ * 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.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests the storing of null in an Object array.
+ */
+public class ObjectStoreNullTest extends ObjectStoreTest {
+
+    @Override
+    public void run(int gid) {
+        outIntegerArray[gid] = (gid % 3 == 1 ? null : inIntegerArray[gid]);
+    }
+
+    @Test
+    @Override
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjectStoreTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -0,0 +1,62 @@
+/*
+ * 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.compiler.hsail.test;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+/**
+ * Tests the storing of objects into an array.
+ */
+public class ObjectStoreTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public Integer[] outIntegerArray = new Integer[NUM];
+    public Integer[] inIntegerArray = new Integer[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            inIntegerArray[i] = new Integer(i);
+            outIntegerArray[i] = null;
+        }
+    }
+
+    public void run(int gid) {
+        outIntegerArray[gid] = inIntegerArray[gid];
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchMethodKernel(NUM);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelTest.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -25,6 +25,7 @@
 
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
 import org.junit.Test;
+import static org.junit.Assume.*;
 
 /**
  * Unit test that simulates the Mandelbrot application. The run method here is a static method
@@ -79,6 +80,7 @@
 
     @Test
     public void test() {
+        assumeTrue(runningOnSimulator());
         testGeneratedHsail();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyCallTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -0,0 +1,46 @@
+/*
+ * 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.compiler.hsail.test;
+
+import static org.junit.Assume.*;
+
+import org.junit.*;
+
+/**
+ * Unit test of NBody demo app. This version uses a call to the main routine which would normally be
+ * too large to inline.
+ */
+public class StaticNBodyCallTest extends StaticNBodyTest {
+
+    public static void run(float[] inxyz, float[] outxyz, float[] invxyz, float[] outvxyz, int gid) {
+        StaticNBodyTest.run(inxyz, outxyz, invxyz, outvxyz, gid);
+    }
+
+    @Test
+    @Override
+    public void test() {
+        assumeTrue(aggressiveInliningEnabled() || canHandleHSAILMethodCalls());
+        testGeneratedHsail();
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Mon Jul 15 17:58:17 2013 -0700
@@ -98,7 +98,7 @@
 
     public static HSAILCompilationResult getHSAILCompilationResult(StructuredGraph graph) {
         Debug.dump(graph, "Graph");
-        TargetDescription target = new TargetDescription(new HSAIL(), true, 1, 0, true);
+        TargetDescription target = new TargetDescription(new HSAIL(), true, 8, 0, true);
         HSAILBackend hsailBackend = new HSAILBackend(Graal.getRequiredCapability(GraalCodeCacheProvider.class), target);
         PhasePlan phasePlan = new PhasePlan();
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jul 15 17:58:17 2013 -0700
@@ -47,20 +47,29 @@
 import com.oracle.graal.lir.hsail.HSAILControlFlow.FloatCompareBranchOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.FloatCondMoveOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ReturnOp;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall1ArgOp;
 import com.oracle.graal.lir.hsail.HSAILMove.LeaOp;
 import com.oracle.graal.lir.hsail.HSAILMove.LoadOp;
 import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp;
 import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreOp;
+import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer;
+import com.oracle.graal.lir.hsail.HSAILMove.StoreCompressedPointer;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.hotspot.meta.*;
 
 /**
  * This class implements the HSAIL specific portion of the LIR generator.
  */
 public class HSAILLIRGenerator extends LIRGenerator {
 
+    private HotSpotRuntime runtime() {
+        return (HotSpotRuntime) runtime;
+    }
+
     public static class HSAILSpillMoveFactory implements LIR.SpillMoveFactory {
 
         @Override
@@ -123,6 +132,14 @@
         }
     }
 
+    protected HSAILAddressValue asAddressValue(Value address) {
+        if (address instanceof HSAILAddressValue) {
+            return (HSAILAddressValue) address;
+        } else {
+            return emitAddress(address, 0, Value.ILLEGAL, 0);
+        }
+    }
+
     public HSAILAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
         long finalDisp = displacement;
@@ -163,27 +180,36 @@
         return new HSAILAddressValue(target().wordKind, baseRegister, finalDisp);
     }
 
-    private HSAILAddressValue asAddress(Value address) {
-        if (address instanceof HSAILAddressValue) {
-            return (HSAILAddressValue) address;
-        } else {
-            return emitAddress(address, 0, Value.ILLEGAL, 0);
-        }
+    private static boolean isCompressCandidate(DeoptimizingNode access) {
+        return access != null && ((HeapAccess) access).compress();
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) {
-        HSAILAddressValue loadAddress = asAddress(address);
+    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode access) {
+        HSAILAddressValue loadAddress = asAddressValue(address);
         Variable result = newVariable(kind);
-        append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
+        LIRFrameState state = access != null ? state(access) : null;
+        assert access == null || access instanceof HeapAccess;
+        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
+            Variable scratch = newVariable(Kind.Long);
+            append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+        } else {
+            append(new LoadOp(kind, result, loadAddress, state));
+        }
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
-        HSAILAddressValue storeAddress = asAddress(address);
+    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode access) {
+        HSAILAddressValue storeAddress = asAddressValue(address);
+        LIRFrameState state = access != null ? state(access) : null;
         Variable input = load(inputVal);
-        append(new StoreOp(kind, storeAddress, input, deopting != null ? state(deopting) : null));
+        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
+            Variable scratch = newVariable(Kind.Long);
+            append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+        } else {
+            append(new StoreOp(kind, storeAddress, input, state));
+        }
     }
 
     @Override
@@ -460,6 +486,9 @@
             case Int:
                 append(new Op2Stack(IAND, result, a, loadNonConst(b)));
                 break;
+            case Long:
+                append(new Op2Stack(LAND, result, a, loadNonConst(b)));
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -483,6 +512,9 @@
             case Int:
                 append(new ShiftOp(ISHL, result, a, b));
                 break;
+            case Long:
+                append(new ShiftOp(LSHL, result, a, b));
+                break;
             default:
                 GraalInternalError.shouldNotReachHere();
         }
@@ -501,6 +533,9 @@
             case Int:
                 append(new ShiftOp(IUSHR, result, a, b));
                 break;
+            case Long:
+                append(new ShiftOp(LUSHR, result, a, b));
+                break;
             default:
                 GraalInternalError.shouldNotReachHere();
         }
@@ -561,7 +596,23 @@
 
     @Override
     protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
-        throw new InternalError("NYI emitForeignCall");
+        String callName = linkage.getDescriptor().getName();
+        if (callName.equals("createOutOfBoundsException") || callName.equals("createNullPointerException")) {
+            // hack Alert !!
+            switch (arguments.length) {
+                case 0:
+                    append(new ForeignCallNoArgOp(callName, result));
+                    break;
+                case 1:
+                    append(new ForeignCall1ArgOp(callName, result, arguments[0]));
+                    break;
+                default:
+                    throw new InternalError("NYI emitForeignCall");
+            }
+
+        } else {
+            throw new InternalError("NYI emitForeignCall");
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -22,8 +22,14 @@
  */
 package com.oracle.graal.compiler.test;
 
+import static org.junit.Assert.*;
+
 import org.junit.*;
 
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.*;
 import com.oracle.graal.phases.common.*;
 
 /**
@@ -89,4 +95,102 @@
 
         test("search", e2, "e3", new Entry("e4"));
     }
+
+    @SuppressWarnings("unused")
+    public static int testNullnessSnippet(Object a, Object b) {
+        if (a == null) {
+            if (a == b) {
+                if (b == null) {
+                    return 1;
+                } else {
+                    return -2;
+                }
+            } else {
+                if (b == null) {
+                    return 3;
+                } else {
+                    return 4;
+                }
+            }
+        } else {
+            if (a == b) {
+                if (b == null) {
+                    return -5;
+                } else {
+                    return 6;
+                }
+            } else {
+                if (b == null) {
+                    return 7;
+                } else {
+                    return 8;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testNullness() {
+        test("testNullnessSnippet", null, null);
+        test("testNullnessSnippet", null, new Object());
+        test("testNullnessSnippet", new Object(), null);
+        test("testNullnessSnippet", new Object(), new Object());
+
+        StructuredGraph graph = parse("testNullnessSnippet");
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) {
+            assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static int testDisjunctionSnippet(Object a) {
+        if (a instanceof Integer) {
+            if (a == null) {
+                return -1;
+            } else {
+                return 2;
+            }
+        } else {
+            return 3;
+        }
+    }
+
+    @Test
+    public void testDisjunction() {
+        StructuredGraph graph = parse("testDisjunctionSnippet");
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        IfNode ifNode = (IfNode) graph.start().next();
+        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
+        LogicDisjunctionNode disjunction = graph.unique(new LogicDisjunctionNode(graph.unique(new IsNullNode(graph.getLocal(0))), instanceOf));
+        ifNode.setCondition(disjunction);
+        ifNode.negate(disjunction);
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) {
+            assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
+        }
+    }
+
+    public static int testInvokeSnippet(Number n) {
+        if (n instanceof Integer) {
+            return n.intValue();
+        } else {
+            return 1;
+        }
+    }
+
+    @Test
+    public void testInvoke() {
+        test("testInvokeSnippet", new Integer(16));
+        StructuredGraph graph = parse("testInvokeSnippet");
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+
+        InvokeNode invoke = graph.getNodes(InvokeNode.class).first();
+        assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind());
+    }
+
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -507,6 +507,7 @@
     }
 
     private StructuredGraph parse0(Method m, GraphBuilderConfiguration conf) {
+        assert m.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + m;
         ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m);
         StructuredGraph graph = new StructuredGraph(javaMethod);
         new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -24,8 +24,6 @@
 
 import static org.junit.Assert.*;
 
-import java.util.concurrent.*;
-
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
@@ -43,7 +41,7 @@
 
     public static Object staticField;
 
-    public static class TestObject implements Callable<Integer> {
+    public static class TestObject {
 
         public int x;
         public int y;
@@ -52,11 +50,6 @@
             this.x = x;
             this.y = y;
         }
-
-        @Override
-        public Integer call() throws Exception {
-            return x;
-        }
     }
 
     public static class TestObject2 {
@@ -70,6 +63,16 @@
         }
     }
 
+    public static class TestObject3 extends TestObject {
+
+        public int z;
+
+        public TestObject3(int x, int y, int z) {
+            super(x, y);
+            this.z = z;
+        }
+    }
+
     @SuppressWarnings("all")
     public static int testSimpleSnippet(TestObject a) {
         a.x = 2;
@@ -213,6 +216,24 @@
         assertEquals(1, graph.getNodes().filter(StoreFieldNode.class).count());
     }
 
+    public static int testValueProxySnippet(boolean b, TestObject o) {
+        int sum = 0;
+        if (b) {
+            sum += o.x;
+        } else {
+            TestObject3 p = (TestObject3) o;
+            sum += p.x;
+        }
+        sum += o.x;
+        return sum;
+    }
+
+    @Test
+    public void testValueProxy() {
+        processMethod("testValueProxySnippet");
+        assertEquals(2, graph.getNodes().filter(LoadFieldNode.class).count());
+    }
+
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
         assertEquals(1, graph.getNodes(ReturnNode.class).count());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Jul 15 17:58:17 2013 -0700
@@ -70,6 +70,11 @@
     private ValueNode lastInstructionPrinted; // Debugging only
 
     /**
+     * Records whether the code being generated makes at least one foreign call.
+     */
+    private boolean hasForeignCall;
+
+    /**
      * Checks whether the supplied constant can be used without loading it into a register for store
      * operations, i.e., on the right hand side of a memory access.
      * 
@@ -116,6 +121,13 @@
     }
 
     /**
+     * Determines whether the code being generated makes at least one foreign call.
+     */
+    public boolean hasForeignCall() {
+        return hasForeignCall;
+    }
+
+    /**
      * Returns the operand that has been previously initialized by
      * {@link #setResult(ValueNode, Value)} with the result of an instruction.
      * 
@@ -601,6 +613,7 @@
             emitMove(loc, arg);
             argLocations[i] = loc;
         }
+        this.hasForeignCall = true;
         emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state);
 
         if (isLegal(linkageCc.getReturn())) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Jul 15 17:58:17 2013 -0700
@@ -153,11 +153,13 @@
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
-        // - has no instructions with debug info
+        // - has no deoptimization points
+        // - makes no foreign calls (which require an aligned stack)
         AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
         FrameMap frameMap = gen.frameMap;
         LIR lir = gen.lir;
-        boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
+        assert gen.deoptimizationRescueSlot == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
+        boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall();
 
         Stub stub = gen.getStub();
         AbstractAssembler masm = createAssembler(frameMap);
@@ -236,7 +238,15 @@
             Register receiver = asRegister(cc.getArgument(0));
             AMD64Address src = new AMD64Address(receiver, config.hubOffset);
 
-            asm.cmpq(inlineCacheKlass, src);
+            AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
+            HotSpotRuntime hr = ((HotSpotRuntime) gen.getRuntime());
+            if (hr.config.useCompressedKlassPointers) {
+                Register register = r10;
+                AMD64Move.decodeKlassPointer(asm, register, src, hr.config.narrowKlassBase, hr.config.narrowKlassShift, hr.config.logKlassAlignment);
+                asm.cmpq(inlineCacheKlass, register);
+            } else {
+                asm.cmpq(inlineCacheKlass, src);
+            }
             asm.jcc(ConditionFlag.NotEqual, unverifiedStub);
         }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Jul 15 17:58:17 2013 -0700
@@ -413,9 +413,16 @@
         AMD64AddressValue loadAddress = asAddressValue(address);
         Variable result = newVariable(kind);
         assert access == null || access instanceof HeapAccess;
-        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
-            append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase, runtime().config.narrowOopShift,
-                            runtime().config.logMinObjAlignment));
+        if (isCompressCandidate(access)) {
+            if (runtime().config.useCompressedOops && kind == Kind.Object) {
+                append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase, runtime().config.narrowOopShift,
+                                runtime().config.logMinObjAlignment));
+            } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) {
+                append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) : null, runtime().config.narrowKlassBase, runtime().config.narrowKlassShift,
+                                runtime().config.logKlassAlignment));
+            } else {
+                append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
+            }
         } else {
             append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
         }
@@ -429,17 +436,31 @@
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
             if (canStoreConstant(c)) {
-                append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
+                if (inputVal.getKind() == Kind.Object) {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
+                } else if (inputVal.getKind() == Kind.Long) {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedKlassPointers && isCompressCandidate(access)));
+                } else {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, false));
+                }
                 return;
             }
         }
         Variable input = load(inputVal);
-        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
-            if (input.getKind() == Kind.Object) {
+        if (isCompressCandidate(access)) {
+            if (runtime().config.useCompressedOops && kind == Kind.Object) {
+                if (input.getKind() == Kind.Object) {
+                    Variable scratch = newVariable(Kind.Long);
+                    append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+                } else {
+                    // the input oop is already compressed
+                    append(new StoreOp(input.getKind(), storeAddress, input, state));
+                }
+            } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) {
                 Variable scratch = newVariable(Kind.Long);
-                append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+                append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowKlassBase, runtime().config.narrowKlassShift, runtime().config.logKlassAlignment));
             } else {
-                append(new StoreOp(input.getKind(), storeAddress, input, state));
+                append(new StoreOp(kind, storeAddress, input, state));
             }
         } else {
             append(new StoreOp(kind, storeAddress, input, state));
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -287,6 +287,103 @@
         return "Test".equals(c1);
     }
 
+    @SuppressWarnings("unchecked")
+    public static Object[] unmodListTestByte(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        List<Byte> queue = (ArrayList<Byte>) c1;
+        Byte[] result = Collections.unmodifiableCollection(queue).toArray(new Byte[queue.size()]);
+        return result;
+    }
+
+    @Test
+    public void test13() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("unmodListTestByte");
+        List<Byte> list = new ArrayList<>();
+        Byte[] array = (Byte[]) installedBenchmarkCode.execute(list, null, null);
+        Assert.assertTrue(list.size() == array.length);
+    }
+
+    @Test
+    public void test14() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferTest");
+        StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest");
+        Assert.assertTrue(buffer.length() == 28);
+        String a = new String("TestTestTestTestTestTestTest");
+        installedBenchmarkCode.execute(buffer, a.toCharArray(), null);
+        Assert.assertTrue(buffer.length() == 56);
+        Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+    }
+
+    public static void stringBufferTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        StringBuffer source = (StringBuffer) c1;
+        char[] add = (char[]) c2;
+        for (int i = 0; i < add.length; i++) {
+            source.append(add[i]);
+        }
+    }
+
+    @Test
+    public void test15() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferTestIn");
+        installedBenchmarkCode.execute(null, null, null);
+    }
+
+    @SuppressWarnings("unused")
+    public static void stringBufferTestIn(Object c1, Object c2, Object c3) {
+        StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest");
+        Assert.assertTrue(buffer.length() == 28);
+        String a = new String("TestTestTestTestTestTestTest");
+        char[] add = a.toCharArray();
+        for (int i = 0; i < add.length; i++) {
+            buffer.append(add[i]);
+        }
+        Assert.assertTrue(buffer.length() == 56);
+        Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+    }
+
+    @Test
+    public void test16() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferArrayCopy");
+        installedBenchmarkCode.execute(null, null, null);
+    }
+
+    @SuppressWarnings("unused")
+    public static void stringBufferArrayCopy(Object c1, Object c2, Object c3) {
+        StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest");
+        Assert.assertTrue(buffer.length() == 28);
+        String a = new String("TestTestTestTestTestTestTest");
+        char[] dst = new char[buffer.length() * 2];
+        System.arraycopy(buffer.toString().toCharArray(), 0, dst, 0, buffer.length());
+        System.arraycopy(a.toCharArray(), 0, dst, buffer.length(), buffer.length());
+        Assert.assertTrue(dst.length == 56);
+        Assert.assertTrue(new String(dst).equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+    }
+
+    @Test
+    public void test17() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringFormat");
+        installedBenchmarkCode.execute(null, null, null);
+    }
+
+    @SuppressWarnings("unused")
+    public static void stringFormat(Object c1, Object c2, Object c3) {
+        String.format("Hello %d", 0);
+        String.format("Hello %d", -11);
+        String.format("Hello %d", -2147483648);
+    }
+
+    @Test
+    public void test18() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBuilder");
+        StringBuilder b = (StringBuilder) installedBenchmarkCode.execute(null, null, null);
+        Assert.assertTrue(b.capacity() == 16);
+        Assert.assertTrue(b.length() == 0);
+    }
+
+    @SuppressWarnings("unused")
+    public static Object stringBuilder(Object c1, Object c2, Object c3) {
+        return new StringBuilder();
+    }
+
     static class Container {
 
         public Object a = new Object();
@@ -352,5 +449,4 @@
 
         }
     }
-
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Jul 15 17:58:17 2013 -0700
@@ -649,6 +649,10 @@
             ResolvedJavaMethod method = loadMethodNode.getMethod();
             ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, loadMethodNode.getHub(), method);
             graph.replaceFixed(loadMethodNode, metaspaceMethod);
+        } else if (n instanceof StoreHubNode) {
+            StoreHubNode storeHub = (StoreHubNode) n;
+            WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue());
+            graph.replaceFixed(storeHub, hub);
         } else if (n instanceof FixedGuardNode) {
             FixedGuardNode node = (FixedGuardNode) n;
             GuardingNode guard = tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated());
@@ -836,7 +840,13 @@
     private ReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object) {
         LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false));
+        return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, config.useCompressedKlassPointers));
+    }
+
+    private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) {
+        LocationNode location = ConstantLocationNode.create(ANY_LOCATION, wordKind, config.hubOffset, graph);
+        assert !object.isConstant() || object.asConstant().isNull();
+        return graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE, config.useCompressedKlassPointers));
     }
 
     public static long referentOffset() {
@@ -1158,7 +1168,11 @@
                 return Constant.forInt(base == null ? unsafe.getInt(displacement) : unsafe.getInt(base, displacement));
             case Long:
                 if (displacement == config().hubOffset && this.getGraalRuntime().getRuntime().config.useCompressedKlassPointers) {
-                    return Constant.forLong(this.getGraalRuntime().getCompilerToVM().readUnsafeKlassPointer(base));
+                    if (base == null) {
+                        throw new GraalInternalError("Base of object must not be null");
+                    } else {
+                        return Constant.forLong(this.getGraalRuntime().getCompilerToVM().readUnsafeKlassPointer(base));
+                    }
                 } else {
                     return Constant.forLong(base == null ? unsafe.getLong(displacement) : unsafe.getLong(base, displacement));
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FixedValueAnchorNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FixedValueAnchorNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable {
+public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy {
 
     @Input private ValueNode object;
 
@@ -53,4 +53,9 @@
         generator.setResult(this, generator.operand(object));
     }
 
+    @Override
+    public ValueNode getOriginalValue() {
+        return object;
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Jul 15 17:58:17 2013 -0700
@@ -69,10 +69,12 @@
         WriteBarrierType barrierType = node.getWriteBarrierType();
         if (barrierType == WriteBarrierType.PRECISE) {
             if (useG1GC()) {
-                G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck()));
-                preBarrier.setDeoptimizationState(node.getDeoptimizationState());
-                node.setNullCheck(false);
-                graph.addBeforeFixed(node, preBarrier);
+                if (node.isInitialized()) {
+                    G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck()));
+                    preBarrier.setDeoptimizationState(node.getDeoptimizationState());
+                    node.setNullCheck(false);
+                    graph.addBeforeFixed(node, preBarrier);
+                }
                 graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.value(), node.location(), true)));
             } else {
                 graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), true)));
@@ -116,9 +118,11 @@
 
     private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) {
         if (useG1GC()) {
-            G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+            if (node.isInitialized()) {
+                G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+                graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier);
+            }
             G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
-            graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier);
             graph.addAfterFixed(node, g1ArrayRangePostWriteBarrier);
         } else {
             SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Jul 15 17:58:17 2013 -0700
@@ -277,7 +277,7 @@
 
     public static void initializeObjectHeader(Word memory, Word markWord, Word hub) {
         memory.writeWord(markOffset(), markWord, MARK_WORD_LOCATION);
-        memory.writeWord(hubOffset(), hub, HUB_LOCATION);
+        StoreHubNode.write(memory.toObject(), hub);
     }
 
     @Fold
@@ -351,7 +351,7 @@
     }
 
     @Fold
-    public static int headerSize() {
+    public static int instanceHeaderSize() {
         return config().useCompressedKlassPointers ? (2 * wordSize()) - 4 : 2 * wordSize();
     }
 
@@ -473,6 +473,7 @@
     }
 
     public static Word loadWordFromObject(Object object, int offset) {
+        assert offset != hubOffset() : "Use loadHubIntrinsic instead";
         return loadWordFromObjectIntrinsic(object, 0, offset, getWordKind());
     }
 
@@ -488,7 +489,10 @@
     @SuppressWarnings("unused")
     @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true)
     static Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word) {
-        return Word.box(unsafeReadWord(object, hubOffset()));
+        if (wordKind() == Kind.Int) {
+            return Word.box((int) unsafeReadKlassPointer(object));
+        }
+        return Word.box(unsafeReadKlassPointer(object));
     }
 
     @Fold
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Jul 15 17:58:17 2013 -0700
@@ -203,12 +203,12 @@
             if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) {
                 new_seqInit.inc();
                 explodeLoop();
-                for (int offset = headerSize(); offset < size; offset += wordSize()) {
+                for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) {
                     memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                 }
             } else {
                 new_loopInit.inc();
-                for (int offset = headerSize(); offset < size; offset += wordSize()) {
+                for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) {
                     memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                 }
             }
@@ -259,7 +259,7 @@
             args.addConst("size", size);
             args.add("hub", hub);
             args.add("prototypeMarkWord", type.prototypeMarkWord());
-            args.addConst("fillContents", useG1GC() || newInstanceNode.fillContents());
+            args.addConst("fillContents", newInstanceNode.fillContents());
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args);
@@ -284,7 +284,7 @@
             args.add("prototypeMarkWord", arrayType.prototypeMarkWord());
             args.addConst("headerSize", headerSize);
             args.addConst("log2ElementSize", log2ElementSize);
-            args.addConst("fillContents", useG1GC() || newArrayNode.fillContents());
+            args.addConst("fillContents", newArrayNode.fillContents());
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
@@ -295,7 +295,7 @@
             Arguments args = new Arguments(allocateArrayDynamic);
             args.add("elementType", newArrayNode.getElementType());
             args.add("length", newArrayNode.length());
-            args.addConst("fillContents", useG1GC() || newArrayNode.fillContents());
+            args.addConst("fillContents", newArrayNode.fillContents());
 
             SnippetTemplate template = template(args);
             template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Mon Jul 15 17:58:17 2013 -0700
@@ -54,10 +54,10 @@
     private static Object instanceClone(Object src, Word hub, int layoutHelper) {
         int instanceSize = layoutHelper;
         Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
-        Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, useG1GC());
+        Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, false);
 
         Pointer memory = Word.fromObject(result);
-        for (int offset = headerSize(); offset < instanceSize; offset += wordSize()) {
+        for (int offset = instanceHeaderSize(); offset < instanceSize; offset += wordSize()) {
             memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION);
         }
 
@@ -71,7 +71,7 @@
         int sizeInBytes = NewObjectSnippets.computeArrayAllocationSize(arrayLength, wordSize(), headerSize, log2ElementSize);
 
         Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
-        Object result = NewObjectSnippets.allocateArray(hub, arrayLength, prototypeMarkWord, headerSize, log2ElementSize, useG1GC());
+        Object result = NewObjectSnippets.allocateArray(hub, arrayLength, prototypeMarkWord, headerSize, log2ElementSize, false);
 
         Pointer memory = Word.fromObject(result);
         for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -82,6 +82,11 @@
         return elementKind == Kind.Object;
     }
 
+    @Override
+    public boolean isInitialized() {
+        return true;
+    }
+
     public Kind getElementKind() {
         return elementKind;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Jul 15 17:58:17 2013 -0700
@@ -94,7 +94,7 @@
                 if (memory.notEqual(0)) {
                     Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
                     initializeObjectHeader(memory, prototypeMarkWord, hub);
-                    for (int offset = headerSize(); offset < sizeInBytes; offset += wordSize()) {
+                    for (int offset = instanceHeaderSize(); offset < sizeInBytes; offset += wordSize()) {
                         memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                     }
                     return verifyObject(memory.toObject());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Mon Jul 15 17:58:17 2013 -0700
@@ -213,7 +213,7 @@
                     fatal("oop not in heap: %p", oop.rawValue());
                 }
 
-                Word klass = oop.readWord(hubOffset());
+                Word klass = loadHub(object);
                 if (klass.equal(Word.zero())) {
                     fatal("klass for oop %p is null", oop.rawValue());
                 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Jul 15 17:58:17 2013 -0700
@@ -129,14 +129,18 @@
             this.base = base;
             this.shift = shift;
             this.alignment = alignment;
-            assert kind == Kind.Object;
+            assert kind == Kind.Object || kind == Kind.Long;
         }
 
         @Override
         public void emitMemAccess(AMD64MacroAssembler masm) {
             Register resRegister = asRegister(result);
             masm.movl(resRegister, address.toAddress());
-            decodePointer(masm, resRegister, base, shift, alignment);
+            if (kind == Kind.Object) {
+                decodePointer(masm, resRegister, base, shift, alignment);
+            } else {
+                decodeKlassPointer(masm, resRegister, base, shift, alignment);
+            }
         }
     }
 
@@ -203,13 +207,17 @@
             this.address = address;
             this.state = state;
             this.input = input;
-            assert kind == Kind.Object;
+            assert kind == Kind.Object || kind == Kind.Long;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
             masm.movq(asRegister(scratch), asRegister(input));
-            encodePointer(masm, asRegister(scratch), base, shift, alignment);
+            if (kind == Kind.Object) {
+                encodePointer(masm, asRegister(scratch), base, shift, alignment);
+            } else {
+                encodeKlassPointer(masm, asRegister(scratch), base, shift, alignment);
+            }
             if (state != null) {
                 tasm.recordImplicitException(masm.codeBuffer.position(), state);
             }
@@ -286,7 +294,11 @@
                     break;
                 case Long:
                     if (NumUtil.isInt(input.asLong())) {
-                        masm.movslq(address.toAddress(), (int) input.asLong());
+                        if (compress) {
+                            masm.movl(address.toAddress(), (int) input.asLong());
+                        } else {
+                            masm.movslq(address.toAddress(), (int) input.asLong());
+                        }
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                     }
@@ -691,4 +703,30 @@
         }
     }
 
+    private static void encodeKlassPointer(AMD64MacroAssembler masm, Register scratchRegister, long base, int shift, int alignment) {
+        if (base != 0) {
+            masm.subq(scratchRegister, AMD64.r12);
+        }
+        if (shift != 0) {
+            assert alignment == shift : "Encode algorithm is wrong";
+            masm.shrq(scratchRegister, alignment);
+        }
+    }
+
+    private static void decodeKlassPointer(AMD64MacroAssembler masm, Register resRegister, long base, int shift, int alignment) {
+        if (shift != 0) {
+            assert alignment == shift : "Decode algorighm is wrong";
+            masm.shlq(resRegister, alignment);
+            if (base != 0) {
+                masm.addq(resRegister, AMD64.r12);
+            }
+        } else {
+            assert base == 0 : "Sanity";
+        }
+    }
+
+    public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, AMD64Address address, long narrowKlassBase, int narrowKlassShift, int logKlassAlignment) {
+        masm.movl(register, address);
+        decodeKlassPointer(masm, register, narrowKlassBase, narrowKlassShift, logKlassAlignment);
+    }
 }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Mon Jul 15 17:58:17 2013 -0700
@@ -44,10 +44,11 @@
     IMIN, LMIN, IUMIN, LUMIN, IREM,
     LREM, FREM, DREM, IUREM, LUREM,
     ICARRY, LCARRY, IUCARRY, LUCARRY,
-    IAND, INEG, IUSHR, I2B, I2S, I2L,
+    IAND, LAND, INEG, I2B, I2S, I2L,
     F2D, F2I, F2L, D2F, I2F, I2D, D2I,
     L2F, D2L, MOV_F2I, MOV_D2L, L2D, MOV_I2F,
-    MOV_L2D, ISHL, SQRT, UNDEF, CALL, L2I;
+    MOV_L2D, ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR,
+    SQRT, UNDEF, CALL, L2I;
 
     public static class Op1Stack extends HSAILLIRInstruction {
         @Opcode private final HSAILArithmetic opcode;
@@ -245,6 +246,22 @@
     }
 
     public static void emit(TargetMethodAssembler tasm, HSAILAssembler masm, HSAILArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) {
+        /**
+         * First check if one of src1 or src2 is an AddressValue.  If it is,
+         * convert the address to a register using an lda instruction.  We can
+         * just reuse the eventual dst register for this.
+         */
+        if (src1 instanceof HSAILAddressValue) {
+            assert (!(src2 instanceof HSAILAddressValue));
+            masm.emitLda(dst, ((HSAILAddressValue) src1).toAddress());
+            emit(tasm, masm, opcode, dst, dst, src2, info);
+            return;
+        } else if (src2 instanceof HSAILAddressValue) {
+            assert (!(src1 instanceof HSAILAddressValue));
+            masm.emitLda(dst, ((HSAILAddressValue) src2).toAddress());
+            emit(tasm, masm, opcode, dst, src1, dst, info);
+            return;
+        }
         int exceptionOffset = -1;
         switch (opcode) {
             case IADD:
@@ -276,7 +293,14 @@
             case LMIN:
                 masm.emit("min", dst, src1, src2); break;
             case ISHL:
+            case LSHL:
                 masm.emit("shl", dst, src1, src2); break;
+            case ISHR:
+            case LSHR:
+                masm.emit("shr", dst, src1, src2); break;
+            case IUSHR:
+            case LUSHR:
+                masm.emitForceUnsigned("shr", dst, src1, src2); break;
             case IREM:
                 masm.emit("rem", dst, src1, src2); break;
             default:    throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Mon Jul 15 17:58:17 2013 -0700
@@ -53,6 +53,34 @@
         }
     }
 
+
+    public static class ForeignCallNoArgOp extends HSAILLIRInstruction {
+
+        @Def({REG}) protected Value out;
+        String callName;
+
+        public ForeignCallNoArgOp(String callName, Value out) {
+            this.out = out;
+            this.callName = callName;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
+            masm.emitComment("//ForeignCall to " + callName + " would have gone here");
+        }
+    }
+
+    public static class ForeignCall1ArgOp extends ForeignCallNoArgOp {
+
+        @Use({REG, ILLEGAL}) protected Value arg1;
+
+        public ForeignCall1ArgOp(String callName, Value out, Value arg1) {
+            super(callName, out);
+            this.arg1 = arg1;
+        }
+    }
+
+
     public static class CompareBranchOp extends HSAILLIRInstruction implements StandardOp.BranchOp {
 
         @Opcode protected final HSAILCompare opcode;
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Mon Jul 15 17:58:17 2013 -0700
@@ -129,49 +129,147 @@
         }
     }
 
-    public static class LoadOp extends HSAILLIRInstruction {
 
-        @SuppressWarnings("unused") private final Kind kind;
-        @Def({REG}) protected AllocatableValue result;
+    public abstract static class MemOp extends HSAILLIRInstruction {
+
+        protected final Kind kind;
         @Use({COMPOSITE}) protected HSAILAddressValue address;
         @State protected LIRFrameState state;
 
-        public LoadOp(Kind kind, AllocatableValue result, HSAILAddressValue address, LIRFrameState state) {
+        public MemOp(Kind kind, HSAILAddressValue address, LIRFrameState state) {
             this.kind = kind;
-            this.result = result;
             this.address = address;
             this.state = state;
         }
 
+        protected abstract void emitMemAccess(HSAILAssembler masm);
+
         @Override
         public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
+            if (state != null) {
+                // tasm.recordImplicitException(masm.codeBuffer.position(), state);
+                throw new InternalError("NYI");
+            }
+            emitMemAccess(masm);
+        }
+    }
+
+    public static class LoadOp extends MemOp {
+
+        @Def({REG}) protected AllocatableValue result;
+
+        public LoadOp(Kind kind, AllocatableValue result, HSAILAddressValue address, LIRFrameState state) {
+            super(kind, address, state);
+            this.result = result;
+        }
+
+        @Override
+        public void emitMemAccess(HSAILAssembler masm) {
             HSAILAddress addr = address.toAddress();
             masm.emitLoad(result, addr);
         }
     }
 
-    public static class StoreOp extends HSAILLIRInstruction {
+    public static class StoreOp extends MemOp {
 
-        @SuppressWarnings("unused") private final Kind kind;
-        @Use({COMPOSITE}) protected HSAILAddressValue address;
         @Use({REG}) protected AllocatableValue input;
-        @State protected LIRFrameState state;
 
         public StoreOp(Kind kind, HSAILAddressValue address, AllocatableValue input, LIRFrameState state) {
-            this.kind = kind;
-            this.address = address;
+            super(kind, address, state);
             this.input = input;
-            this.state = state;
         }
 
         @Override
-        public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
+        public void emitMemAccess(HSAILAssembler masm) {
             assert isRegister(input);
             HSAILAddress addr = address.toAddress();
             masm.emitStore(input, addr);
         }
     }
 
+    public static class LoadCompressedPointer extends LoadOp {
+
+        private long narrowOopBase;
+        private int narrowOopShift;
+        private int logMinObjAlignment;
+        @Temp({REG}) private AllocatableValue scratch;
+
+        public LoadCompressedPointer(Kind kind, AllocatableValue result, AllocatableValue scratch, HSAILAddressValue address, LIRFrameState state, long narrowOopBase, int narrowOopShift,
+                        int logMinObjAlignment) {
+            super(kind, result, address, state);
+            this.narrowOopBase = narrowOopBase;
+            this.narrowOopShift = narrowOopShift;
+            this.logMinObjAlignment = logMinObjAlignment;
+            this.scratch = scratch;
+            assert kind == Kind.Object;
+        }
+
+        @Override
+        public void emitMemAccess(HSAILAssembler masm) {
+            // we will do a 32 bit load, zero extending into a 64 bit register
+            masm.emitLoad(result, address.toAddress(), "u32");
+            decodePointer(masm, result, narrowOopBase, narrowOopShift, logMinObjAlignment);
+        }
+    }
+
+    public static class StoreCompressedPointer extends HSAILLIRInstruction {
+
+        protected final Kind kind;
+        private long narrowOopBase;
+        private int narrowOopShift;
+        private int logMinObjAlignment;
+        @Temp({REG}) private AllocatableValue scratch;
+        @Alive({REG}) protected AllocatableValue input;
+        @Alive({COMPOSITE}) protected HSAILAddressValue address;
+        @State protected LIRFrameState state;
+
+        public StoreCompressedPointer(Kind kind, HSAILAddressValue address, AllocatableValue input, AllocatableValue scratch, LIRFrameState state, long narrowOopBase, int narrowOopShift,
+                        int logMinObjAlignment) {
+            this.narrowOopBase = narrowOopBase;
+            this.narrowOopShift = narrowOopShift;
+            this.logMinObjAlignment = logMinObjAlignment;
+            this.scratch = scratch;
+            this.kind = kind;
+            this.address = address;
+            this.state = state;
+            this.input = input;
+            assert kind == Kind.Object;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) {
+            masm.emitMov(scratch, input);
+            encodePointer(masm, scratch, narrowOopBase, narrowOopShift, logMinObjAlignment);
+            if (state != null) {
+                throw new InternalError("NYI");
+                // tasm.recordImplicitException(masm.codeBuffer.position(), state);
+            }
+            masm.emitStore(scratch, address.toAddress(), "u32");
+        }
+    }
+
+    private static void encodePointer(HSAILAssembler masm, Value scratch, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+        if (narrowOopBase == 0 && narrowOopShift == 0) {
+            return;
+        }
+        if (narrowOopShift != 0) {
+            assert logMinObjAlignment == narrowOopShift : "Encode algorithm is wrong";
+        }
+        masm.emitCompressedOopEncode(scratch, narrowOopBase, narrowOopShift);
+    }
+
+    private static void decodePointer(HSAILAssembler masm, Value result, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+        if (narrowOopBase == 0 && narrowOopShift == 0) {
+            return;
+        }
+        if (narrowOopShift != 0) {
+            assert logMinObjAlignment == narrowOopShift : "Decode algorithm is wrong";
+        }
+        masm.emitCompressedOopDecode(result, narrowOopBase, narrowOopShift);
+    }
+
+
+
     public static class LeaOp extends HSAILLIRInstruction {
 
         @Def({REG}) protected AllocatableValue result;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -34,7 +34,7 @@
  * 
  * A GuardedValueNode will only go away if its guard is null or {@link StructuredGraph#start()}.
  */
-public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable {
+public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable, ValueProxy {
 
     @Input private ValueNode object;
 
@@ -81,4 +81,9 @@
         }
         return this;
     }
+
+    @Override
+    public ValueNode getOriginalValue() {
+        return object;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -34,7 +34,7 @@
  * A node that changes the stamp of its input based on some condition being true.
  */
 @NodeInfo(nameTemplate = "GuardingPi(!={p#negated}) {p#reason/s}")
-public class GuardingPiNode extends FixedWithNextNode implements Lowerable, GuardingNode, Canonicalizable {
+public class GuardingPiNode extends FixedWithNextNode implements Lowerable, GuardingNode, Canonicalizable, ValueProxy {
 
     @Input private ValueNode object;
     @Input private LogicNode condition;
@@ -109,4 +109,9 @@
     public ValueNode asNode() {
         return this;
     }
+
+    @Override
+    public ValueNode getOriginalValue() {
+        return object;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -36,7 +36,7 @@
  * is as narrow or narrower than the PiNode's type. The PiNode, and therefore also the scheduling
  * restriction enforced by the anchor, will go away.
  */
-public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable {
+public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable, ValueProxy {
 
     @Input private ValueNode object;
 
@@ -82,4 +82,9 @@
         }
         return this;
     }
+
+    @Override
+    public ValueNode getOriginalValue() {
+        return object;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -27,7 +27,6 @@
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A value proxy that is inserted in the frame state of a loop exit for any value that is created
@@ -35,7 +34,7 @@
  * loop.
  */
 @NodeInfo(nameTemplate = "{p#type/s}Proxy")
-public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable {
+public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy {
 
     @Input(notDataflow = true) private AbstractBeginNode proxyPoint;
     @Input private ValueNode value;
@@ -60,11 +59,6 @@
         return updateStamp(value.stamp());
     }
 
-    @Override
-    public Stamp stamp() {
-        return value().stamp();
-    }
-
     public AbstractBeginNode proxyPoint() {
         return proxyPoint;
     }
@@ -116,4 +110,8 @@
         return graph.unique(new ProxyNode(value, exit, PhiType.Memory, location));
     }
 
+    @Override
+    public ValueNode getOriginalValue() {
+        return value;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -27,12 +27,11 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A node that attaches a type profile to a proxied input node.
  */
-public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType {
+public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, ValueProxy {
 
     @Input private ValueNode object;
     private final JavaTypeProfile profile;
@@ -67,12 +66,7 @@
 
     @Override
     public boolean inferStamp() {
-        return object.inferStamp();
-    }
-
-    @Override
-    public Stamp stamp() {
-        return object.stamp();
+        return updateStamp(object.stamp());
     }
 
     @Override
@@ -130,4 +124,9 @@
         }
         assert graph.getNodes(TypeProfileProxyNode.class).count() == 0;
     }
+
+    @Override
+    public ValueNode getOriginalValue() {
+        return object;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -44,7 +44,7 @@
         this.stamp = stamp;
     }
 
-    public Stamp stamp() {
+    public final Stamp stamp() {
         return stamp;
     }
 
@@ -80,7 +80,7 @@
         return false;
     }
 
-    public Kind kind() {
+    public final Kind kind() {
         return stamp().kind();
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -54,4 +54,10 @@
      * Return true if the written array is an object array, false if it is a primitive array.
      */
     public abstract boolean isObjectArray();
+
+    /**
+     * If {@link #isInitialized()} is true, the memory location contains a valid value. If
+     * {@link #isInitialized()} is false, the memory location is uninitialized or zero.
+     */
+    public abstract boolean isInitialized();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -37,6 +37,7 @@
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
+    private final boolean initialized;
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -56,9 +57,22 @@
         return value;
     }
 
+    /**
+     * If {@link #isInitialized()} is true, the memory location contains a valid value. If
+     * {@link #isInitialized()} is false, the memory location is uninitialized or zero.
+     */
+    public boolean isInitialized() {
+        return initialized;
+    }
+
     public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType, boolean compress) {
+        this(object, value, location, barrierType, compress, true);
+    }
+
+    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType, boolean compress, boolean initialized) {
         super(object, location, StampFactory.forVoid(), barrierType, compress);
         this.value = value;
+        this.initialized = initialized;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Jul 15 17:58:17 2013 -0700
@@ -25,7 +25,9 @@
 import static com.oracle.graal.api.code.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -35,7 +37,7 @@
 /**
  * Implements a type check against a compile-time known type.
  */
-public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType, Virtualizable {
+public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType, Virtualizable, ValueProxy {
 
     @Input private ValueNode object;
     private final ResolvedJavaType type;
@@ -66,6 +68,10 @@
         return forStoreCheck;
     }
 
+    // TODO (ds) remove once performance regression in compiler.sunflow (and other benchmarks)
+    // caused by new lowering is fixed
+    private static final boolean useNewLowering = true; // Boolean.getBoolean("graal.checkcast.useNewLowering");
+
     /**
      * Lowers a {@link CheckCastNode} to a {@link GuardingPiNode}. That is:
      * 
@@ -94,20 +100,31 @@
      */
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile));
-        Stamp stamp = StampFactory.declared(type).join(object.stamp());
-        ValueNode condition;
-        if (stamp == null) {
-            // This is a check cast that will always fail
-            condition = LogicConstantNode.contradiction(graph());
-            stamp = StampFactory.declared(type);
-        } else if (object.stamp().nonNull()) {
-            condition = typeTest;
+        if (useNewLowering) {
+            InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile));
+            Stamp stamp = StampFactory.declared(type).join(object.stamp());
+            ValueNode condition;
+            if (stamp == null) {
+                // This is a check cast that will always fail
+                condition = LogicConstantNode.contradiction(graph());
+                stamp = StampFactory.declared(type);
+            } else if (object.stamp().nonNull()) {
+                condition = typeTest;
+            } else {
+                if (profile != null && profile.getNullSeen() == TriState.FALSE) {
+                    FixedGuardNode nullGuard = graph().add(new FixedGuardNode(graph().unique(new IsNullNode(object)), UnreachedCode, DeoptimizationAction.InvalidateReprofile, true));
+                    graph().addBeforeFixed(this, nullGuard);
+                    condition = typeTest;
+                    stamp = stamp.join(StampFactory.objectNonNull());
+                } else {
+                    condition = graph().unique(new LogicDisjunctionNode(graph().unique(new IsNullNode(object)), typeTest));
+                }
+            }
+            GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp));
+            graph().replaceFixedWithFixed(this, checkedObject);
         } else {
-            condition = graph().unique(new LogicDisjunctionNode(graph().unique(new IsNullNode(object)), typeTest));
+            tool.getRuntime().lower(this, tool);
         }
-        GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp));
-        graph().replaceFixedWithFixed(this, checkedObject);
     }
 
     @Override
@@ -176,4 +193,9 @@
             }
         }
     }
+
+    @Override
+    public ValueNode getOriginalValue() {
+        return object;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ValueProxy.java	Mon Jul 15 17:58:17 2013 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.spi;
+
+import com.oracle.graal.nodes.*;
+
+public interface ValueProxy {
+
+    ValueNode getOriginalValue();
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Mon Jul 15 17:58:17 2013 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 
 public class GraphUtil {
 
@@ -257,14 +258,6 @@
         return null;
     }
 
-    public static ValueNode unProxify(ValueNode proxy) {
-        ValueNode v = proxy;
-        while (v instanceof ProxyNode) {
-            v = ((ProxyNode) v).value();
-        }
-        return v;
-    }
-
     /**
      * Returns a string representation of the given collection of objects.
      * 
@@ -285,16 +278,31 @@
     }
 
     /**
+     * Gets the original value by iterating through all {@link ValueProxy ValueProxies}.
+     * 
+     * @param value The start value.
+     * @return The first non-proxy value encountered.
+     */
+    public static ValueNode unproxify(ValueNode value) {
+        ValueNode result = value;
+        while (result instanceof ValueProxy) {
+            result = ((ValueProxy) result).getOriginalValue();
+        }
+        return result;
+    }
+
+    /**
      * Tries to find an original value of the given node by traversing through proxies and
-     * unambiguous phis.
+     * unambiguous phis. Note that this method will perform an exhaustive search through phis. It is
+     * intended to be used during graph building, when phi nodes aren't yet canonicalized.
      * 
      * @param proxy The node whose original value should be determined.
      */
     public static ValueNode originalValue(ValueNode proxy) {
         ValueNode v = proxy;
         do {
-            if (v instanceof ProxyNode) {
-                v = ((ProxyNode) v).value();
+            if (v instanceof ValueProxy) {
+                v = ((ValueProxy) v).getOriginalValue();
             } else if (v instanceof PhiNode) {
                 v = ((PhiNode) v).singleValue();
             } else {
@@ -308,8 +316,8 @@
             NodeWorkList worklist = proxy.graph().createNodeWorkList();
             worklist.add(proxy);
             for (Node node : worklist) {
-                if (node instanceof ProxyNode) {
-                    worklist.add(((ProxyNode) node).value());
+                if (node instanceof ValueProxy) {
+                    worklist.add(((ValueProxy) node).getOriginalValue());
                 } else if (node instanceof PhiNode) {
                     worklist.addAll(((PhiNode) node).values());
                 } else {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Jul 15 17:58:17 2013 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.phases.common;
 
+import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -33,6 +34,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
@@ -193,16 +195,16 @@
         }
 
         public ResolvedJavaType getNodeType(ValueNode node) {
-            ResolvedJavaType result = knownTypes.get(node);
+            ResolvedJavaType result = knownTypes.get(GraphUtil.unproxify(node));
             return result == null ? node.objectStamp().type() : result;
         }
 
         public boolean isNull(ValueNode value) {
-            return value.objectStamp().alwaysNull() || knownNull.contains(value);
+            return value.objectStamp().alwaysNull() || knownNull.contains(GraphUtil.unproxify(value));
         }
 
         public boolean isNonNull(ValueNode value) {
-            return value.objectStamp().nonNull() || knownNonNull.contains(value);
+            return value.objectStamp().nonNull() || knownNonNull.contains(GraphUtil.unproxify(value));
         }
 
         @Override
@@ -245,25 +247,27 @@
          * to be null, otherwise the value is known to be non-null.
          */
         public void addNullness(boolean isNull, ValueNode value) {
+            ValueNode original = GraphUtil.unproxify(value);
             if (isNull) {
-                if (!isNull(value)) {
+                if (!isNull(original)) {
                     metricNullnessRegistered.increment();
-                    knownNull.add(value);
+                    knownNull.add(original);
                 }
             } else {
-                if (!isNonNull(value)) {
+                if (!isNonNull(original)) {
                     metricNullnessRegistered.increment();
-                    knownNonNull.add(value);
+                    knownNonNull.add(original);
                 }
             }
         }
 
         public void addType(ResolvedJavaType type, ValueNode value) {
-            ResolvedJavaType knownType = getNodeType(value);
+            ValueNode original = GraphUtil.unproxify(value);
+            ResolvedJavaType knownType = getNodeType(original);
             ResolvedJavaType newType = tighten(type, knownType);
 
             if (newType != knownType) {
-                knownTypes.put(value, newType);
+                knownTypes.put(original, newType);
                 metricTypeRegistered.increment();
             }
         }
@@ -315,42 +319,48 @@
         }
 
         private void registerCondition(boolean isTrue, LogicNode condition, ValueNode anchor) {
-            state.addCondition(isTrue, condition, anchor);
+            if (!isTrue && condition instanceof LogicDisjunctionNode) {
+                LogicDisjunctionNode disjunction = (LogicDisjunctionNode) condition;
+                registerCondition(disjunction.isXNegated(), disjunction.getX(), anchor);
+                registerCondition(disjunction.isYNegated(), disjunction.getY(), anchor);
+            } else {
+                state.addCondition(isTrue, condition, anchor);
 
-            if (isTrue && condition instanceof InstanceOfNode) {
-                InstanceOfNode instanceOf = (InstanceOfNode) condition;
-                ValueNode object = instanceOf.object();
-                state.addNullness(false, object);
-                state.addType(instanceOf.type(), object);
-            } else if (condition instanceof IsNullNode) {
-                IsNullNode nullCheck = (IsNullNode) condition;
-                state.addNullness(isTrue, nullCheck.object());
-            } else if (condition instanceof ObjectEqualsNode) {
-                ObjectEqualsNode equals = (ObjectEqualsNode) condition;
-                ValueNode x = equals.x();
-                ValueNode y = equals.y();
-                if (isTrue) {
-                    if (state.isNull(x) && !state.isNull(y)) {
-                        metricObjectEqualsRegistered.increment();
-                        state.addNullness(true, y);
-                    } else if (!state.isNull(x) && state.isNull(y)) {
-                        metricObjectEqualsRegistered.increment();
-                        state.addNullness(true, x);
-                    }
-                    if (state.isNonNull(x) && !state.isNonNull(y)) {
-                        metricObjectEqualsRegistered.increment();
-                        state.addNullness(false, y);
-                    } else if (!state.isNonNull(x) && state.isNonNull(y)) {
-                        metricObjectEqualsRegistered.increment();
-                        state.addNullness(false, x);
-                    }
-                } else {
-                    if (state.isNull(x) && !state.isNonNull(y)) {
-                        metricObjectEqualsRegistered.increment();
-                        state.addNullness(true, y);
-                    } else if (!state.isNonNull(x) && state.isNull(y)) {
-                        metricObjectEqualsRegistered.increment();
-                        state.addNullness(true, x);
+                if (isTrue && condition instanceof InstanceOfNode) {
+                    InstanceOfNode instanceOf = (InstanceOfNode) condition;
+                    ValueNode object = instanceOf.object();
+                    state.addNullness(false, object);
+                    state.addType(instanceOf.type(), object);
+                } else if (condition instanceof IsNullNode) {
+                    IsNullNode nullCheck = (IsNullNode) condition;
+                    state.addNullness(isTrue, nullCheck.object());
+                } else if (condition instanceof ObjectEqualsNode) {
+                    ObjectEqualsNode equals = (ObjectEqualsNode) condition;
+                    ValueNode x = equals.x();
+                    ValueNode y = equals.y();
+                    if (isTrue) {
+                        if (state.isNull(x) && !state.isNull(y)) {
+                            metricObjectEqualsRegistered.increment();
+                            state.addNullness(true, y);
+                        } else if (!state.isNull(x) && state.isNull(y)) {
+                            metricObjectEqualsRegistered.increment();
+                            state.addNullness(true, x);
+                        }
+                        if (state.isNonNull(x) && !state.isNonNull(y)) {
+                            metricObjectEqualsRegistered.increment();
+                            state.addNullness(false, y);
+                        } else if (!state.isNonNull(x) && state.isNonNull(y)) {
+                            metricObjectEqualsRegistered.increment();
+                            state.addNullness(false, x);
+                        }
+                    } else {
+                        if (state.isNull(x) && !state.isNonNull(y)) {
+                            metricObjectEqualsRegistered.increment();
+                            state.addNullness(false, y);
+                        } else if (!state.isNonNull(x) && state.isNull(y)) {
+                            metricObjectEqualsRegistered.increment();
+                            state.addNullness(false, x);
+                        }
                     }
                 }
             }
@@ -569,6 +579,25 @@
                         }
                     }
                 }
+            } else if (node instanceof Invoke) {
+                Invoke invoke = (Invoke) node;
+                if (invoke.callTarget() instanceof MethodCallTargetNode) {
+                    MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
+                    ValueNode receiver = callTarget.receiver();
+                    if (receiver != null && (callTarget.invokeKind() == InvokeKind.Interface || callTarget.invokeKind() == InvokeKind.Virtual)) {
+                        ResolvedJavaType type = state.getNodeType(receiver);
+                        if (type != receiver.objectStamp().type()) {
+                            ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod());
+                            if (method != null) {
+                                if ((method.getModifiers() & Modifier.FINAL) != 0 || (type.getModifiers() & Modifier.FINAL) != 0) {
+                                    callTarget.setInvokeKind(InvokeKind.Special);
+                                    callTarget.setTargetMethod(method);
+                                }
+                            }
+                        }
+                    }
+                }
+
             }
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Jul 15 17:58:17 2013 -0700
@@ -448,6 +448,10 @@
 
         @Override
         public boolean isWorthInlining(InlineInfo info, int inliningDepth, double probability, double relevance, boolean fullyProcessed) {
+            if (InlineEverything.getValue()) {
+                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
+            }
+
             if (isIntrinsic(info)) {
                 return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
             }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Jul 15 17:58:17 2013 -0700
@@ -63,6 +63,8 @@
     public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300);
     @Option(help = "")
     public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0);
+    @Option(help = "")
+    public static final OptionValue<Boolean> InlineEverything = new OptionValue<>(false);
 
     // escape analysis settings
     @Option(help = "")
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Mon Jul 15 17:58:17 2013 -0700
@@ -65,8 +65,7 @@
         if (truffleCompiler == null) {
             truffleCompiler = new TruffleCompilerImpl();
         }
-        return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleCompilationThreshold.getValue(), TruffleInliningReprofileCount.getValue(),
-                        TruffleInvalidationReprofileCount.getValue());
+        return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleCompilationThreshold.getValue());
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Jul 15 17:58:17 2013 -0700
@@ -40,19 +40,19 @@
 public final class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, FrameFactory {
 
     private static final PrintStream OUT = TTY.out().out();
+    private static final int MIN_INVOKES_AFTER_INLINING = 2;
 
-    private final int inliningReprofileCount;
-    private final int invalidationReprofileCount;
-
-    protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int compilationThreshold, int inliningReprofileCount, int invalidationReprofileCount) {
+    protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int compilationThreshold) {
         super(rootNode, descriptor);
         this.compiler = compiler;
         this.invokeCounter = compilationThreshold >> 7;
         this.loopAndInvokeCounter = compilationThreshold;
         this.originalInvokeCounter = compilationThreshold;
         this.rootNode.setCallTarget(this);
-        this.inliningReprofileCount = inliningReprofileCount;
-        this.invalidationReprofileCount = invalidationReprofileCount;
+
+        if (TruffleProfiling.getValue()) {
+            registerCallTarget(this);
+        }
     }
 
     private InstalledCode compiledMethod;
@@ -62,6 +62,11 @@
     private int loopAndInvokeCounter;
     private boolean disableCompilation;
 
+    // TruffleProfiling
+    private int callCount;
+    private int inlinedCallSiteCount;
+
+    // TraceTruffleCompilation
     long timeCompilationStarted;
     long timePartialEvaluationFinished;
     long timeCompilationFinished;
@@ -71,6 +76,9 @@
 
     @Override
     public Object call(PackedFrame caller, Arguments args) {
+        if (TruffleProfiling.getValue()) {
+            callCount++;
+        }
         if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, compiledMethod != null)) {
             try {
                 return compiledMethod.execute(this, caller, args);
@@ -82,8 +90,9 @@
         }
     }
 
-    protected Object compiledCodeInvalidated(PackedFrame caller, Arguments args) {
+    private Object compiledCodeInvalidated(PackedFrame caller, Arguments args) {
         compiledMethod = null;
+        int invalidationReprofileCount = TruffleInvalidationReprofileCount.getValue();
         invokeCounter = invalidationReprofileCount;
         if (TruffleFunctionInlining.getValue()) {
             originalInvokeCounter += invalidationReprofileCount;
@@ -101,7 +110,8 @@
             return executeHelper(caller, args);
         } else {
             if (TruffleFunctionInlining.getValue() && inline()) {
-                invokeCounter = 2;
+                invokeCounter = MIN_INVOKES_AFTER_INLINING;
+                int inliningReprofileCount = TruffleInliningReprofileCount.getValue();
                 loopAndInvokeCounter = inliningReprofileCount;
                 originalInvokeCounter = inliningReprofileCount;
             } else {
@@ -112,10 +122,12 @@
     }
 
     public boolean inline() {
+        CompilerAsserts.neverPartOfCompilation();
         return new InliningHelper(this).inline();
     }
 
     public void compile() {
+        CompilerAsserts.neverPartOfCompilation();
         try {
             compiledMethod = compiler.compile(this);
             if (compiledMethod == null) {
@@ -127,6 +139,9 @@
                                     (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6,
                                     (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, codeSize);
                 }
+                if (TruffleProfiling.getValue()) {
+                    resetProfiling();
+                }
             }
         } catch (Throwable e) {
             disableCompilation = true;
@@ -202,10 +217,14 @@
 
             boolean inlined = false;
             for (InlinableCallSiteInfo inlinableCallSite : inlinableCallSites) {
-                if (policy.isWorthInlining(inlinableCallSite) && inlinableCallSite.getCallSite().inline(target)) {
+                if (!policy.isWorthInlining(inlinableCallSite)) {
+                    break;
+                }
+                if (inlinableCallSite.getCallSite().inline(target)) {
                     if (TraceTruffleInlining.getValue()) {
                         printCallSiteInfo(policy, inlinableCallSite, "inlined");
                     }
+                    target.inlinedCallSiteCount++;
                     inlined = true;
                     break;
                 }
@@ -267,7 +286,11 @@
 
                     @Override
                     public int compare(InlinableCallSiteInfo cs1, InlinableCallSiteInfo cs2) {
-                        return Double.compare(metric(cs2), metric(cs1));
+                        int result = (isWorthInlining(cs2) ? 1 : 0) - (isWorthInlining(cs1) ? 1 : 0);
+                        if (result == 0) {
+                            return Double.compare(metric(cs2), metric(cs1));
+                        }
+                        return result;
                     }
                 });
             }
@@ -313,4 +336,65 @@
             return inlinableCallSites;
         }
     }
+
+    private static void resetProfiling() {
+        for (OptimizedCallTarget callTarget : OptimizedCallTarget.callTargets.keySet()) {
+            callTarget.callCount = 0;
+        }
+    }
+
+    private static void printProfiling() {
+        List<OptimizedCallTarget> sortedCallTargets = new ArrayList<>(OptimizedCallTarget.callTargets.keySet());
+        Collections.sort(sortedCallTargets, new Comparator<OptimizedCallTarget>() {
+
+            @Override
+            public int compare(OptimizedCallTarget o1, OptimizedCallTarget o2) {
+                return o2.callCount - o1.callCount;
+            }
+        });
+
+        int totalCallCount = 0;
+        int totalInlinedCallSiteCount = 0;
+        int totalNotInlinedCallSiteCount = 0;
+        int totalNodeCount = 0;
+
+        PrintStream out = TTY.out().out();
+        out.println();
+        out.printf("%-50s | %-10s | %s / %s | %s\n", "Call Target", "Call Count", "Calls Sites Inlined", "Not Inlined", "Node Count");
+        for (OptimizedCallTarget callTarget : sortedCallTargets) {
+            if (callTarget.callCount == 0) {
+                continue;
+            }
+
+            int notInlinedCallSiteCount = InliningHelper.getInlinableCallSites(callTarget).size();
+            int nodeCount = NodeUtil.countNodes(callTarget.rootNode);
+            String comment = callTarget.compiledMethod == null ? " int" : "";
+            out.printf("%-50s | %10s | %15s | %15s | %10s%s\n", callTarget.getRootNode(), callTarget.callCount, callTarget.inlinedCallSiteCount, notInlinedCallSiteCount, nodeCount, comment);
+
+            totalCallCount += callTarget.callCount;
+            totalInlinedCallSiteCount += callTarget.inlinedCallSiteCount;
+            totalNotInlinedCallSiteCount += notInlinedCallSiteCount;
+            totalNodeCount += nodeCount;
+        }
+        out.printf("%-50s | %10s | %15s | %15s | %10s\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNotInlinedCallSiteCount, totalNodeCount);
+    }
+
+    private static void registerCallTarget(OptimizedCallTarget callTarget) {
+        callTargets.put(callTarget, 0);
+    }
+
+    private static Map<OptimizedCallTarget, Integer> callTargets;
+    static {
+        if (TruffleProfiling.getValue()) {
+            callTargets = new WeakHashMap<>();
+
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+
+                @Override
+                public void run() {
+                    printProfiling();
+                }
+            });
+        }
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Jul 15 17:58:17 2013 -0700
@@ -64,7 +64,7 @@
     private final HotSpotGraalRuntime graalRuntime;
     private final TruffleCache truffleCache;
 
-    private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class};
+    private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class, InvalidInstalledCodeException.class};
 
     public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability,
                     OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Jul 15 17:58:17 2013 -0700
@@ -81,5 +81,7 @@
     public static final OptionValue<Boolean> TraceTruffleInlining = new OptionValue<>(true);
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleInliningDetails = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TruffleProfiling = new StableOptionValue<>(false);
     // @formatter:on
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationPEClosure.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationPEClosure.java	Mon Jul 15 17:58:17 2013 -0700
@@ -34,6 +34,7 @@
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationPEBlockState.ReadCacheEntry;
 
@@ -54,24 +55,26 @@
         if (!deleted) {
             if (node instanceof LoadFieldNode) {
                 LoadFieldNode load = (LoadFieldNode) node;
-                ValueNode cachedValue = state.getReadCache(load.object(), load.field());
+                ValueNode object = GraphUtil.unproxify(load.object());
+                ValueNode cachedValue = state.getReadCache(object, load.field());
                 if (cachedValue != null) {
                     effects.replaceAtUsages(load, cachedValue);
                     state.addScalarAlias(load, cachedValue);
+                    deleted = true;
                 } else {
-                    state.addReadCache(load.object(), load.field(), load);
+                    state.addReadCache(object, load.field(), load);
                 }
-                deleted = true;
             } else if (node instanceof StoreFieldNode) {
                 StoreFieldNode store = (StoreFieldNode) node;
-                ValueNode cachedValue = state.getReadCache(store.object(), store.field());
+                ValueNode object = GraphUtil.unproxify(store.object());
+                ValueNode cachedValue = state.getReadCache(object, store.field());
 
                 if (state.getScalarAlias(store.value()) == cachedValue) {
                     effects.deleteFixedNode(store);
                     deleted = true;
                 }
                 state.killReadCache(store.field());
-                state.addReadCache(store.object(), store.field(), store.value());
+                state.addReadCache(object, store.field(), store.value());
             } else if (node instanceof MemoryCheckpoint.Single) {
                 METRIC_MEMORYCHECKOINT.increment();
                 LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Mon Jul 15 17:58:17 2013 -0700
@@ -365,6 +365,20 @@
     void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
 
     /**
+     * Initializes the memory at address {@code (this + offset)}. Both the base address and offset
+     * are in bytes. The memory must be uninitialized or zero prior to this operation.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void initializeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
+
+    /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
@@ -459,6 +473,16 @@
     void writeWord(int offset, WordBase val, LocationIdentity locationIdentity);
 
     /**
+     * Initializes the memory at address {@code (this + offset)}. Both the base address and offset
+     * are in bytes. The memory must be uninitialized or zero prior to this operation.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void initializeWord(int offset, WordBase val, LocationIdentity locationIdentity);
+
+    /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Mon Jul 15 17:58:17 2013 -0700
@@ -61,6 +61,7 @@
          READ,
          READ_COMPRESSED,
          WRITE,
+         INITIALIZE,
          ZERO,
          FROM_UNSIGNED,
          FROM_SIGNED,
@@ -758,6 +759,12 @@
     }
 
     @Override
+    @Operation(opcode = Opcode.INITIALIZE)
+    public void initializeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity) {
+        unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
+    }
+
+    @Override
     @Operation(opcode = Opcode.WRITE)
     public native void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
 
@@ -810,6 +817,12 @@
     }
 
     @Override
+    @Operation(opcode = Opcode.INITIALIZE)
+    public void initializeWord(int offset, WordBase val, LocationIdentity locationIdentity) {
+        initializeWord(signed(offset), val, locationIdentity);
+    }
+
+    @Override
     @Operation(opcode = Opcode.WRITE)
     public void writeObject(int offset, Object val, LocationIdentity locationIdentity) {
         writeObject(signed(offset), val, locationIdentity);
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Jul 15 17:58:17 2013 -0700
@@ -38,6 +38,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.word.*;
+import com.oracle.graal.word.Word.Opcode;
 import com.oracle.graal.word.Word.Operation;
 
 /**
@@ -69,15 +70,20 @@
     @Override
     protected void run(StructuredGraph graph) {
         for (Node n : GraphOrder.forwardGraph(graph)) {
-            if (n instanceof ValueNode) {
+            if (n instanceof ValueNode && !(n instanceof PhiNode && ((PhiNode) n).isLoopPhi())) {
                 ValueNode valueNode = (ValueNode) n;
                 if (isWord(valueNode)) {
                     changeToWord(valueNode);
                 }
             }
         }
+        for (PhiNode phi : graph.getNodes(PhiNode.class)) {
+            if (phi.isLoopPhi() && isWord(phi)) {
+                changeToWord(phi);
+            }
+        }
 
-        // Remove casts between different word types (which are by now no longer have kind Object)
+        // Remove casts between different word types (which by now no longer have kind Object)
         for (CheckCastNode checkCastNode : graph.getNodes().filter(CheckCastNode.class).snapshot()) {
             if (!checkCastNode.isDeleted() && checkCastNode.kind() == wordKind) {
                 checkCastNode.replaceAtUsages(checkCastNode.object());
@@ -184,7 +190,8 @@
                         replace(invoke, readOp(graph, arguments.get(0), invoke, location, true));
                         break;
                     }
-                    case WRITE: {
+                    case WRITE:
+                    case INITIALIZE: {
                         assert arguments.size() == 3 || arguments.size() == 4;
                         Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass()));
                         LocationNode location;
@@ -193,7 +200,7 @@
                         } else {
                             location = makeLocation(graph, arguments.get(1), writeKind, arguments.get(3));
                         }
-                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(2), invoke, location));
+                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(2), invoke, location, operation.opcode()));
                         break;
                     }
                     case ZERO:
@@ -330,8 +337,9 @@
         return read;
     }
 
-    private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location) {
-        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE, false));
+    private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location, Opcode op) {
+        assert op == Opcode.WRITE || op == Opcode.INITIALIZE;
+        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE, false, op == Opcode.WRITE));
         write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.asNode(), write);
         return write;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Mon Jul 15 17:58:17 2013 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
+import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Node1Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeInfo.Kind;
+
+public class PolymorphicTest2 {
+
+    @Test
+    public void testMultipleTypes() {
+        /* Tests the unexpected polymorphic case. */
+        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
+        assertEquals(21, executeWith(node, false, false));
+        assertEquals(42, executeWith(node, 21, 21));
+        assertEquals("(boolean,int)", executeWith(node, false, 42));
+        assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+    }
+
+    @SuppressWarnings("unused")
+    @PolymorphicLimit(3)
+    abstract static class Node1 extends BinaryNode {
+
+        @Specialization(order = 1)
+        int add(int left, int right) {
+            return 42;
+        }
+
+        @Specialization(order = 2)
+        int add(boolean left, boolean right) {
+            return 21;
+        }
+
+        @Specialization(order = 4)
+        String add(boolean left, int right) {
+            return "(boolean,int)";
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Mon Jul 15 17:58:17 2013 -0700
@@ -81,7 +81,7 @@
 
     class TestRootNode extends RootNode {
 
-        @Children private ValueNode[] children;
+        @Children private final ValueNode[] children;
 
         public TestRootNode(ValueNode[] children) {
             this.children = adoptChildren(children);
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Jul 15 17:58:17 2013 -0700
@@ -163,9 +163,11 @@
                 } else if (Node.class.isAssignableFrom(field.getType()) && field.getAnnotation(Child.class) != null) {
                     kind = NodeFieldKind.CHILD;
                     childOffsetsList.add(fieldOffsetProvider.objectFieldOffset(field));
+                    assert !Modifier.isFinal(field.getModifiers()) : "child field must not be final (\"" + field.getName() + "\", " + clazz + ")";
                 } else if (field.getType().isArray() && Node.class.isAssignableFrom(field.getType().getComponentType()) && field.getAnnotation(Children.class) != null) {
                     kind = NodeFieldKind.CHILDREN;
                     childrenOffsetsList.add(fieldOffsetProvider.objectFieldOffset(field));
+                    assert Modifier.isFinal(field.getModifiers()) : "children array field must be final (\"" + field.getName() + "\", " + clazz + ")";
                 } else {
                     kind = NodeFieldKind.DATA;
                 }
@@ -352,24 +354,54 @@
     public static void replaceChild(Node parent, Node oldChild, Node newChild) {
         NodeClass nodeClass = NodeClass.get(parent.getClass());
 
-        for (long fieldOffset : nodeClass.childOffsets) {
+        for (long fieldOffset : nodeClass.getChildOffsets()) {
             if (unsafe.getObject(parent, fieldOffset) == oldChild) {
+                assert assertAssignable(nodeClass, fieldOffset, newChild);
                 unsafe.putObject(parent, fieldOffset, newChild);
             }
         }
-        for (long fieldOffset : nodeClass.childrenOffsets) {
-            Node[] array = (Node[]) unsafe.getObject(parent, fieldOffset);
-            if (array != null) {
+
+        for (long fieldOffset : nodeClass.getChildrenOffsets()) {
+            Object arrayObject = unsafe.getObject(parent, fieldOffset);
+            if (arrayObject != null) {
+                assert arrayObject instanceof Node[] : "Children array must be instanceof Node[] ";
+                Node[] array = (Node[]) arrayObject;
                 for (int i = 0; i < array.length; i++) {
                     if (array[i] == oldChild) {
+                        assert assertAssignable(nodeClass, fieldOffset, newChild);
                         array[i] = newChild;
-                        return;
                     }
                 }
             }
         }
     }
 
+    private static boolean assertAssignable(NodeClass clazz, long fieldOffset, Object newValue) {
+        if (newValue == null) {
+            return true;
+        }
+        for (NodeField field : clazz.getFields()) {
+            if (field.getOffset() == fieldOffset) {
+                if (field.getKind() == NodeFieldKind.CHILD) {
+                    if (field.getType().isAssignableFrom(newValue.getClass())) {
+                        return true;
+                    } else {
+                        assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
+                        return false;
+                    }
+                } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+                    if (field.getType().getComponentType().isAssignableFrom(newValue.getClass())) {
+                        return true;
+                    } else {
+                        assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
+                        return false;
+                    }
+                }
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+
     /** Returns all declared fields in the class hierarchy. */
     private static Field[] getAllFields(Class<? extends Object> clazz) {
         Field[] declaredFields = clazz.getDeclaredFields();
@@ -660,4 +692,5 @@
             p.print("    ");
         }
     }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Fri Jul 12 10:12:06 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon Jul 15 17:58:17 2013 -0700
@@ -32,6 +32,7 @@
 import javax.lang.model.util.*;
 
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.ast.*;
@@ -1226,6 +1227,12 @@
         private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) {
             String name = executeCachedName(polymorph);
             CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name);
+
+            ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
+            boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
+            if (sourceThrowsUnexpected) {
+                cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class));
+            }
             addInternalValueParameters(cachedExecute, polymorph, true, true);
 
             if (polymorph == node.getGenericPolymorphicSpecialization()) {
@@ -2441,11 +2448,18 @@
             }
 
             if (!returnBuilder.isEmpty()) {
-                builder.startReturn();
+
+                ExecutableTypeData sourceExecutableType = node.findExecutableType(specialization.getReturnType().getTypeSystemType(), 0);
+                boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
+                boolean targetSupportsUnexpected = executable.hasUnexpectedValue(getContext());
 
                 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
                 TypeData sourceType = specialization.getReturnType().getTypeSystemType();
 
+                if (specialization.isPolymorphic() && sourceThrowsUnexpected && !targetSupportsUnexpected) {
+                    builder.startTryBlock();
+                }
+                builder.startReturn();
                 if (targetType == null || sourceType == null) {
                     builder.tree(returnBuilder.getRoot());
                 } else if (sourceType.needsCastTo(getContext(), targetType)) {
@@ -2454,6 +2468,19 @@
                     builder.tree(returnBuilder.getRoot());
                 }
                 builder.end();
+                if (specialization.isPolymorphic() && sourceThrowsUnexpected && !targetSupportsUnexpected) {
+                    builder.end();
+                    builder.startCatchBlock(getUnexpectedValueException(), "ex");
+                    builder.startReturn();
+                    CodeTree returns = CodeTreeBuilder.singleString("ex.getResult()");
+                    if (sourceType.needsCastTo(getContext(), targetType)) {
+                        builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), returns));
+                    } else {
+                        builder.tree(returns);
+                    }
+                    builder.end();
+                    builder.end();
+                }
             }
 
             if (!specialization.getExceptions().isEmpty()) {
--- a/src/share/vm/runtime/arguments.cpp	Fri Jul 12 10:12:06 2013 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Mon Jul 15 17:58:17 2013 -0700
@@ -2208,12 +2208,9 @@
 #ifdef GRAAL
   if (UseCompressedKlassPointers) {
     if (IgnoreUnrecognizedVMOptions) {
-      warning("UseCompressedKlassPointers is disabled, because it is not supported by Graal");
-      FLAG_SET_CMDLINE(bool, UseCompressedKlassPointers, false);
+      FLAG_SET_CMDLINE(bool, UseCompressedKlassPointers, true);
     } else {
-      jio_fprintf(defaultStream::error_stream(),
-                    "UseCompressedKlassPointers are not supported in Graal at the moment\n");
-      status = false;
+      status = true;
     }
   } else {
     // This prevents the flag being set to true by set_ergonomics_flags()