changeset 14945:b14cb2d9253d

Make compression and uncompression explicit in the high level graph.
author Roland Schatz <roland.schatz@oracle.com>
date Wed, 02 Apr 2014 15:26:58 +0200
parents 96f8e6b6a81a
children 31ded66cd2cb
files CHANGELOG.md graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java mx/projects
diffstat 35 files changed, 929 insertions(+), 486 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Wed Apr 02 14:43:52 2014 +0200
+++ b/CHANGELOG.md	Wed Apr 02 15:26:58 2014 +0200
@@ -2,6 +2,7 @@
 
 ## `tip`
 ### Graal
+* Explicit support for oop compression/uncompression in high level graph.
 * LIRGenerator refactoring.
 * ...
 
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Wed Apr 02 15:26:58 2014 +0200
@@ -80,11 +80,11 @@
 
     /**
      * Moves an Object into a register.
-     * 
+     *
      * Because Object references become stale after Garbage collection (GC) the technique used here
      * is to load a JNI global reference to that Object into the register. These JNI global
      * references get updated by the GC whenever the GC moves an Object.
-     * 
+     *
      * @param a the destination register
      * @param obj the Object being moved
      */
@@ -112,11 +112,11 @@
 
     }
 
-    public final void emitMov(Value dst, Value src) {
-        if (isRegister(dst) && isConstant(src) && src.getKind().getStackKind() == Kind.Object) {
+    public final void emitMov(Kind kind, Value dst, Value src) {
+        if (isRegister(dst) && isConstant(src) && kind.getStackKind() == Kind.Object) {
             mov(asRegister(dst), (asConstant(src)).asObject());
         } else {
-            String argtype = getArgType(dst).substring(1);
+            String argtype = getArgTypeFromKind(kind).substring(1);
             emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";");
         }
     }
@@ -133,7 +133,7 @@
 
     /**
      * Emits a memory barrier instruction.
-     * 
+     *
      * @param barriers the kind of barrier to emit
      */
     public final void emitMembar(int barriers) {
@@ -189,16 +189,16 @@
         storeImmediateImpl("f64", Double.toString(src), addr);
     }
 
-    public final void emitSpillLoad(Value dest, Value src) {
-        emitString("ld_spill_" + getArgType(dest) + " " + HSAIL.mapRegister(dest) + ", " + mapStackSlot(src, getArgSize(dest)) + ";");
+    public final void emitSpillLoad(Kind kind, Value dest, Value src) {
+        emitString("ld_spill_" + getArgTypeFromKind(kind) + " " + HSAIL.mapRegister(dest) + ", " + mapStackSlot(src, getArgSizeFromKind(kind)) + ";");
     }
 
     public final void emitStore(Value src, HSAILAddress addr) {
         emitString("st_global_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapAddress(addr) + ";");
     }
 
-    public final void emitSpillStore(Value src, Value dest) {
-        int sizestored = getArgSize(src);
+    public final void emitSpillStore(Kind kind, Value src, Value dest) {
+        int sizestored = getArgSizeFromKind(kind);
         if (maxDataTypeSize < sizestored) {
             maxDataTypeSize = sizestored;
         }
@@ -206,7 +206,7 @@
         if (maxStackOffset < stackoffset) {
             maxStackOffset = stackoffset;
         }
-        emitString("st_spill_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSize(src)) + ";");
+        emitString("st_spill_" + getArgTypeFromKind(kind) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSizeFromKind(kind)) + ";");
     }
 
     /**
@@ -226,7 +226,11 @@
     }
 
     public int getArgSize(Value src) {
-        switch (src.getKind()) {
+        return getArgSizeFromKind(src.getKind());
+    }
+
+    private static int getArgSizeFromKind(Kind kind) {
+        switch (kind) {
             case Int:
             case Float:
                 return 32;
@@ -277,7 +281,11 @@
     }
 
     public static final String getArgTypeForceUnsigned(Value src) {
-        switch (src.getKind()) {
+        return getArgTypeForceUnsignedKind(src.getKind());
+    }
+
+    public static final String getArgTypeForceUnsignedKind(Kind kind) {
+        switch (kind) {
             case Int:
                 return "u32";
             case Long:
@@ -296,7 +304,7 @@
 
     /**
      * Emits a compare instruction.
-     * 
+     *
      * @param src0 - the first source register
      * @param src1 - the second source register
      * @param condition - the compare condition i.e., eq, ne, lt, gt
@@ -307,8 +315,9 @@
     public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) {
         // Formulate the prefix of the instruction.
         // if unordered is true, it should be ignored unless the src type is f32 or f64
-        String unorderedPrefix = (getArgType(src1).startsWith("f") && unordered ? "u" : "");
-        String prefix = "cmp_" + condition + unorderedPrefix + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : getArgType(src1));
+        String argType = getArgTypeFromKind(src1.getKind().getStackKind());
+        String unorderedPrefix = (argType.startsWith("f") && unordered ? "u" : "");
+        String prefix = "cmp_" + condition + unorderedPrefix + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : argType);
         // Generate a comment for debugging purposes
         String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) && (asConstant(src1).asObject() == null) ? " // null test " : "");
         // Emit the instruction.
@@ -329,7 +338,7 @@
     /**
      * Emits a convert instruction that uses unsigned prefix, regardless of the type of dest and
      * src.
-     * 
+     *
      * @param dest the destination operand
      * @param src the source operand
      */
@@ -372,7 +381,7 @@
 
     /**
      * Emits an instruction.
-     * 
+     *
      * @param mnemonic the instruction mnemonic
      * @param dest the destination operand
      * @param sources the source operands
@@ -384,20 +393,25 @@
 
     /**
      * Emits an unsigned instruction.
-     * 
+     *
      * @param mnemonic the instruction mnemonic
      * @param dest the destination argument
      * @param sources the source arguments
-     * 
+     *
      */
     public final void emitForceUnsigned(String mnemonic, Value dest, Value... sources) {
         String prefix = getArgTypeForceUnsigned(dest);
         emitTextFormattedInstruction(mnemonic + "_" + prefix, dest, sources);
     }
 
+    public final void emitForceUnsignedKind(String mnemonic, Kind kind, Value dest, Value... sources) {
+        String prefix = getArgTypeForceUnsignedKind(kind);
+        emitTextFormattedInstruction(mnemonic + "_" + prefix, dest, sources);
+    }
+
     /**
      * Emits an instruction for a bitwise logical operation.
-     * 
+     *
      * @param mnemonic the instruction mnemonic
      * @param dest the destination
      * @param sources the source operands
@@ -410,7 +424,7 @@
     /**
      * Central helper routine that emits a text formatted HSAIL instruction via call to
      * AbstractAssembler.emitString. All the emit routines in the assembler end up calling this one.
-     * 
+     *
      * @param instr the full instruction mnenomics including any prefixes
      * @param dest the destination operand
      * @param sources the source operand
@@ -442,7 +456,7 @@
 
     /**
      * Emits a conditional move instruction.
-     * 
+     *
      * @param dest the destination operand storing result of the move
      * @param trueReg the register that should be copied to dest if the condition is true
      * @param falseReg the register that should be copied to dest if the condition is false
@@ -459,7 +473,7 @@
      * shift. The compressed value could represent either a normal oop or a klass ptr. If the
      * compressed value is 0, the uncompressed must also be 0. We only emit this if base and shift
      * are not both zero.
-     * 
+     *
      * @param result the register containing the compressed value on input and the uncompressed ptr
      *            on output
      * @param base the amount to be added to the compressed value
@@ -471,7 +485,7 @@
         assert (!isConstant(result));
         if (base == 0) {
             // we don't have to test for null if shl is the only operation
-            emitForceUnsigned("shl", result, result, Constant.forInt(shift));
+            emitForceUnsignedKind("shl", Kind.Long, result, result, Constant.forInt(shift));
         } else if (shift == 0) {
             // only use add if result is not starting as null (test only if testForNull is true)
             emitWithOptionalTestForNull(testForNull, "add", result, result, Constant.forLong(base));
@@ -486,7 +500,7 @@
      * and shift. The compressed value could represent either a normal oop or a klass ptr. If the
      * ptr is 0, the compressed value must also be 0. We only emit this if base and shift are not
      * both zero.
-     * 
+     *
      * @param result the register containing the 64-bit pointer on input and the compressed value on
      *            output
      * @param base the amount to be subtracted from the 64-bit pointer
@@ -502,7 +516,7 @@
         }
         if (shift != 0) {
             // note that the shr can still be done even if the result is null
-            emitForceUnsigned("shr", result, result, Constant.forInt(shift));
+            emitForceUnsignedKind("shr", Kind.Long, result, result, Constant.forInt(shift));
         }
     }
 
@@ -510,7 +524,7 @@
      * Emits code for the requested mnemonic on the result and sources. In addition, if testForNull
      * is true, surrounds the instruction with code that will guarantee that if the result starts as
      * 0, it will remain 0.
-     * 
+     *
      * @param testForNull true if we want to add the code to check for and preserve null
      * @param mnemonic the instruction to be applied (without size prefix)
      * @param result the register which is both an input and the final output
@@ -528,7 +542,7 @@
 
     /**
      * Emits an atomic_cas_global instruction.
-     * 
+     *
      * @param result result operand that gets the original contents of the memory location
      * @param address the memory location
      * @param cmpValue the value that will be compared against the memory location
@@ -542,7 +556,7 @@
 
     /**
      * Emits an atomic_add_global instruction.
-     * 
+     *
      * @param result result operand that gets the original contents of the memory location
      * @param address the memory location
      * @param deltaValue the amount to add
@@ -553,7 +567,7 @@
 
     /**
      * Emits a comment. Useful for debugging purposes.
-     * 
+     *
      * @param comment
      */
     public void emitComment(String comment) {
@@ -588,7 +602,7 @@
         // emitString(String.format("maxwaveid_u32 %s;", HSAIL.mapRegister(dest)));
         int hardCodedMaxWaveId = 36;
         emitComment("// Hard-coded maxwaveid=" + hardCodedMaxWaveId + " until it works");
-        emitMov(dest, Constant.forInt(hardCodedMaxWaveId));
+        emitMov(Kind.Int, dest, Constant.forInt(hardCodedMaxWaveId));
     }
 
     public void emitMultiplyByWavesize(Value dest) {
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Apr 02 15:26:58 2014 +0200
@@ -147,9 +147,9 @@
         if (src instanceof AMD64AddressValue) {
             return new LeaOp(dst, (AMD64AddressValue) src);
         } else if (isRegister(src) || isStackSlot(dst)) {
-            return new MoveFromRegOp(dst, src);
+            return new MoveFromRegOp(dst.getKind(), dst, src);
         } else {
-            return new MoveToRegOp(dst, src);
+            return new MoveToRegOp(dst.getKind(), dst, src);
         }
     }
 
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Apr 02 15:26:58 2014 +0200
@@ -60,17 +60,11 @@
  */
 public abstract class HSAILLIRGenerator extends LIRGenerator {
 
-    public static class HSAILSpillMoveFactory implements LIR.SpillMoveFactory {
+    public class HSAILSpillMoveFactory implements LIR.SpillMoveFactory {
 
         @Override
         public LIRInstruction createMove(AllocatableValue dst, Value src) {
-            if (src instanceof HSAILAddressValue) {
-                return new LeaOp(dst, (HSAILAddressValue) src);
-            } else if (isRegister(src) || isStackSlot(dst)) {
-                return new MoveFromRegOp(dst, src);
-            } else {
-                return new MoveToRegOp(dst, src);
-            }
+            return HSAILLIRGenerator.this.createMove(dst, src);
         }
     }
 
@@ -104,13 +98,19 @@
         return result;
     }
 
+    protected HSAILLIRInstruction createMove(AllocatableValue dst, Value src) {
+        if (src instanceof HSAILAddressValue) {
+            return new LeaOp(dst, (HSAILAddressValue) src);
+        } else if (isRegister(src) || isStackSlot(dst)) {
+            return new MoveFromRegOp(dst.getKind(), dst, src);
+        } else {
+            return new MoveToRegOp(dst.getKind(), dst, src);
+        }
+    }
+
     @Override
     public void emitMove(AllocatableValue dst, Value src) {
-        if (isRegister(src) || isStackSlot(dst)) {
-            append(new MoveFromRegOp(dst, src));
-        } else {
-            append(new MoveToRegOp(dst, src));
-        }
+        append(createMove(dst, src));
     }
 
     public void emitData(AllocatableValue dst, byte[] data) {
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Apr 02 15:26:58 2014 +0200
@@ -232,26 +232,26 @@
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
         PTXAddressValue loadAddress = asAddress(address);
         Variable result = newVariable(kind);
         LIRFrameState state = null;
         if (access instanceof DeoptimizingNode) {
             state = state((DeoptimizingNode) access);
         }
-        append(new LoadOp(kind, result, loadAddress, state));
+        append(new LoadOp((Kind) kind, result, loadAddress, state));
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
         PTXAddressValue storeAddress = asAddress(address);
         Variable input = load(inputVal);
         LIRFrameState state = null;
         if (access instanceof DeoptimizingNode) {
             state = state((DeoptimizingNode) access);
         }
-        append(new StoreOp(kind, storeAddress, input, state));
+        append(new StoreOp((Kind) kind, storeAddress, input, state));
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Apr 02 15:26:58 2014 +0200
@@ -582,10 +582,15 @@
     }
 
     public PlatformKind getIntegerKind(int bits, boolean unsigned) {
-        if (bits > 32) {
+        if (bits <= 8) {
+            return Kind.Byte;
+        } else if (bits <= 16) {
+            return Kind.Short;
+        } else if (bits <= 32) {
+            return Kind.Int;
+        } else {
+            assert bits <= 64;
             return Kind.Long;
-        } else {
-            return Kind.Int;
         }
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Apr 02 15:26:58 2014 +0200
@@ -495,7 +495,7 @@
     }
 
     protected PlatformKind getPhiKind(PhiNode phi) {
-        return phi.getKind();
+        return gen.getPlatformKind(phi.stamp());
     }
 
     private Value operandForPhi(PhiNode phi) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Apr 02 15:26:58 2014 +0200
@@ -48,6 +48,7 @@
 import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
+import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
@@ -103,7 +104,7 @@
                 dst = newVariable(Kind.Long);
             }
 
-            placeholder.replace(getResult().getLIR(), new MoveFromRegOp(dst, rbp.asValue(Kind.Long)));
+            placeholder.replace(getResult().getLIR(), new MoveFromRegOp(Kind.Long, dst, rbp.asValue(Kind.Long)));
             return dst;
         }
     }
@@ -323,7 +324,7 @@
     /**
      * Returns whether or not the input access should be (de)compressed.
      */
-    private boolean isCompressedOperation(Kind kind, Access access) {
+    private boolean isCompressedOperation(PlatformKind kind, Access access) {
         return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops));
     }
 
@@ -338,10 +339,26 @@
         }
     }
 
+    private static Kind getMemoryKind(PlatformKind kind) {
+        if (kind == NarrowOopStamp.NarrowOop) {
+            return Kind.Int;
+        } else {
+            return (Kind) kind;
+        }
+    }
+
+    private static PlatformKind toStackKind(PlatformKind kind) {
+        if (kind instanceof Kind) {
+            return ((Kind) kind).getStackKind();
+        } else {
+            return kind;
+        }
+    }
+
     @Override
-    public Variable emitLoad(Kind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
         AMD64AddressValue loadAddress = asAddressValue(address);
-        Variable result = newVariable(kind.getStackKind());
+        Variable result = newVariable(toStackKind(kind));
         LIRFrameState state = null;
         if (access instanceof DeoptimizingNode) {
             state = state((DeoptimizingNode) access);
@@ -355,21 +372,21 @@
          */
         if (isCompressedOperation(kind, access)) {
             if (kind == Kind.Object) {
-                append(new LoadCompressedPointer(kind, result, getProviders().getRegisters().getHeapBaseRegister().asValue(), loadAddress, state, config.getOopEncoding()));
+                append(new LoadCompressedPointer(Kind.Object, result, getProviders().getRegisters().getHeapBaseRegister().asValue(), loadAddress, state, config.getOopEncoding()));
             } else if (kind == Kind.Long) {
                 Variable scratch = config.getKlassEncoding().base != 0 ? newVariable(Kind.Long) : null;
-                append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, config.getKlassEncoding()));
+                append(new LoadCompressedPointer(Kind.Long, result, scratch, loadAddress, state, config.getKlassEncoding()));
             } else {
                 throw GraalInternalError.shouldNotReachHere("can't handle: " + access);
             }
         } else {
-            append(new LoadOp(kind, result, loadAddress, state));
+            append(new LoadOp(getMemoryKind(kind), result, loadAddress, state));
         }
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
         AMD64AddressValue storeAddress = asAddressValue(address);
         LIRFrameState state = null;
         if (access instanceof DeoptimizingNode) {
@@ -381,18 +398,18 @@
             if (canStoreConstant(c, isCompressed)) {
                 if (isCompressed) {
                     if (c.getKind() == Kind.Object) {
-                        append(new StoreCompressedConstantOp(kind, storeAddress, c, state));
+                        append(new StoreCompressedConstantOp(Kind.Object, storeAddress, c, state));
                     } else if (c.getKind() == Kind.Long) {
                         // It's always a good idea to directly store compressed constants since they
                         // have to be materialized as 64 bits encoded otherwise.
                         Constant value = compress(c, config.getKlassEncoding());
-                        append(new StoreCompressedConstantOp(kind, storeAddress, value, state));
+                        append(new StoreCompressedConstantOp(Kind.Long, storeAddress, value, state));
                     } else {
                         throw GraalInternalError.shouldNotReachHere("can't handle: " + access);
                     }
                     return;
                 } else {
-                    append(new StoreConstantOp(kind, storeAddress, c, state));
+                    append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state));
                     return;
                 }
             }
@@ -403,7 +420,7 @@
                 if (input.getKind() == Kind.Object) {
                     Variable scratch = newVariable(Kind.Long);
                     Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister();
-                    append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, config.getOopEncoding(), heapBaseReg));
+                    append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, config.getOopEncoding(), heapBaseReg));
                 } else {
                     // the input oop is already compressed
                     append(new StoreOp(input.getKind(), storeAddress, input, state));
@@ -411,12 +428,12 @@
             } else if (kind == Kind.Long) {
                 Variable scratch = newVariable(Kind.Long);
                 Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister();
-                append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, config.getKlassEncoding(), heapBaseReg));
+                append(new StoreCompressedPointer(Kind.Long, storeAddress, input, scratch, state, config.getKlassEncoding(), heapBaseReg));
             } else {
-                append(new StoreOp(kind, storeAddress, input, state));
+                append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
             }
         } else {
-            append(new StoreOp(kind, storeAddress, input, state));
+            append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
         }
     }
 
@@ -434,4 +451,17 @@
         return result;
     }
 
+    @Override
+    protected AMD64LIRInstruction createMove(AllocatableValue dst, Value src) {
+        if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) {
+            if (isRegister(src) || isStackSlot(dst)) {
+                return new MoveFromRegOp(Kind.Int, dst, src);
+            } else {
+                return new MoveToRegOp(Kind.Int, dst, src);
+            }
+        } else {
+            return super.createMove(dst, src);
+        }
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Wed Apr 02 15:26:58 2014 +0200
@@ -92,8 +92,8 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            AMD64Move.move(crb, masm, result, input);
             if (result.getPlatformKind() == NarrowOopStamp.NarrowOop) {
+                AMD64Move.move(Kind.Long, crb, masm, result, input);
                 encodePointer(masm, asRegister(result), asRegister(baseRegister), encoding);
             } else {
                 throw GraalInternalError.unimplemented();
@@ -118,8 +118,8 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            AMD64Move.move(crb, masm, result, input);
             if (result.getKind() == Kind.Object) {
+                AMD64Move.move(Kind.Int, crb, masm, result, input);
                 decodePointer(masm, asRegister(result), asRegister(baseRegister), encoding);
             } else {
                 throw GraalInternalError.unimplemented();
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Apr 02 15:26:58 2014 +0200
@@ -61,6 +61,7 @@
 import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
@@ -671,7 +672,7 @@
             asm.emitLoadKernelArg(scratch64, asm.getDeoptInfoName(), "u64");
 
             // Set deopt occurred flag
-            asm.emitMov(scratch32, Constant.forInt(1));
+            asm.emitMov(Kind.Int, scratch32, Constant.forInt(1));
             asm.emitStoreRelease(scratch32, deoptInfoAddr);
 
             asm.emitComment("// Determine next deopt save slot");
@@ -904,7 +905,8 @@
             int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long);
             long offset = config.hsailFrameSaveAreaOffset + longSize * (regNumber - HSAIL.d0.number);
             LocationNode numSRegsLocation = ConstantLocationNode.create(FINAL_LOCATION, Kind.Byte, config.hsailFrameNumSRegOffset, hostGraph);
-            ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forKind(Kind.Byte)));
+            ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8, false)));
+            numSRegs = SignExtendNode.convert(numSRegs, StampFactory.forKind(Kind.Byte));
             location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4);
         } else {
             throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber);
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java	Wed Apr 02 15:26:58 2014 +0200
@@ -27,7 +27,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hsail.*;
 
 public class HSAILHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider {
 
@@ -44,6 +43,6 @@
 
     @Override
     protected RegisterConfig createRegisterConfig() {
-        return new HSAILRegisterConfig();
+        return new HSAILHotSpotRegisterConfig();
     }
 }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Apr 02 15:26:58 2014 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
@@ -41,6 +42,8 @@
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp;
 import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer;
 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.StoreCompressedPointer;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreOp;
@@ -51,7 +54,7 @@
 /**
  * The HotSpot specific portion of the HSAIL LIR generator.
  */
-public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator {
+public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator implements HotSpotLIRGenerator {
 
     final HotSpotVMConfig config;
 
@@ -101,32 +104,42 @@
     /**
      * Returns whether or not the input access should be (de)compressed.
      */
-    private boolean isCompressedOperation(Kind kind, Access access) {
+    private boolean isCompressedOperation(PlatformKind kind, Access access) {
         return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops));
     }
 
+    private static Kind getMemoryKind(PlatformKind kind) {
+        if (kind == NarrowOopStamp.NarrowOop) {
+            return Kind.Int;
+        } else {
+            return (Kind) kind;
+        }
+    }
+
     @Override
-    public Variable emitLoad(Kind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
         HSAILAddressValue loadAddress = asAddressValue(address);
-        Variable result = newVariable(kind.getStackKind());
+        Variable result = newVariable(kind);
         LIRFrameState state = null;
         if (access instanceof DeoptimizingNode) {
             state = state((DeoptimizingNode) access);
         }
         if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) {
             Variable scratch = newVariable(Kind.Long);
-            append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
+            append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
         } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) {
             Variable scratch = newVariable(Kind.Long);
-            append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment()));
+            append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment()));
+        } else if (kind == NarrowOopStamp.NarrowOop) {
+            append(new LoadOp(Kind.Int, result, loadAddress, state));
         } else {
-            append(new LoadOp(kind, result, loadAddress, state));
+            append(new LoadOp(getMemoryKind(kind), result, loadAddress, state));
         }
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
         HSAILAddressValue storeAddress = asAddressValue(address);
         LIRFrameState state = null;
         if (access instanceof DeoptimizingNode) {
@@ -147,7 +160,7 @@
                     }
                     return;
                 } else {
-                    append(new StoreConstantOp(kind, storeAddress, c, state));
+                    append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state));
                     return;
                 }
             }
@@ -155,12 +168,14 @@
         Variable input = load(inputVal);
         if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) {
             Variable scratch = newVariable(Kind.Long);
-            append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
+            append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
         } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) {
             Variable scratch = newVariable(Kind.Long);
-            append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment()));
+            append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment()));
+        } else if (kind == NarrowOopStamp.NarrowOop) {
+            append(new StoreOp(Kind.Int, storeAddress, input, state));
         } else {
-            append(new StoreOp(kind, storeAddress, input, state));
+            append(new StoreOp(getMemoryKind(kind), storeAddress, input, state));
         }
     }
 
@@ -215,6 +230,19 @@
     }
 
     @Override
+    protected HSAILLIRInstruction createMove(AllocatableValue dst, Value src) {
+        if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) {
+            if (isRegister(src) || isStackSlot(dst)) {
+                return new MoveFromRegOp(Kind.Int, dst, src);
+            } else {
+                return new MoveToRegOp(Kind.Int, dst, src);
+            }
+        } else {
+            return super.createMove(dst, src);
+        }
+    }
+
+    @Override
     protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
         // this version of emitForeignCall not used for now
     }
@@ -229,4 +257,28 @@
             throw GraalInternalError.shouldNotReachHere();
         }
     }
+
+    public void emitTailcall(Value[] args, Value address) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    public StackSlot getLockSlot(int lockDepth) {
+        throw GraalInternalError.shouldNotReachHere("NYI");
+    }
+
+    public Value emitCompress(Value pointer, CompressEncoding encoding) {
+        Variable result = newVariable(NarrowOopStamp.NarrowOop);
+        append(new HSAILMove.CompressPointer(result, newVariable(pointer.getPlatformKind()), asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment));
+        return result;
+    }
+
+    public Value emitUncompress(Value pointer, CompressEncoding encoding) {
+        Variable result = newVariable(Kind.Object);
+        append(new HSAILMove.UncompressPointer(result, asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment));
+        return result;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java	Wed Apr 02 15:26:58 2014 +0200
@@ -0,0 +1,200 @@
+/*
+ * 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.hotspot.hsail;
+
+import static com.oracle.graal.hsail.HSAIL.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.nodes.type.*;
+import com.oracle.graal.hsail.*;
+
+/**
+ * This class defines a higher level interface for the register allocator to be able to access info
+ * about the {@link HSAIL} register set.
+ *
+ * Note: In HSAIL, the number of registers of each type is actually a variable number that must
+ * satisfy the equation: Total num of registers = No. of S registers + 2 * (No. of D registers) + 4
+ * * (No. of Q registers) = 128 In other words we can have up to 128S or 64 D or 32Q or a blend.
+ *
+ * For now we haven't implemented support for a variable sized register file. Instead we've fixed
+ * the number of registers of each type so that they satisfy the above equation. See {@link HSAIL}
+ * for more details.
+ */
+public class HSAILHotSpotRegisterConfig implements RegisterConfig {
+
+    private final Register[] allocatable = {s0, s1, s2, s3, s4, s5, s6, /* s7, */s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31,
+                    d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15};
+
+    private final Register[] regBitness32 = {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31};
+    private final Register[] regBitness64 = {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15};
+    private final RegisterAttributes[] attributesMap = RegisterAttributes.createMap(this, HSAIL.allRegisters);
+
+    @Override
+    public Register getReturnRegister(Kind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+            case Object:
+                return s0;
+            case Float:
+            case Double:
+                return d0;
+            case Void:
+            case Illegal:
+                return null;
+            default:
+                throw new UnsupportedOperationException("no return register for type " + kind);
+        }
+    }
+
+    @Override
+    public Register getFrameRegister() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
+        return callingConvention(regBitness32, regBitness64, returnType, parameterTypes, type, target, stackOnly);
+    }
+
+    private CallingConvention callingConvention(Register[] generalParameterRegisters, Register[] longParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type,
+                    TargetDescription target, boolean stackOnly) {
+        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+        int currentRegs32 = 0;
+        int currentRegs64 = 0;
+        int currentStackOffset = 0;
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            final Kind kind = parameterTypes[i].getKind();
+
+            switch (kind) {
+                case Byte:
+                case Boolean:
+                case Short:
+                case Char:
+                case Int:
+                case Float:
+
+                    if (!stackOnly && currentRegs32 < generalParameterRegisters.length) {
+                        Register register = generalParameterRegisters[currentRegs32++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                case Long:
+                case Object:
+                case Double:
+                    if (!stackOnly && currentRegs64 < longParameterRegisters.length) {
+                        Register register = longParameterRegisters[currentRegs64++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+
+            if (locations[i] == null) {
+                locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
+                currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize);
+            }
+        }
+
+        Kind returnKind = returnType == null ? Kind.Void : returnType.getKind();
+        AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind);
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
+    }
+
+    @Override
+    public Register[] getCallingConventionRegisters(Type type, Kind kind) {
+        throw new GraalInternalError("getCallingConventinoRegisters unimplemented");
+    }
+
+    @Override
+    public Register[] getAllocatableRegisters() {
+        return allocatable.clone();
+    }
+
+    @Override
+    public Register[] getAllocatableRegisters(PlatformKind kind) {
+        Kind primitiveKind;
+        if (kind == NarrowOopStamp.NarrowOop) {
+            primitiveKind = Kind.Int;
+        } else {
+            primitiveKind = (Kind) kind;
+        }
+
+        switch (primitiveKind) {
+            case Int:
+            case Short:
+            case Byte:
+            case Float:
+                return regBitness32.clone();
+            case Long:
+            case Double:
+            case Object:
+                return regBitness64.clone();
+
+            default:
+                throw new GraalInternalError("unknown register allocation");
+        }
+    }
+
+    @Override
+    public Register[] getCallerSaveRegisters() {
+        // TODO Auto-generated method stub
+        return new Register[0];
+    }
+
+    @Override
+    public boolean areAllAllocatableRegistersCallerSaved() {
+        return false;
+    }
+
+    @Override
+    public CalleeSaveLayout getCalleeSaveLayout() {
+        return null;
+    }
+
+    @Override
+    public RegisterAttributes[] getAttributesMap() {
+        return attributesMap.clone();
+    }
+
+    @Override
+    public Register getRegisterForRole(int id) {
+        throw new UnsupportedOperationException();
+    }
+
+    public HSAILHotSpotRegisterConfig() {
+
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Apr 02 15:26:58 2014 +0200
@@ -147,9 +147,9 @@
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
         SPARCAddressValue loadAddress = asAddressValue(address);
-        Variable result = newVariable(kind.getStackKind());
+        Variable result = newVariable(kind);
         LIRFrameState state = null;
         if (access instanceof DeoptimizingNode) {
             state = state((DeoptimizingNode) access);
@@ -168,16 +168,16 @@
                 // config.logKlassAlignment));
                 throw GraalInternalError.unimplemented();
             } else {
-                append(new LoadOp(kind, result, loadAddress, state));
+                append(new LoadOp((Kind) kind, result, loadAddress, state));
             }
         } else {
-            append(new LoadOp(kind, result, loadAddress, state));
+            append(new LoadOp((Kind) kind, result, loadAddress, state));
         }
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
         SPARCAddressValue storeAddress = asAddressValue(address);
         LIRFrameState state = null;
         if (access instanceof DeoptimizingNode) {
@@ -187,11 +187,11 @@
             Constant c = asConstant(inputVal);
             if (canStoreConstant(c, isCompressCandidate(access))) {
                 if (inputVal.getKind() == Kind.Object) {
-                    append(new StoreConstantOp(kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(access)));
+                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(access)));
                 } else if (inputVal.getKind() == Kind.Long) {
-                    append(new StoreConstantOp(kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(access)));
+                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(access)));
                 } else {
-                    append(new StoreConstantOp(kind, storeAddress, c, state, false));
+                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, false));
                 }
                 return;
             }
@@ -216,10 +216,10 @@
                 // config.logKlassAlignment));
                 throw GraalInternalError.unimplemented();
             } else {
-                append(new StoreOp(kind, storeAddress, input, state));
+                append(new StoreOp((Kind) kind, storeAddress, input, state));
             }
         } else {
-            append(new StoreOp(kind, storeAddress, input, state));
+            append(new StoreOp((Kind) kind, storeAddress, input, state));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Wed Apr 02 15:26:58 2014 +0200
@@ -42,6 +42,7 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
@@ -88,7 +89,7 @@
         instanceofSnippets = new InstanceOfSnippets.Templates(providers, target);
         newObjectSnippets = new NewObjectSnippets.Templates(providers, target);
         monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking);
-        writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target);
+        writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null);
         boxingSnippets = new BoxingSnippets.Templates(providers, target);
         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target);
         unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target);
@@ -117,6 +118,10 @@
             lowerUnsafeLoadNode((UnsafeLoadNode) n, tool);
         } else if (n instanceof UnsafeStoreNode) {
             lowerUnsafeStoreNode((UnsafeStoreNode) n);
+        } else if (n instanceof JavaReadNode) {
+            lowerJavaReadNode((JavaReadNode) n);
+        } else if (n instanceof JavaWriteNode) {
+            lowerJavaWriteNode((JavaWriteNode) n);
         } else if (n instanceof LoadHubNode) {
             lowerLoadHubNode((LoadHubNode) n);
         } else if (n instanceof LoadMethodNode) {
@@ -255,14 +260,64 @@
         }
     }
 
+    private Stamp loadStamp(Stamp stamp, Kind kind) {
+        return loadStamp(stamp, kind, true);
+    }
+
+    private Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+                return StampTool.narrowingConversion(stamp, 8);
+
+            case Char:
+            case Short:
+                return StampTool.narrowingConversion(stamp, 16);
+
+            case Object:
+                if (compressible && runtime.getConfig().useCompressedOops) {
+                    return new NarrowOopStamp((ObjectStamp) stamp, runtime.getConfig().getOopEncoding());
+                }
+        }
+        return stamp;
+    }
+
+    private ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value) {
+        return implicitLoadConvert(graph, kind, value, true);
+    }
+
+    private ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) {
+        switch (kind) {
+            case Byte:
+            case Short:
+                return graph.unique(new SignExtendNode(value, 32));
+
+            case Boolean:
+            case Char:
+                return graph.unique(new ZeroExtendNode(value, 32));
+
+            case Object:
+                if (compressible && runtime.getConfig().useCompressedOops) {
+                    return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding());
+                }
+        }
+        return value;
+    }
+
     private void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) {
         StructuredGraph graph = loadField.graph();
         HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
         ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object();
         assert loadField.getKind() != Kind.Illegal;
         BarrierType barrierType = getFieldLoadBarrierType(field);
-        ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadField.stamp(), barrierType, (loadField.getKind() == Kind.Object)));
-        graph.replaceFixedWithFixed(loadField, memoryRead);
+
+        Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind());
+        ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadStamp, barrierType, false));
+        ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead);
+
+        loadField.replaceAtUsages(readValue);
+        graph.replaceFixed(loadField, memoryRead);
+
         memoryRead.setGuard(createNullCheck(object, memoryRead, tool));
 
         if (loadField.isVolatile()) {
@@ -273,12 +328,34 @@
         }
     }
 
+    private ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value) {
+        return implicitStoreConvert(graph, kind, value, true);
+    }
+
+    private ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+                return graph.unique(new NarrowNode(value, 8));
+            case Char:
+            case Short:
+                return graph.unique(new NarrowNode(value, 16));
+            case Object:
+                if (compressible && runtime.getConfig().useCompressedOops) {
+                    return CompressionNode.compress(value, runtime.getConfig().getOopEncoding());
+                }
+        }
+        return value;
+    }
+
     private void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) {
         StructuredGraph graph = storeField.graph();
         HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
         ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object();
         BarrierType barrierType = getFieldStoreBarrierType(storeField);
-        WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field, false), barrierType, storeField.field().getKind() == Kind.Object));
+
+        ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value());
+        WriteNode memoryWrite = graph.add(new WriteNode(object, value, createFieldLocation(graph, field, false), barrierType, false));
         memoryWrite.setStateAfter(storeField.stateAfter());
         graph.replaceFixedWithFixed(storeField, memoryWrite);
         memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool));
@@ -307,9 +384,15 @@
         StructuredGraph graph = loadIndexed.graph();
         Kind elementKind = loadIndexed.elementKind();
         LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false);
-        ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object));
+
+        Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind);
+        ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadStamp, BarrierType.NONE, false));
+        ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead);
+
         memoryRead.setGuard(createBoundsCheck(loadIndexed, tool));
-        graph.replaceFixedWithFixed(loadIndexed, memoryRead);
+
+        loadIndexed.replaceAtUsages(readValue);
+        graph.replaceFixed(loadIndexed, memoryRead);
     }
 
     private void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) {
@@ -317,6 +400,7 @@
         GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool);
         Kind elementKind = storeIndexed.elementKind();
         LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false);
+
         ValueNode value = storeIndexed.value();
         ValueNode array = storeIndexed.array();
 
@@ -348,7 +432,7 @@
             }
         }
         BarrierType barrierType = getArrayStoreBarrierType(storeIndexed);
-        WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object));
+        WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), arrayLocation, barrierType, false));
         memoryWrite.setGuard(boundsCheck);
         memoryWrite.setStateAfter(storeIndexed.stateAfter());
         graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
@@ -361,24 +445,30 @@
         }
     }
 
+    private ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) {
+        boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
+        Kind readKind = load.accessKind();
+        LocationNode location = createLocation(load);
+        Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible);
+        ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE, false));
+        ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible);
+        load.replaceAtUsages(readValue);
+        return memoryRead;
+    }
+
     private void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) {
         StructuredGraph graph = load.graph();
         if (load.getGuardingCondition() != null) {
-            boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
             ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition()));
-            LocationNode location = createLocation(load);
-            ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), valueAnchorNode, BarrierType.NONE, compressible));
-            load.replaceAtUsages(memoryRead);
+            ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode);
             graph.replaceFixedWithFixed(load, valueAnchorNode);
             graph.addAfterFixed(valueAnchorNode, memoryRead);
         } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) {
             assert load.getKind() != Kind.Illegal;
-            boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
             if (addReadBarrier(load)) {
                 unsafeLoadSnippets.lower(load, tool);
             } else {
-                LocationNode location = createLocation(load);
-                ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible));
+                ReadNode memoryRead = createUnsafeRead(graph, load, null);
                 // An unsafe read must not float outside its block otherwise
                 // it may float above an explicit null check on its object.
                 memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
@@ -387,16 +477,46 @@
         }
     }
 
-    private static void lowerUnsafeStoreNode(UnsafeStoreNode store) {
+    private void lowerUnsafeStoreNode(UnsafeStoreNode store) {
         StructuredGraph graph = store.graph();
         LocationNode location = createLocation(store);
         ValueNode object = store.object();
         BarrierType barrierType = getUnsafeStoreBarrierType(store);
-        WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().getKind() == Kind.Object));
+        boolean compressible = store.value().getKind() == Kind.Object;
+        Kind valueKind = store.accessKind();
+        ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible);
+        WriteNode write = graph.add(new WriteNode(object, value, location, barrierType, false));
         write.setStateAfter(store.stateAfter());
         graph.replaceFixedWithFixed(store, write);
     }
 
+    private void lowerJavaReadNode(JavaReadNode read) {
+        StructuredGraph graph = read.graph();
+
+        Kind valueKind = read.location().getValueKind();
+        Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible());
+        ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType(), false));
+        ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible());
+
+        memoryRead.setGuard(read.getGuard());
+
+        read.replaceAtUsages(readValue);
+        graph.replaceFixed(read, memoryRead);
+    }
+
+    private void lowerJavaWriteNode(JavaWriteNode write) {
+        StructuredGraph graph = write.graph();
+
+        Kind valueKind = write.location().getValueKind();
+        ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible());
+
+        WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), false, write.isInitialization()));
+        memoryWrite.setStateAfter(write.stateAfter());
+        graph.replaceFixedWithFixed(write, memoryWrite);
+
+        memoryWrite.setGuard(write.getGuard());
+    }
+
     private void lowerLoadHubNode(LoadHubNode loadHub) {
         StructuredGraph graph = loadHub.graph();
         if (graph.getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) {
@@ -464,7 +584,7 @@
                             location = ConstantLocationNode.create(INIT_LOCATION, accessKind, getArrayBaseOffset(entryKind) + i * getScalingFactor(entryKind), graph);
                             barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE;
                         }
-                        WriteNode write = new WriteNode(newObject, value, location, barrierType, entryKind == Kind.Object);
+                        WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType, false);
                         graph.addAfterFixed(newObject, graph.add(write));
                     }
                     valuePos++;
@@ -487,9 +607,11 @@
                             WriteNode write;
                             if (virtual instanceof VirtualInstanceNode) {
                                 VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
-                                write = new WriteNode(newObject, allocValue, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true), BarrierType.IMPRECISE, true);
+                                write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i),
+                                                true), BarrierType.IMPRECISE, false);
                             } else {
-                                write = new WriteNode(newObject, allocValue, createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), true), BarrierType.PRECISE, true);
+                                write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph),
+                                                true), BarrierType.PRECISE, false);
                             }
                             graph.addBeforeFixed(commit, graph.add(write));
                         }
@@ -569,10 +691,14 @@
     }
 
     private static LocationNode createLocation(UnsafeAccessNode access) {
-        ValueNode offset = access.offset();
+        return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind());
+    }
+
+    private static LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) {
+        ValueNode offset = offsetNode;
         if (offset.isConstant()) {
             long offsetValue = offset.asConstant().asLong();
-            return ConstantLocationNode.create(access.getLocationIdentity(), access.accessKind(), offsetValue, access.graph());
+            return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph());
         }
 
         long displacement = 0;
@@ -602,7 +728,7 @@
             }
         }
 
-        return IndexedLocationNode.create(access.getLocationIdentity(), access.accessKind(), displacement, offset, access.graph(), indexScaling);
+        return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling);
     }
 
     private static boolean addReadBarrier(UnsafeLoadNode load) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Wed Apr 02 15:26:58 2014 +0200
@@ -42,9 +42,9 @@
     public static Object lowerUnsafeLoad(Object object, long offset) {
         Object fixedObject = FixedValueAnchorNode.getObject(object);
         if (object instanceof java.lang.ref.Reference && referentOffset() == offset) {
-            return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.PRECISE, true);
+            return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.PRECISE);
         } else {
-            return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.NONE, true);
+            return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.NONE);
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Wed Apr 02 15:26:58 2014 +0200
@@ -31,8 +31,10 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.hotspot.HotSpotVMConfig.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
@@ -136,7 +138,7 @@
             // If the previous value has to be loaded (before the write), the load is issued.
             // The load is always issued except the cases of CAS and referent field.
             if (probability(LIKELY_PROBABILITY, doLoad)) {
-                previousOop = (Word) Word.fromObject(field.readObject(0, BarrierType.NONE, true));
+                previousOop = (Word) Word.fromObject(field.readObject(0, BarrierType.NONE));
                 if (trace) {
                     log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue());
                     verifyOop(previousOop.toObject());
@@ -252,7 +254,7 @@
 
         for (int i = startIndex; i < length; i++) {
             long address = dstAddr + header + (i * scale);
-            Pointer oop = Word.fromObject(Word.unsigned(address).readObject(0, BarrierType.NONE, true));
+            Pointer oop = Word.fromObject(Word.unsigned(address).readObject(0, BarrierType.NONE));
             verifyOop(oop.toObject());
             if (oop.notEqual(0)) {
                 if (indexValue != 0) {
@@ -330,8 +332,11 @@
         private final SnippetInfo g1ArrayRangePreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier");
         private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier");
 
-        public Templates(Providers providers, TargetDescription target) {
+        private final CompressEncoding oopEncoding;
+
+        public Templates(Providers providers, TargetDescription target, CompressEncoding oopEncoding) {
             super(providers, target);
+            this.oopEncoding = oopEncoding;
         }
 
         public void lower(SerialWriteBarrier writeBarrier, LoweringTool tool) {
@@ -357,7 +362,14 @@
         public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers, LoweringTool tool) {
             Arguments args = new Arguments(g1PreWriteBarrier, writeBarrierPre.graph().getGuardsStage(), tool.getLoweringStage());
             args.add("object", writeBarrierPre.getObject());
-            args.add("expectedObject", writeBarrierPre.getExpectedObject());
+
+            ValueNode expected = writeBarrierPre.getExpectedObject();
+            if (expected != null && expected.stamp() instanceof NarrowOopStamp) {
+                assert oopEncoding != null;
+                expected = CompressionNode.uncompress(expected, oopEncoding);
+            }
+            args.add("expectedObject", expected);
+
             args.add("location", writeBarrierPre.getLocation());
             args.addConst("doLoad", writeBarrierPre.doLoad());
             args.addConst("nullCheck", writeBarrierPre.getNullCheck());
@@ -369,7 +381,14 @@
         public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
             Arguments args = new Arguments(g1ReferentReadBarrier, readBarrier.graph().getGuardsStage(), tool.getLoweringStage());
             args.add("object", readBarrier.getObject());
-            args.add("expectedObject", readBarrier.getExpectedObject());
+
+            ValueNode expected = readBarrier.getExpectedObject();
+            if (expected != null && expected.stamp() instanceof NarrowOopStamp) {
+                assert oopEncoding != null;
+                expected = CompressionNode.uncompress(expected, oopEncoding);
+            }
+
+            args.add("expectedObject", expected);
             args.add("location", readBarrier.getLocation());
             args.addConst("doLoad", readBarrier.doLoad());
             args.addConst("nullCheck", false);
@@ -379,13 +398,21 @@
         }
 
         public void lower(G1PostWriteBarrier writeBarrierPost, HotSpotRegistersProvider registers, LoweringTool tool) {
+            StructuredGraph graph = writeBarrierPost.graph();
             if (writeBarrierPost.alwaysNull()) {
-                writeBarrierPost.graph().removeFixed(writeBarrierPost);
+                graph.removeFixed(writeBarrierPost);
                 return;
             }
-            Arguments args = new Arguments(g1PostWriteBarrier, writeBarrierPost.graph().getGuardsStage(), tool.getLoweringStage());
+            Arguments args = new Arguments(g1PostWriteBarrier, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("object", writeBarrierPost.getObject());
-            args.add("value", writeBarrierPost.getValue());
+
+            ValueNode value = writeBarrierPost.getValue();
+            if (value.stamp() instanceof NarrowOopStamp) {
+                assert oopEncoding != null;
+                value = CompressionNode.uncompress(value, oopEncoding);
+            }
+            args.add("value", value);
+
             args.add("location", writeBarrierPost.getLocation());
             args.addConst("usePrecise", writeBarrierPost.usePrecise());
             args.addConst("threadRegister", registers.getThreadRegister());
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java	Wed Apr 02 15:26:58 2014 +0200
@@ -176,20 +176,7 @@
     }
 
     public static String mapRegister(Value arg) {
-        Register reg;
-        int encoding = 0;
-        String regPrefix = null;
-        Kind kind = arg.getKind();
-        if (kind == Kind.Double || kind == Kind.Long) {
-            regPrefix = "$d";
-        } else if (kind == Kind.Int || kind == Kind.Float) {
-            regPrefix = "$s";
-        } else {
-            regPrefix = "$d";
-        }
-        reg = asRegister(arg);
-        encoding = reg.encoding();
-        return new String(regPrefix + encoding);
+        return "$" + asRegister(arg).name;
     }
 
     @Override
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java	Wed Apr 02 14:43:52 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.graal.hsail;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CallingConvention.Type;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-
-import static com.oracle.graal.hsail.HSAIL.*;
-
-/**
- * This class defines a higher level interface for the register allocator to be able to access info
- * about the {@link HSAIL} register set.
- * 
- * Note: In HSAIL, the number of registers of each type is actually a variable number that must
- * satisfy the equation: Total num of registers = No. of S registers + 2 * (No. of D registers) + 4
- * * (No. of Q registers) = 128 In other words we can have up to 128S or 64 D or 32Q or a blend.
- * 
- * For now we haven't implemented support for a variable sized register file. Instead we've fixed
- * the number of registers of each type so that they satisfy the above equation. See {@link HSAIL}
- * for more details.
- */
-public class HSAILRegisterConfig implements RegisterConfig {
-
-    private final Register[] allocatable = {s0, s1, s2, s3, s4, s5, s6, /* s7, */s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31,
-                    d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15};
-
-    private final Register[] regBitness32 = {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31};
-    private final Register[] regBitness64 = {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15};
-    private final RegisterAttributes[] attributesMap = RegisterAttributes.createMap(this, HSAIL.allRegisters);
-
-    @Override
-    public Register getReturnRegister(Kind kind) {
-        switch (kind) {
-            case Boolean:
-            case Byte:
-            case Char:
-            case Short:
-            case Int:
-            case Long:
-            case Object:
-                return s0;
-            case Float:
-            case Double:
-                return d0;
-            case Void:
-            case Illegal:
-                return null;
-            default:
-                throw new UnsupportedOperationException("no return register for type " + kind);
-        }
-    }
-
-    @Override
-    public Register getFrameRegister() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
-        return callingConvention(regBitness32, regBitness64, returnType, parameterTypes, type, target, stackOnly);
-    }
-
-    private CallingConvention callingConvention(Register[] generalParameterRegisters, Register[] longParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type,
-                    TargetDescription target, boolean stackOnly) {
-        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
-
-        int currentRegs32 = 0;
-        int currentRegs64 = 0;
-        int currentStackOffset = 0;
-
-        for (int i = 0; i < parameterTypes.length; i++) {
-            final Kind kind = parameterTypes[i].getKind();
-
-            switch (kind) {
-                case Byte:
-                case Boolean:
-                case Short:
-                case Char:
-                case Int:
-                case Float:
-
-                    if (!stackOnly && currentRegs32 < generalParameterRegisters.length) {
-                        Register register = generalParameterRegisters[currentRegs32++];
-                        locations[i] = register.asValue(kind);
-                    }
-                    break;
-                case Long:
-                case Object:
-                case Double:
-                    if (!stackOnly && currentRegs64 < longParameterRegisters.length) {
-                        Register register = longParameterRegisters[currentRegs64++];
-                        locations[i] = register.asValue(kind);
-                    }
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
-
-            if (locations[i] == null) {
-                locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
-                currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize);
-            }
-        }
-
-        Kind returnKind = returnType == null ? Kind.Void : returnType.getKind();
-        AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind);
-        return new CallingConvention(currentStackOffset, returnLocation, locations);
-    }
-
-    @Override
-    public Register[] getCallingConventionRegisters(Type type, Kind kind) {
-        throw new GraalInternalError("getCallingConventinoRegisters unimplemented");
-    }
-
-    @Override
-    public Register[] getAllocatableRegisters() {
-        return allocatable.clone();
-    }
-
-    @Override
-    public Register[] getAllocatableRegisters(PlatformKind kind) {
-        Kind k = (Kind) kind;
-        switch (k) {
-            case Int:
-            case Short:
-            case Byte:
-            case Float:
-                return regBitness32.clone();
-            case Long:
-            case Double:
-            case Object:
-                return regBitness64.clone();
-
-            default:
-                throw new GraalInternalError("unknown register allocation");
-        }
-    }
-
-    @Override
-    public Register[] getCallerSaveRegisters() {
-        // TODO Auto-generated method stub
-        return new Register[0];
-    }
-
-    @Override
-    public boolean areAllAllocatableRegistersCallerSaved() {
-        return false;
-    }
-
-    @Override
-    public CalleeSaveLayout getCalleeSaveLayout() {
-        return null;
-    }
-
-    @Override
-    public RegisterAttributes[] getAttributesMap() {
-        return attributesMap.clone();
-    }
-
-    @Override
-    public Register getRegisterForRole(int id) {
-        throw new UnsupportedOperationException();
-    }
-
-    public HSAILRegisterConfig() {
-
-    }
-}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Wed Apr 02 15:26:58 2014 +0200
@@ -42,23 +42,38 @@
 
 public class AMD64Move {
 
+    private abstract static class AbstractMoveOp extends AMD64LIRInstruction implements MoveOp {
+
+        private Kind moveKind;
+
+        public AbstractMoveOp(Kind moveKind) {
+            if (moveKind == Kind.Illegal) {
+                // unknown operand size, conservatively move the whole register
+                this.moveKind = Kind.Long;
+            } else {
+                this.moveKind = moveKind;
+            }
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            move(moveKind, crb, masm, getResult(), getInput());
+        }
+    }
+
     @Opcode("MOVE")
-    public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp {
+    public static class MoveToRegOp extends AbstractMoveOp {
 
         @Def({REG, HINT}) protected AllocatableValue result;
         @Use({REG, STACK, CONST}) protected Value input;
 
-        public MoveToRegOp(AllocatableValue result, Value input) {
+        public MoveToRegOp(Kind moveKind, AllocatableValue result, Value input) {
+            super(moveKind);
             this.result = result;
             this.input = input;
         }
 
         @Override
-        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            move(crb, masm, getResult(), getInput());
-        }
-
-        @Override
         public Value getInput() {
             return input;
         }
@@ -70,22 +85,18 @@
     }
 
     @Opcode("MOVE")
-    public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp {
+    public static class MoveFromRegOp extends AbstractMoveOp {
 
         @Def({REG, STACK}) protected AllocatableValue result;
         @Use({REG, CONST, HINT}) protected Value input;
 
-        public MoveFromRegOp(AllocatableValue result, Value input) {
+        public MoveFromRegOp(Kind moveKind, AllocatableValue result, Value input) {
+            super(moveKind);
             this.result = result;
             this.input = input;
         }
 
         @Override
-        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            move(crb, masm, getResult(), getInput());
-        }
-
-        @Override
         public Value getInput() {
             return input;
         }
@@ -404,17 +415,21 @@
     }
 
     public static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
+        move(result.getKind(), crb, masm, result, input);
+    }
+
+    public static void move(Kind moveKind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
         if (isRegister(input)) {
             if (isRegister(result)) {
-                reg2reg(masm, result, input);
+                reg2reg(moveKind, masm, result, input);
             } else if (isStackSlot(result)) {
-                reg2stack(crb, masm, result, input);
+                reg2stack(moveKind, crb, masm, result, input);
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
         } else if (isStackSlot(input)) {
             if (isRegister(result)) {
-                stack2reg(crb, masm, result, input);
+                stack2reg(moveKind, crb, masm, result, input);
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
@@ -431,11 +446,11 @@
         }
     }
 
-    private static void reg2reg(AMD64MacroAssembler masm, Value result, Value input) {
+    private static void reg2reg(Kind kind, AMD64MacroAssembler masm, Value result, Value input) {
         if (asRegister(input).equals(asRegister(result))) {
             return;
         }
-        switch (input.getKind()) {
+        switch (kind.getStackKind()) {
             case Int:
                 masm.movl(asRegister(result), asRegister(input));
                 break;
@@ -456,9 +471,9 @@
         }
     }
 
-    private static void reg2stack(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
+    private static void reg2stack(Kind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
         AMD64Address dest = (AMD64Address) crb.asAddress(result);
-        switch (input.getKind()) {
+        switch (kind) {
             case Boolean:
             case Byte:
                 masm.movb(dest, asRegister(input));
@@ -487,9 +502,9 @@
         }
     }
 
-    private static void stack2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
+    private static void stack2reg(Kind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
         AMD64Address src = (AMD64Address) crb.asAddress(input);
-        switch (input.getKind()) {
+        switch (kind) {
             case Boolean:
                 masm.movzbl(asRegister(result), src);
                 break;
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Wed Apr 02 15:26:58 2014 +0200
@@ -47,7 +47,7 @@
     /**
      * This class represents the LIR instruction that the HSAIL backend generates for a switch
      * construct in Java.
-     * 
+     *
      * The HSAIL backend compiles switch statements into a series of cascading compare and branch
      * instructions because this is the currently the recommended way to generate optimally
      * performing HSAIL code. Thus the execution path for both the TABLESWITCH and LOOKUPSWITCH
@@ -85,12 +85,12 @@
 
         /**
          * Generates the code for this switch op.
-         * 
+         *
          * The keys for switch statements in Java bytecode for of type int. However, Graal also
          * generates a TypeSwitchNode (for method dispatch) which triggers the invocation of these
          * routines with keys of type Long or Object. Currently we only support the
          * IntegerSwitchNode so we throw an exception if the key isn't of type int.
-         * 
+         *
          * @param crb the CompilationResultBuilder
          * @param masm the HSAIL assembler
          */
@@ -191,9 +191,9 @@
             AllocatableValue actionAndReasonReg = HSAIL.s32.asValue(Kind.Int);
             AllocatableValue codeBufferOffsetReg = HSAIL.s33.asValue(Kind.Int);
             AllocatableValue dregOopMapReg = HSAIL.s39.asValue(Kind.Int);
-            masm.emitMov(actionAndReasonReg, actionAndReason);
-            masm.emitMov(codeBufferOffsetReg, Constant.forInt(codeBufferPos));
-            masm.emitMov(dregOopMapReg, Constant.forInt(dregOopMap));
+            masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason);
+            masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
+            masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap));
             masm.emitJumpToLabelName(masm.getDeoptLabelName());
 
             // now record the debuginfo
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Wed Apr 02 15:26:58 2014 +0200
@@ -48,23 +48,33 @@
         return maxStackOffset + maxDatatypeSize;
     }
 
+    private abstract static class AbstractMoveOp extends HSAILLIRInstruction implements MoveOp {
+
+        private Kind moveKind;
+
+        public AbstractMoveOp(Kind moveKind) {
+            this.moveKind = moveKind;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+            move(moveKind, crb, masm, getResult(), getInput());
+        }
+    }
+
     @Opcode("MOVE")
-    public static class SpillMoveOp extends HSAILLIRInstruction implements MoveOp {
+    public static class SpillMoveOp extends AbstractMoveOp {
 
         @Def({REG, STACK}) protected AllocatableValue result;
         @Use({REG, STACK, CONST}) protected Value input;
 
-        public SpillMoveOp(AllocatableValue result, Value input) {
+        public SpillMoveOp(Kind moveKind, AllocatableValue result, Value input) {
+            super(moveKind);
             this.result = result;
             this.input = input;
         }
 
         @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            move(crb, masm, getResult(), getInput());
-        }
-
-        @Override
         public Value getInput() {
             return input;
         }
@@ -76,22 +86,18 @@
     }
 
     @Opcode("MOVE")
-    public static class MoveToRegOp extends HSAILLIRInstruction implements MoveOp {
+    public static class MoveToRegOp extends AbstractMoveOp {
 
         @Def({REG, HINT}) protected AllocatableValue result;
         @Use({REG, STACK, CONST}) protected Value input;
 
-        public MoveToRegOp(AllocatableValue result, Value input) {
+        public MoveToRegOp(Kind moveKind, AllocatableValue result, Value input) {
+            super(moveKind);
             this.result = result;
             this.input = input;
         }
 
         @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            move(crb, masm, getResult(), getInput());
-        }
-
-        @Override
         public Value getInput() {
             return input;
         }
@@ -103,22 +109,18 @@
     }
 
     @Opcode("MOVE")
-    public static class MoveFromRegOp extends HSAILLIRInstruction implements MoveOp {
+    public static class MoveFromRegOp extends AbstractMoveOp {
 
         @Def({REG, STACK}) protected AllocatableValue result;
         @Use({REG, CONST, HINT}) protected Value input;
 
-        public MoveFromRegOp(AllocatableValue result, Value input) {
+        public MoveFromRegOp(Kind moveKind, AllocatableValue result, Value input) {
+            super(moveKind);
             this.result = result;
             this.input = input;
         }
 
         @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            move(crb, masm, getResult(), getInput());
-        }
-
-        @Override
         public Value getInput() {
             return input;
         }
@@ -293,7 +295,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            masm.emitMov(scratch, input);
+            masm.emitMov(kind, scratch, input);
             boolean testForNull = (kind == Kind.Object);
             encodePointer(masm, scratch, base, shift, alignment, testForNull);
             if (state != null) {
@@ -304,6 +306,59 @@
         }
     }
 
+    public static class CompressPointer extends HSAILLIRInstruction {
+
+        private final long base;
+        private final int shift;
+        private final int alignment;
+
+        @Def({REG}) protected AllocatableValue result;
+        @Temp({REG, HINT}) protected AllocatableValue scratch;
+        @Use({REG}) protected AllocatableValue input;
+
+        public CompressPointer(AllocatableValue result, AllocatableValue scratch, AllocatableValue input, long base, int shift, int alignment) {
+            this.result = result;
+            this.scratch = scratch;
+            this.input = input;
+            this.base = base;
+            this.shift = shift;
+            this.alignment = alignment;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+            masm.emitMov(Kind.Long, scratch, input);
+            boolean testForNull = (input.getKind() == Kind.Object);
+            encodePointer(masm, scratch, base, shift, alignment, testForNull);
+            masm.emitConvert(result, scratch, "u32", "u64");
+        }
+    }
+
+    public static class UncompressPointer extends HSAILLIRInstruction {
+
+        private final long base;
+        private final int shift;
+        private final int alignment;
+
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG}) protected AllocatableValue input;
+
+        public UncompressPointer(AllocatableValue result, AllocatableValue input, long base, int shift, int alignment) {
+            this.result = result;
+            this.input = input;
+            this.base = base;
+            this.shift = shift;
+            this.alignment = alignment;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+            masm.emitConvert(result, input, "u64", "u32");
+            boolean testForNull = (result.getKind() == Kind.Object);
+            decodePointer(masm, result, base, shift, alignment, testForNull);
+        }
+    }
+
     private static void encodePointer(HSAILAssembler masm, Value scratch, long base, int shift, int alignment, boolean testForNull) {
         if (base == 0 && shift == 0) {
             return;
@@ -408,9 +463,9 @@
             // assume any encoded or decoded value could be null
             boolean testForNull = true;
             // set up scratch registers to be encoded versions
-            masm.emitMov(scratchCmpValue64, cmpValue);
+            masm.emitMov(Kind.Long, scratchCmpValue64, cmpValue);
             encodePointer(masm, scratchCmpValue64, base, shift, alignment, testForNull);
-            masm.emitMov(scratchNewValue64, newValue);
+            masm.emitMov(Kind.Long, scratchNewValue64, newValue);
             encodePointer(masm, scratchNewValue64, base, shift, alignment, testForNull);
             // get encoded versions into 32-bit registers
             masm.emitConvertForceUnsigned(scratchCmpValue32, scratchCmpValue64);
@@ -441,24 +496,24 @@
     }
 
     @SuppressWarnings("unused")
-    public static void move(CompilationResultBuilder crb, HSAILAssembler masm, Value result, Value input) {
+    public static void move(Kind kind, CompilationResultBuilder crb, HSAILAssembler masm, Value result, Value input) {
         if (isRegister(input)) {
             if (isRegister(result)) {
-                masm.emitMov(result, input);
+                masm.emitMov(kind, result, input);
             } else if (isStackSlot(result)) {
-                masm.emitSpillStore(input, result);
+                masm.emitSpillStore(kind, input, result);
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
         } else if (isStackSlot(input)) {
             if (isRegister(result)) {
-                masm.emitSpillLoad(result, input);
+                masm.emitSpillLoad(kind, result, input);
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
         } else if (isConstant(input)) {
             if (isRegister(result)) {
-                masm.emitMov(result, input);
+                masm.emitMov(kind, result, input);
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Wed Apr 02 15:26:58 2014 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess {
+
+    @Input private ValueNode value;
+    @Input(notDataflow = true) private FrameState stateAfter;
+    private final boolean initialization;
+
+    @Input private Node lastLocationAccess;
+
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    public void setStateAfter(FrameState x) {
+        assert x == null || x.isAlive() : "frame state must be in a graph";
+        updateUsages(stateAfter, x);
+        stateAfter = x;
+    }
+
+    public boolean hasSideEffect() {
+        return true;
+    }
+
+    public ValueNode value() {
+        return value;
+    }
+
+    /**
+     * Returns whether this write is the initialization of the written location. If it is true, the
+     * old value of the memory location is either uninitialized or zero. If it is false, the memory
+     * location is guaranteed to contain a valid value or zero.
+     */
+    public boolean isInitialization() {
+        return initialization;
+    }
+
+    public AbstractWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible) {
+        this(object, value, location, barrierType, compressible, false);
+    }
+
+    public AbstractWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
+        super(object, location, StampFactory.forVoid(), barrierType, compressible);
+        this.value = value;
+        this.initialization = initialization;
+    }
+
+    @Override
+    public LocationIdentity getLocationIdentity() {
+        return location().getLocationIdentity();
+    }
+
+    public MemoryNode getLastLocationAccess() {
+        return (MemoryNode) lastLocationAccess;
+    }
+
+    public void setLastLocationAccess(MemoryNode lla) {
+        Node newLla = ValueNodeUtil.asNode(lla);
+        updateUsages(lastLocationAccess, newLla);
+        lastLocationAccess = newLla;
+    }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Apr 02 15:26:58 2014 +0200
@@ -62,7 +62,8 @@
     @Override
     public void generate(NodeLIRBuiderTool gen) {
         Value address = location().generateAddress(gen, gen.operand(object()));
-        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(location().getValueKind(), address, this));
+        PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Wed Apr 02 15:26:58 2014 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Read a raw memory location according to Java field or array read semantics. It will perform read
+ * barriers, implicit conversions and optionally oop uncompression.
+ */
+public final class JavaReadNode extends FixedAccessNode implements Lowerable {
+
+    public JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
+        super(object, location, StampFactory.forKind(location.getValueKind()), barrierType, compressible);
+    }
+
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java	Wed Apr 02 15:26:58 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Write a raw memory location according to Java field or array write semantics. It will perform
+ * write barriers, implicit conversions and optionally oop compression.
+ */
+public final class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single {
+
+    public JavaWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
+        super(object, value, location, barrierType, compressible, initialization);
+    }
+
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Apr 02 15:26:58 2014 +0200
@@ -55,7 +55,8 @@
     @Override
     public void generate(NodeLIRBuiderTool gen) {
         Value address = location().generateAddress(gen, gen.operand(object()));
-        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(location().getValueKind(), address, this));
+        PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Apr 02 15:26:58 2014 +0200
@@ -23,60 +23,23 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.LocationNode.Location;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}.
  */
-public final class WriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, MemoryAccess, Simplifiable, Virtualizable {
-
-    @Input private ValueNode value;
-    @Input(notDataflow = true) private FrameState stateAfter;
-    private final boolean initialization;
-
-    @Input private Node lastLocationAccess;
-
-    public FrameState stateAfter() {
-        return stateAfter;
-    }
-
-    public void setStateAfter(FrameState x) {
-        assert x == null || x.isAlive() : "frame state must be in a graph";
-        updateUsages(stateAfter, x);
-        stateAfter = x;
-    }
-
-    public boolean hasSideEffect() {
-        return true;
-    }
-
-    public ValueNode value() {
-        return value;
-    }
-
-    /**
-     * Returns whether this write is the initialization of the written location. If it is true, the
-     * old value of the memory location is either uninitialized or zero. If it is false, the memory
-     * location is guaranteed to contain a valid value or zero.
-     */
-    public boolean isInitialization() {
-        return initialization;
-    }
+public final class WriteNode extends AbstractWriteNode implements LIRLowerable, Simplifiable, Virtualizable {
 
     public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible) {
-        this(object, value, location, barrierType, compressible, false);
+        super(object, value, location, barrierType, compressible);
     }
 
     public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
-        super(object, location, StampFactory.forVoid(), barrierType, compressible);
-        this.value = value;
-        this.initialization = initialization;
+        super(object, value, location, barrierType, compressible, initialization);
     }
 
     @Override
@@ -90,7 +53,8 @@
         } else {
             v = gen.operand(value());
         }
-        gen.getLIRGeneratorTool().emitStore(location().getValueKind(), address, v, this);
+        PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(value().stamp());
+        gen.getLIRGeneratorTool().emitStore(writeKind, address, v, this);
     }
 
     @Override
@@ -104,21 +68,6 @@
     public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter BarrierType barrierType, @ConstantNodeParameter boolean compressible);
 
     @Override
-    public LocationIdentity getLocationIdentity() {
-        return location().getLocationIdentity();
-    }
-
-    public MemoryNode getLastLocationAccess() {
-        return (MemoryNode) lastLocationAccess;
-    }
-
-    public void setLastLocationAccess(MemoryNode lla) {
-        Node newLla = ValueNodeUtil.asNode(lla);
-        updateUsages(lastLocationAccess, newLla);
-        lastLocationAccess = newLla;
-    }
-
-    @Override
     public void virtualize(VirtualizerTool tool) {
         if (location() instanceof ConstantLocationNode) {
             ConstantLocationNode constantLocation = (ConstantLocationNode) location();
@@ -133,12 +82,4 @@
             }
         }
     }
-
-    public MemoryCheckpoint asMemoryCheckpoint() {
-        return this;
-    }
-
-    public MemoryPhiNode asMemoryPhi() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Apr 02 15:26:58 2014 +0200
@@ -37,9 +37,9 @@
 
     ForeignCallsProvider getForeignCalls();
 
-    Value emitLoad(Kind kind, Value address, Access access);
+    Value emitLoad(PlatformKind kind, Value address, Access access);
 
-    void emitStore(Kind kind, Value address, Value input, Access access);
+    void emitStore(PlatformKind kind, Value address, Value input, Access access);
 
     void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting);
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Wed Apr 02 15:26:58 2014 +0200
@@ -101,7 +101,7 @@
     }
 
     private static void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
-        ReadNode read = (ReadNode) graph.start().next();
+        JavaReadNode read = (JavaReadNode) graph.start().next();
         Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind());
         Assert.assertEquals(graph.getParameter(0), read.object());
 
@@ -124,7 +124,7 @@
     }
 
     private static void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
-        WriteNode write = (WriteNode) graph.start().next();
+        JavaWriteNode write = (JavaWriteNode) graph.start().next();
         Assert.assertEquals(graph.getParameter(2), write.value());
         Assert.assertEquals(graph.getParameter(0), write.object());
         Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Wed Apr 02 15:26:58 2014 +0200
@@ -109,7 +109,7 @@
     private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
         WordCastNode cast = (WordCastNode) graph.start().next();
 
-        ReadNode read = (ReadNode) cast.next();
+        JavaReadNode read = (JavaReadNode) cast.next();
         Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind());
 
         Assert.assertEquals(cast, read.object());
@@ -137,7 +137,7 @@
     private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
         WordCastNode cast = (WordCastNode) graph.start().next();
 
-        WriteNode write = (WriteNode) cast.next();
+        JavaWriteNode write = (JavaWriteNode) cast.next();
         Assert.assertEquals(graph.getParameter(2), write.value());
         Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci);
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Wed Apr 02 15:26:58 2014 +0200
@@ -611,8 +611,9 @@
     Object readObject(WordBase offset);
 
     /**
-     * Reads the memory at address {@code (this + offset)}. This particular access can allow
-     * decompression and read barriers (G1 referent field).
+     * Reads the memory at address {@code (this + offset)}. This access will decompress the oop if
+     * the VM uses compressed oops, and it can be parameterized to allow read barriers (G1 referent
+     * field).
      * <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
@@ -620,10 +621,9 @@
      * 
      * @param offset the signed offset for the memory access
      * @param barrierType the type of the read barrier to be added
-     * @param compressible whether or not the object is a decompression candidate
      * @return the result of the memory access
      */
-    Object readObject(WordBase offset, BarrierType barrierType, boolean compressible);
+    Object readObject(WordBase offset, BarrierType barrierType);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -707,15 +707,15 @@
     Object readObject(int offset);
 
     /**
-     * Reads the memory at address {@code (this + offset)}. This particular access can be
-     * parameterized to allow decompression and read barriers (G1 referent field).
+     * Reads the memory at address {@code (this + offset)}. This access will decompress the oop if
+     * the VM uses compressed oops, and it can be parameterized to allow read barriers (G1 referent
+     * field).
      * 
      * @param offset the signed offset for the memory access
      * @param barrierType the type of the read barrier to be added
-     * @param compressible whether or not the object is a decompression candidate
      * @return the result of the memory access
      */
-    Object readObject(int offset, BarrierType barrierType, boolean compressible);
+    Object readObject(int offset, BarrierType barrierType);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Wed Apr 02 15:26:58 2014 +0200
@@ -909,7 +909,7 @@
     public native Object readObject(WordBase offset);
 
     @Operation(opcode = Opcode.READ_HEAP)
-    public native Object readObject(WordBase offset, BarrierType barrierType, boolean compressible);
+    public native Object readObject(WordBase offset, BarrierType barrierType);
 
     @Override
     @Operation(opcode = Opcode.READ)
@@ -966,8 +966,8 @@
     }
 
     @Operation(opcode = Opcode.READ_HEAP)
-    public Object readObject(int offset, BarrierType barrierType, boolean compressible) {
-        return readObject(signed(offset), barrierType, compressible);
+    public Object readObject(int offset, BarrierType barrierType) {
+        return readObject(signed(offset), barrierType);
     }
 
     @Override
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Apr 02 14:43:52 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Apr 02 15:26:58 2014 +0200
@@ -214,16 +214,15 @@
                 } else {
                     location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
                 }
-                replace(invoke, readOp(graph, arguments.get(0), invoke, location, StampFactory.forKind(readKind.getStackKind()), BarrierType.NONE, false));
+                replace(invoke, readOp(graph, arguments.get(0), invoke, location, BarrierType.NONE, false));
                 break;
             }
             case READ_HEAP: {
-                assert arguments.size() == 4;
+                assert arguments.size() == 3;
                 Kind readKind = asKind(callTargetNode.returnType());
                 LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
                 BarrierType barrierType = (BarrierType) arguments.get(2).asConstant().asObject();
-                boolean compressible = arguments.get(3).asConstant().asInt() != 0;
-                replace(invoke, readOp(graph, arguments.get(0), invoke, location, StampFactory.forKind(readKind.getStackKind()), barrierType, compressible));
+                replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, true));
                 break;
             }
             case WRITE:
@@ -370,8 +369,8 @@
         return IndexedLocationNode.create(locationIdentity, readKind, 0, fromSigned(graph, offset), graph, 1);
     }
 
-    protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, Stamp stamp, BarrierType barrierType, boolean compressible) {
-        ReadNode read = graph.add(new ReadNode(base, location, stamp, barrierType, compressible));
+    protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) {
+        JavaReadNode read = graph.add(new JavaReadNode(base, location, barrierType, compressible));
         graph.addBeforeFixed(invoke.asNode(), read);
         /*
          * The read must not float outside its block otherwise it may float above an explicit zero
@@ -383,7 +382,7 @@
 
     protected 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, BarrierType.NONE, false, op == Opcode.INITIALIZE));
+        JavaWriteNode write = graph.add(new JavaWriteNode(base, value, location, BarrierType.NONE, false, op == Opcode.INITIALIZE));
         write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.asNode(), write);
         return write;
--- a/mx/projects	Wed Apr 02 14:43:52 2014 +0200
+++ b/mx/projects	Wed Apr 02 15:26:58 2014 +0200
@@ -583,7 +583,7 @@
 # graal.hsail
 project@com.oracle.graal.hsail@subDir=graal
 project@com.oracle.graal.hsail@sourceDirs=src
-project@com.oracle.graal.hsail@dependencies=com.oracle.graal.graph
+project@com.oracle.graal.hsail@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.hsail@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hsail@javaCompliance=1.8
 
@@ -618,7 +618,7 @@
 # graal.asm.hsail
 project@com.oracle.graal.asm.hsail@subDir=graal
 project@com.oracle.graal.asm.hsail@sourceDirs=src
-project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm
+project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm,com.oracle.graal.graph
 project@com.oracle.graal.asm.hsail@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.hsail@javaCompliance=1.8