changeset 7904:c8f2002d2194

reintroduce default Word read/write operations, more tests
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 28 Feb 2013 12:07:59 +0100
parents f19c4d447e73
children 38a597987357
files graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/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
diffstat 4 files changed, 708 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/PointerTest.java	Thu Feb 28 11:50:06 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/PointerTest.java	Thu Feb 28 12:07:59 2013 +0100
@@ -26,8 +26,6 @@
 
 import org.junit.*;
 
-import sun.security.action.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
@@ -76,6 +74,13 @@
     }
 
     @Test
+    public void test_read3() {
+        for (Kind kind : KINDS) {
+            assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.UNKNOWN_LOCATION);
+        }
+    }
+
+    @Test
     public void test_write1() {
         for (Kind kind : KINDS) {
             assertWrite(parse("write" + kind.name() + "1"), kind, false, ID);
@@ -89,6 +94,13 @@
         }
     }
 
+    @Test
+    public void test_write3() {
+        for (Kind kind : KINDS) {
+            assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
+        }
+    }
+
     private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) {
         ReadNode read = (ReadNode) graph.start().next();
         Assert.assertEquals(kind.getStackKind(), read.kind());
@@ -155,6 +167,11 @@
     }
 
     @Snippet
+    public static byte readByte3(Object o, int offset) {
+        return Word.fromObject(o).readByte(offset);
+    }
+
+    @Snippet
     public static void writeByte1(Object o, int offset, byte value) {
         Word.fromObject(o).writeByte(offset, value, ID);
     }
@@ -165,6 +182,11 @@
     }
 
     @Snippet
+    public static void writeByte3(Object o, int offset, byte value) {
+        Word.fromObject(o).writeByte(offset, value);
+    }
+
+    @Snippet
     public static char readChar1(Object o, int offset) {
         return Word.fromObject(o).readChar(offset, ID);
     }
@@ -175,6 +197,11 @@
     }
 
     @Snippet
+    public static char readChar3(Object o, int offset) {
+        return Word.fromObject(o).readChar(offset);
+    }
+
+    @Snippet
     public static void writeChar1(Object o, int offset, char value) {
         Word.fromObject(o).writeChar(offset, value, ID);
     }
@@ -185,6 +212,11 @@
     }
 
     @Snippet
+    public static void writeChar3(Object o, int offset, char value) {
+        Word.fromObject(o).writeChar(offset, value);
+    }
+
+    @Snippet
     public static short readShort1(Object o, int offset) {
         return Word.fromObject(o).readShort(offset, ID);
     }
@@ -195,6 +227,11 @@
     }
 
     @Snippet
+    public static short readShort3(Object o, int offset) {
+        return Word.fromObject(o).readShort(offset);
+    }
+
+    @Snippet
     public static void writeShort1(Object o, int offset, short value) {
         Word.fromObject(o).writeShort(offset, value, ID);
     }
@@ -205,6 +242,11 @@
     }
 
     @Snippet
+    public static void writeShort3(Object o, int offset, short value) {
+        Word.fromObject(o).writeShort(offset, value);
+    }
+
+    @Snippet
     public static int readInt1(Object o, int offset) {
         return Word.fromObject(o).readInt(offset, ID);
     }
@@ -215,6 +257,11 @@
     }
 
     @Snippet
+    public static int readInt3(Object o, int offset) {
+        return Word.fromObject(o).readInt(offset);
+    }
+
+    @Snippet
     public static void writeInt1(Object o, int offset, int value) {
         Word.fromObject(o).writeInt(offset, value, ID);
     }
@@ -225,6 +272,11 @@
     }
 
     @Snippet
+    public static void writeInt3(Object o, int offset, int value) {
+        Word.fromObject(o).writeInt(offset, value);
+    }
+
+    @Snippet
     public static long readLong1(Object o, int offset) {
         return Word.fromObject(o).readLong(offset, ID);
     }
@@ -235,6 +287,11 @@
     }
 
     @Snippet
+    public static long readLong3(Object o, int offset) {
+        return Word.fromObject(o).readLong(offset);
+    }
+
+    @Snippet
     public static void writeLong1(Object o, int offset, long value) {
         Word.fromObject(o).writeLong(offset, value, ID);
     }
@@ -245,6 +302,11 @@
     }
 
     @Snippet
+    public static void writeLong3(Object o, int offset, long value) {
+        Word.fromObject(o).writeLong(offset, value);
+    }
+
+    @Snippet
     public static float readFloat1(Object o, int offset) {
         return Word.fromObject(o).readFloat(offset, ID);
     }
@@ -255,6 +317,11 @@
     }
 
     @Snippet
+    public static float readFloat3(Object o, int offset) {
+        return Word.fromObject(o).readFloat(offset);
+    }
+
+    @Snippet
     public static void writeFloat1(Object o, int offset, float value) {
         Word.fromObject(o).writeFloat(offset, value, ID);
     }
@@ -265,6 +332,11 @@
     }
 
     @Snippet
+    public static void writeFloat3(Object o, int offset, float value) {
+        Word.fromObject(o).writeFloat(offset, value);
+    }
+
+    @Snippet
     public static double readDouble1(Object o, int offset) {
         return Word.fromObject(o).readDouble(offset, ID);
     }
@@ -275,6 +347,11 @@
     }
 
     @Snippet
+    public static double readDouble3(Object o, int offset) {
+        return Word.fromObject(o).readDouble(offset);
+    }
+
+    @Snippet
     public static void writeDouble1(Object o, int offset, double value) {
         Word.fromObject(o).writeDouble(offset, value, ID);
     }
@@ -285,6 +362,11 @@
     }
 
     @Snippet
+    public static void writeDouble3(Object o, int offset, double value) {
+        Word.fromObject(o).writeDouble(offset, value);
+    }
+
+    @Snippet
     public static Object readObject1(Object o, int offset) {
         return Word.fromObject(o).readObject(offset, ID);
     }
@@ -295,6 +377,11 @@
     }
 
     @Snippet
+    public static Object readObject3(Object o, int offset) {
+        return Word.fromObject(o).readObject(offset);
+    }
+
+    @Snippet
     public static void writeObject1(Object o, int offset, Object value) {
         Word.fromObject(o).writeObject(offset, value, ID);
     }
@@ -304,4 +391,9 @@
         Word.fromObject(o).writeObject(Word.signed(offset), value, ID);
     }
 
+    @Snippet
+    public static void writeObject3(Object o, int offset, Object value) {
+        Word.fromObject(o).writeObject(offset, value);
+    }
+
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Thu Feb 28 11:50:06 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Thu Feb 28 12:07:59 2013 +0100
@@ -467,6 +467,402 @@
      */
     void writeObject(int offset, Object val, Object locationIdentity);
 
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    byte readByte(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    char readChar(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    short readShort(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    int readInt(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    long readLong(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    float readFloat(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    double readDouble(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Word readWord(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Object readObject(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    byte readByte(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    char readChar(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    short readShort(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    int readInt(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    long readLong(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    float readFloat(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    double readDouble(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Word readWord(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     */
+    Object readObject(int offset);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeByte(WordBase offset, byte val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeChar(WordBase offset, char val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeShort(WordBase offset, short val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeInt(WordBase offset, int val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeLong(WordBase offset, long val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeFloat(WordBase offset, float val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeDouble(WordBase offset, double val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeWord(WordBase offset, WordBase val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeObject(WordBase offset, Object val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeByte(int offset, byte val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeChar(int offset, char val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeShort(int offset, short val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeInt(int offset, int val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeLong(int offset, long val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeFloat(int offset, float val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeDouble(int offset, double val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeWord(int offset, WordBase val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     */
+    void writeObject(int offset, Object val);
+
     // Math functions that are defined in Unsigned, but known to preserve the
     // pointer-characteristics.
     // It is therefore safe that they return a static type of Pointer instead of Unsigned.
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Thu Feb 28 11:50:06 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Thu Feb 28 12:07:59 2013 +0100
@@ -808,6 +808,218 @@
     }
 
     @Override
+    @Operation(opcode = Opcode.READ)
+    public byte readByte(WordBase offset) {
+        return unsafe.getByte(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public char readChar(WordBase offset) {
+        return unsafe.getChar(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public short readShort(WordBase offset) {
+        return unsafe.getShort(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public int readInt(WordBase offset) {
+        return unsafe.getInt(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public long readLong(WordBase offset) {
+        return unsafe.getLong(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public float readFloat(WordBase offset) {
+        return unsafe.getFloat(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public double readDouble(WordBase offset) {
+        return unsafe.getDouble(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Word readWord(WordBase offset) {
+        return box(unsafe.getAddress(add((Word) offset).unbox()));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public native Object readObject(WordBase offset);
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public byte readByte(int offset) {
+        return readByte(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public char readChar(int offset) {
+        return readChar(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public short readShort(int offset) {
+        return readShort(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public int readInt(int offset) {
+        return readInt(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public long readLong(int offset) {
+        return readLong(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public float readFloat(int offset) {
+        return readFloat(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public double readDouble(int offset) {
+        return readDouble(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Word readWord(int offset) {
+        return readWord(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Object readObject(int offset) {
+        return readObject(signed(offset));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeByte(WordBase offset, byte val) {
+        unsafe.putByte(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeChar(WordBase offset, char val) {
+        unsafe.putChar(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeShort(WordBase offset, short val) {
+        unsafe.putShort(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeInt(WordBase offset, int val) {
+        unsafe.putInt(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeLong(WordBase offset, long val) {
+        unsafe.putLong(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeFloat(WordBase offset, float val) {
+        unsafe.putFloat(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeDouble(WordBase offset, double val) {
+        unsafe.putDouble(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeWord(WordBase offset, WordBase val) {
+        unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public native void writeObject(WordBase offset, Object val);
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeByte(int offset, byte val) {
+        writeByte(signed(offset), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeChar(int offset, char val) {
+        writeChar(signed(offset), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeShort(int offset, short val) {
+        writeShort(signed(offset), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeInt(int offset, int val) {
+        writeInt(signed(offset), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeLong(int offset, long val) {
+        writeLong(signed(offset), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeFloat(int offset, float val) {
+        writeFloat(signed(offset), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeDouble(int offset, double val) {
+        writeDouble(signed(offset), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeWord(int offset, WordBase val) {
+        writeWord(signed(offset), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeObject(int offset, Object val) {
+        writeObject(signed(offset), val);
+    }
+
+    @Override
     public final boolean equals(Object obj) {
         throw GraalInternalError.shouldNotReachHere("equals must not be called on words");
     }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Feb 28 11:50:06 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Feb 28 12:07:59 2013 +0100
@@ -138,15 +138,17 @@
                         break;
 
                     case READ:
-                        assert arguments.size() == 3;
+                        assert arguments.size() == 2 || arguments.size() == 3;
                         Kind readKind = asKind(callTargetNode.returnType());
-                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, readKind, arguments.get(2).asConstant().asObject()));
+                        Object readLocation = arguments.size() == 2 ? LocationNode.UNKNOWN_LOCATION : arguments.get(2).asConstant().asObject();
+                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, readKind, readLocation));
                         break;
 
                     case WRITE:
-                        assert arguments.size() == 4;
+                        assert arguments.size() == 3 || arguments.size() == 4;
                         Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass()));
-                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, writeKind, arguments.get(3).asConstant().asObject()));
+                        Object writeLocation = arguments.size() == 3 ? LocationNode.ANY_LOCATION : arguments.get(3).asConstant().asObject();
+                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, writeKind, writeLocation));
                         break;
 
                     case ZERO: