changeset 10557:c636b4399ffa

Merge
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Thu, 27 Jun 2013 21:03:55 +0200
parents 35783fbfcf28 (diff) 97caf20971ed (current diff)
children 60ce5bd6e104
files
diffstat 10 files changed, 267 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jun 27 18:21:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jun 27 21:03:55 2013 +0200
@@ -618,7 +618,7 @@
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != Kind.Illegal;
-            lowerUnsafeLoad(load);
+            lowerUnsafeLoad(load, tool);
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
             IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
@@ -783,6 +783,10 @@
             writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
         } else if (n instanceof SerialArrayRangeWriteBarrier) {
             writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
+        } else if (n instanceof G1ArrayRangePreWriteBarrier) {
+            writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, tool);
+        } else if (n instanceof G1ArrayRangePostWriteBarrier) {
+            writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool);
         } else if (n instanceof NewMultiArrayNode) {
             if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
                 newObjectSnippets.lower((NewMultiArrayNode) n);
@@ -851,17 +855,18 @@
      * 
      * </pre>
      * 
-     * TODO (ck): Replace the code below with a snippet.
+     * TODO (ck): Replace the code below with a snippet, properly fix the issue with the unsafe
+     * loads generated by the array copy intrinsics (robust assertions).
      * 
      */
-    private void lowerUnsafeLoad(UnsafeLoadNode load) {
+    private void lowerUnsafeLoad(UnsafeLoadNode load, LoweringTool tool) {
         StructuredGraph graph = load.graph();
         boolean compress = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
         if (config().useG1GC && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object && !load.object().objectStamp().alwaysNull() && load.object().objectStamp().type() != null &&
-                        !(load.object().objectStamp().type().isArray())) {
+                        !(load.object().objectStamp().type().isArray()) && tool.getLoweringType() != LoweringType.AFTER_GUARDS) {
             IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
             // Calculate offset+displacement
-            IntegerAddNode addNode = graph.add(new IntegerAddNode(Kind.Long, load.offset(), ConstantNode.forInt(load.displacement(), graph)));
+            IntegerAddNode addNode = graph.add(new IntegerAddNode(Kind.Long, load.offset(), ConstantNode.forLong(load.displacement(), graph)));
             // Compare previous result with referent offset (16)
             CompareNode offsetCondition = CompareNode.createCompareNode(Condition.EQ, addNode, ConstantNode.forLong(referentOffset(), graph));
             // Instance of unsafe load is java.lang.ref.Reference
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Thu Jun 27 18:21:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Thu Jun 27 21:03:55 2013 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.hotspot.phases;
 
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.replacements.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.extended.*;
@@ -55,7 +55,7 @@
 
     private static void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
         if (node.getWriteBarrierType() == WriteBarrierType.PRECISE) {
-            assert HotSpotReplacementsUtil.useG1GC();
+            assert useG1GC();
             graph.addAfterFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node, node.location(), false)));
         } else {
             assert node.getWriteBarrierType() == WriteBarrierType.NONE : "Non precise write barrier has been attached to read node.";
@@ -65,14 +65,14 @@
     private static void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
         WriteBarrierType barrierType = node.getWriteBarrierType();
         if (barrierType == WriteBarrierType.PRECISE) {
-            if (HotSpotReplacementsUtil.useG1GC()) {
+            if (useG1GC()) {
                 graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true)));
                 graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.value(), node.location(), true)));
             } else {
                 graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), true)));
             }
         } else if (barrierType == WriteBarrierType.IMPRECISE) {
-            if (HotSpotReplacementsUtil.useG1GC()) {
+            if (useG1GC()) {
                 graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true)));
                 graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.value(), node.location(), false)));
             } else {
@@ -87,14 +87,14 @@
     private static void addCASBarriers(CompareAndSwapNode node, StructuredGraph graph) {
         WriteBarrierType barrierType = node.getWriteBarrierType();
         if (barrierType == WriteBarrierType.PRECISE) {
-            if (HotSpotReplacementsUtil.useG1GC()) {
+            if (useG1GC()) {
                 graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false)));
                 graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.newValue(), node.getLocation(), true)));
             } else {
                 graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getLocation(), true)));
             }
         } else if (barrierType == WriteBarrierType.IMPRECISE) {
-            if (HotSpotReplacementsUtil.useG1GC()) {
+            if (useG1GC()) {
                 graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false)));
                 graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.newValue(), node.getLocation(), false)));
             } else {
@@ -106,8 +106,11 @@
     }
 
     private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) {
-        if (HotSpotReplacementsUtil.useG1GC()) {
-            throw new GraalInternalError("G1 does not yet support barriers for ArrayCopy Intrinsics. Run with -G:-IntrinsifyArrayCopy");
+        if (useG1GC()) {
+            G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+            G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+            graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier);
+            graph.addAfterFixed(node, g1ArrayRangePostWriteBarrier);
         } else {
             SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
             graph.addAfterFixed(node, serialArrayRangeWriteBarrier);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Thu Jun 27 18:21:13 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Thu Jun 27 21:03:55 2013 +0200
@@ -111,7 +111,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 (doLoad) {
-                previousOop = (Word) Word.fromObject(UnsafeLoadNode.load(field, 0, 0, Kind.Object));
+                previousOop = (Word) Word.fromObject(field.readObjectCompressed(0));
             }
             // If the previous value is null the barrier should not be issued.
             if (previousOop.notEqual(0)) {
@@ -187,6 +187,79 @@
         }
     }
 
+    @Snippet
+    public static void g1ArrayRangePreWriteBarrier(Object object, int startIndex, int length) {
+        Object dest = FixedValueAnchorNode.getObject(object);
+        Word thread = thread();
+        byte markingValue = thread.readByte(g1SATBQueueMarkingOffset());
+        Word bufferAddress = thread.readWord(g1SATBQueueBufferOffset());
+        Word indexAddress = thread.add(g1SATBQueueIndexOffset());
+        Word indexValue = indexAddress.readWord(0);
+
+        // If the concurrent marker is not enabled return.
+        if (markingValue == (byte) 0) {
+            return;
+        }
+        Word oop;
+        final int scale = arrayIndexScale(Kind.Object);
+        int header = arrayBaseOffset(Kind.Object);
+
+        for (int i = startIndex; i < length; i++) {
+            Word address = (Word) Word.fromObject(dest).add(header).add(Word.unsigned(i * (long) scale));
+            oop = (Word) Word.fromObject(address.readObjectCompressed(0));
+            if (oop.notEqual(0)) {
+                if (indexValue.notEqual(0)) {
+                    Word nextIndex = indexValue.subtract(wordSize());
+                    Word logAddress = bufferAddress.add(nextIndex);
+                    // Log the object to be marked as well as update the SATB's buffer next index.
+                    logAddress.writeWord(0, oop);
+                    indexAddress.writeWord(0, nextIndex);
+                } else {
+                    g1PreBarrierStub(G1WBPRECALL, oop.toObject());
+                }
+            }
+        }
+    }
+
+    @Snippet
+    public static void g1ArrayRangePostWriteBarrier(Object object, int startIndex, int length) {
+        Object dest = FixedValueAnchorNode.getObject(object);
+        Word thread = thread();
+        Word bufferAddress = thread.readWord(g1CardQueueBufferOffset());
+        Word indexAddress = thread.add(g1CardQueueIndexOffset());
+        Word indexValue = thread.readWord(g1CardQueueIndexOffset());
+
+        int cardShift = cardTableShift();
+        long cardStart = cardTableStart();
+        final int scale = arrayIndexScale(Kind.Object);
+        int header = arrayBaseOffset(Kind.Object);
+        long dstAddr = GetObjectAddressNode.get(dest);
+        long start = (dstAddr + header + (long) startIndex * scale) >>> cardShift;
+        long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift;
+        long count = end - start + 1;
+
+        while (count-- > 0) {
+            Word cardAddress = Word.unsigned((start + cardStart) + count);
+            byte cardByte = cardAddress.readByte(0);
+            // If the card is already dirty, (hence already enqueued) skip the insertion.
+            if (cardByte != (byte) 0) {
+                cardAddress.writeByte(0, (byte) 0);
+                // If the thread local card queue is full, issue a native call which will
+                // initialize a new one and add the card entry.
+                if (indexValue.notEqual(0)) {
+                    Word nextIndex = indexValue.subtract(wordSize());
+                    Word logAddress = bufferAddress.add(nextIndex);
+                    // Log the object to be scanned as well as update
+                    // the card queue's next index.
+                    logAddress.writeWord(0, cardAddress);
+                    indexAddress.writeWord(0, nextIndex);
+                } else {
+                    g1PostBarrierStub(G1WBPOSTCALL, cardAddress);
+                }
+            }
+        }
+    }
+
     public static final ForeignCallDescriptor G1WBPRECALL = new ForeignCallDescriptor("write_barrier_pre", void.class, Object.class);
 
     @NodeIntrinsic(ForeignCallNode.class)
@@ -203,6 +276,8 @@
         private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier");
         private final SnippetInfo g1PreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier");
         private final SnippetInfo g1PostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PostWriteBarrier");
+        private final SnippetInfo g1ArrayRangePreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier");
+        private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
             super(runtime, replacements, target);
@@ -241,5 +316,21 @@
             args.addConst("usePrecise", writeBarrierPost.usePrecise());
             template(args).instantiate(runtime, writeBarrierPost, DEFAULT_REPLACER, args);
         }
+
+        public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
+            Arguments args = new Arguments(g1ArrayRangePreWriteBarrier);
+            args.add("object", arrayRangeWriteBarrier.getObject());
+            args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
+            args.add("length", arrayRangeWriteBarrier.getLength());
+            template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
+        }
+
+        public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
+            Arguments args = new Arguments(g1ArrayRangePostWriteBarrier);
+            args.add("object", arrayRangeWriteBarrier.getObject());
+            args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
+            args.add("length", arrayRangeWriteBarrier.getLength());
+            template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ArrayRangeWriteBarrier.java	Thu Jun 27 21:03:55 2013 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+public abstract class ArrayRangeWriteBarrier extends WriteBarrier {
+
+    @Input private ValueNode startIndex;
+    @Input private ValueNode length;
+
+    public ValueNode getStartIndex() {
+        return startIndex;
+    }
+
+    public ValueNode getLength() {
+        return length;
+    }
+
+    public ArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
+        super(object, null, true);
+        this.startIndex = startIndex;
+        this.length = length;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ArrayRangePostWriteBarrier.java	Thu Jun 27 21:03:55 2013 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+public final class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier {
+
+    public G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
+        super(object, startIndex, length);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ArrayRangePreWriteBarrier.java	Thu Jun 27 21:03:55 2013 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier {
+
+    public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
+        super(object, startIndex, length);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java	Thu Jun 27 18:21:13 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java	Thu Jun 27 21:03:55 2013 +0200
@@ -22,37 +22,9 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class SerialArrayRangeWriteBarrier extends FixedWithNextNode implements Lowerable {
-
-    @Input private ValueNode object;
-    @Input private ValueNode startIndex;
-    @Input private ValueNode length;
-
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public ValueNode getStartIndex() {
-        return startIndex;
-    }
-
-    public ValueNode getLength() {
-        return length;
-    }
+public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier {
 
     public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.startIndex = startIndex;
-        this.length = length;
-
+        super(object, startIndex, length);
     }
-
-    public void lower(LoweringTool generator, LoweringType loweringType) {
-        generator.getRuntime().lower(this, generator);
-    }
-
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Thu Jun 27 18:21:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Thu Jun 27 21:03:55 2013 +0200
@@ -586,6 +586,19 @@
     Object readObject(WordBase offset);
 
     /**
+     * Reads the memory at address {@code (this + offset)} and uncompresses it. 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 readObjectCompressed(WordBase offset);
+
+    /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
@@ -667,6 +680,15 @@
     Object readObject(int offset);
 
     /**
+     * Reads the memory at address {@code (this + offset)} and decompressed it. 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 readObjectCompressed(int offset);
+
+    /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Thu Jun 27 18:21:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Thu Jun 27 21:03:55 2013 +0200
@@ -59,6 +59,7 @@
          COMPARISON,
          NOT,
          READ,
+         READ_COMPRESSED,
          WRITE,
          ZERO,
          FROM_UNSIGNED,
@@ -867,6 +868,10 @@
     public native Object readObject(WordBase offset);
 
     @Override
+    @Operation(opcode = Opcode.READ_COMPRESSED)
+    public native Object readObjectCompressed(WordBase offset);
+
+    @Override
     @Operation(opcode = Opcode.READ)
     public byte readByte(int offset) {
         return readByte(signed(offset));
@@ -921,6 +926,12 @@
     }
 
     @Override
+    @Operation(opcode = Opcode.READ_COMPRESSED)
+    public Object readObjectCompressed(int offset) {
+        return readObjectCompressed(signed(offset));
+    }
+
+    @Override
     @Operation(opcode = Opcode.WRITE)
     public void writeByte(WordBase offset, byte val) {
         unsafe.putByte(add((Word) offset).unbox(), val);
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Jun 27 18:21:13 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Jun 27 21:03:55 2013 +0200
@@ -169,7 +169,19 @@
                         } else {
                             location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
                         }
-                        replace(invoke, readOp(graph, arguments.get(0), invoke, location));
+                        replace(invoke, readOp(graph, arguments.get(0), invoke, location, false));
+                        break;
+                    }
+                    case READ_COMPRESSED: {
+                        assert arguments.size() == 2 || arguments.size() == 3;
+                        Kind readKind = asKind(callTargetNode.returnType());
+                        LocationNode location;
+                        if (arguments.size() == 2) {
+                            location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
+                        } else {
+                            location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
+                        }
+                        replace(invoke, readOp(graph, arguments.get(0), invoke, location, true));
                         break;
                     }
                     case WRITE: {
@@ -309,8 +321,8 @@
         return IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1);
     }
 
-    private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location) {
-        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), WriteBarrierType.NONE, false));
+    private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, boolean compress) {
+        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), WriteBarrierType.NONE, compress));
         graph.addBeforeFixed(invoke.asNode(), read);
         // The read must not float outside its block otherwise it may float above an explicit zero
         // check on its base address