changeset 10842:63c3d7b5edd9

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Mon, 22 Jul 2013 16:19:39 +0200
parents 020f63bfd781 (current diff) 02a5f5abd842 (diff)
children 50f3f3958555
files
diffstat 37 files changed, 393 insertions(+), 207 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Mon Jul 22 16:19:39 2013 +0200
@@ -137,7 +137,9 @@
     }
 
     /**
-     * Represents a reference to data from the code. The associated data can be any constant.
+     * Represents a reference to data from the code. The associated data can be either a
+     * {@link Constant} or a raw byte array. The raw byte array is patched as is, no endian swapping
+     * is done on it.
      */
     public static final class DataPatch extends Site {
 
@@ -161,6 +163,8 @@
 
         private DataPatch(int pcOffset, Constant data, byte[] rawData, int alignment, boolean inlined) {
             super(pcOffset);
+            assert (data == null) != (rawData == null) : "only one of data and rawData is allowed";
+            assert !inlined || rawData == null : "rawData can not be inlined";
             this.constant = data;
             this.rawConstant = rawData;
             this.alignment = alignment;
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/AbstractHSAILAssembler.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/AbstractHSAILAssembler.java	Mon Jul 22 16:19:39 2013 +0200
@@ -54,4 +54,9 @@
     protected void patchJumpTarget(int branch, int jumpTarget) {
         // Nothing to do
     }
+
+    @Override
+    protected String createLabelName(Label l, int id) {
+        return "@L" + id;
+    }
 }
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Mon Jul 22 16:19:39 2013 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.api.code.*;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hsail.*;
 import com.oracle.graal.graph.GraalInternalError;
@@ -144,12 +145,10 @@
     }
 
     /**
-     * The mapping to stack slots is always relative to the beginning
-     * of the spillseg.  HSAIL.getStackOffset returns the positive
-     * version of the originally negative offset.  Then we back up
-     * from that by the argSize in bytes.  This ensures that slots of
-     * different size do not overlap, even though we have converted
-     * from negative to positive offsets.
+     * The mapping to stack slots is always relative to the beginning of the spillseg.
+     * HSAIL.getStackOffset returns the positive version of the originally negative offset. Then we
+     * back up from that by the argSize in bytes. This ensures that slots of different size do not
+     * overlap, even though we have converted from negative to positive offsets.
      */
     public static String mapStackSlot(Value reg, int argSize) {
         long offset = HSAIL.getStackOffset(reg);
@@ -213,8 +212,7 @@
 
     public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) {
         String prefix = "cmp_" + condition + (unordered ? "u" : "") + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : getArgType(src1));
-        String comment = (isConstant(src1) && (src1.getKind() == Kind.Object)
-                          && (asConstant(src1).asObject() == null) ? " // null test " : "");
+        String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) && (asConstant(src1).asObject() == null) ? " // null test " : "");
         emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";" + comment);
     }
 
@@ -269,7 +267,6 @@
         emit(mnemonic + "_" + prefix, dest, "", src0, src1);
     }
 
-
     private void emit(String instr, Value dest, String controlRegString, Value src0, Value src1) {
         assert (!isConstant(dest));
         emitString(String.format("%s %s, %s%s, %s;", instr, HSAIL.mapRegister(dest), controlRegString, mapRegOrConstToString(src0), mapRegOrConstToString(src1)));
@@ -277,17 +274,14 @@
 
     private void emit(String instr, Value dest, Value src0, Value src1, Value src2) {
         assert (!isConstant(dest));
-        emitString(String.format("%s %s, %s, %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(src0),
-                                 mapRegOrConstToString(src1), mapRegOrConstToString(src2)));
+        emitString(String.format("%s %s, %s, %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(src0), mapRegOrConstToString(src1), mapRegOrConstToString(src2)));
     }
 
-
     public final void cmovCommon(Value dest, Value trueReg, Value falseReg, int width) {
         String instr = (width == 32 ? "cmov_b32" : "cmov_b64");
         emit(instr, dest, "$c0, ", trueReg, falseReg);
     }
 
-
     /**
      * Emit code to build a 64-bit pointer from a compressed-oop and the associated base and shift.
      * We only emit this if base and shift are not both zero.
@@ -309,9 +303,8 @@
     }
 
     /**
-     * Emit code to build a 32-bit compressed pointer from a full
-     * 64-bit pointer using the associated base and shift.  We only
-     * emit this if base and shift are not both zero.
+     * Emit code to build a 32-bit compressed pointer from a full 64-bit pointer using the
+     * associated base and shift. We only emit this if base and shift are not both zero.
      */
     public void emitCompressedOopEncode(Value result, long narrowOopBase, int narrowOopShift) {
         if (narrowOopBase != 0) {
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java	Mon Jul 22 16:19:39 2013 +0200
@@ -64,9 +64,10 @@
      * 
      * @param l the label for which a name is being created
      * @param id a label identifier that is unique with the scope of this assembler
+     * @return a label name in the form of "L123"
      */
     protected String createLabelName(Label l, int id) {
-        return "@L" + id;
+        return "L" + id;
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jul 22 16:19:39 2013 +0200
@@ -181,7 +181,7 @@
     }
 
     private static boolean isCompressCandidate(DeoptimizingNode access) {
-        return access != null && ((HeapAccess) access).compress();
+        return access != null && ((HeapAccess) access).isCompressible();
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Jul 22 16:19:39 2013 +0200
@@ -405,7 +405,7 @@
     }
 
     private static boolean isCompressCandidate(DeoptimizingNode access) {
-        return access != null && ((HeapAccess) access).compress();
+        return access != null && ((HeapAccess) access).isCompressible();
     }
 
     @Override
@@ -488,7 +488,7 @@
 
         RegisterValue raxRes = AMD64.rax.asValue(kind);
         emitMove(raxRes, expected);
-        if (runtime().config.useCompressedOops && node.compress()) {
+        if (runtime().config.useCompressedOops && node.isCompressible()) {
             Variable scratch = newVariable(Kind.Long);
             append(new CompareAndSwapCompressedOp(raxRes, address, raxRes, newValue, scratch, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
         } else {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Jul 22 16:19:39 2013 +0200
@@ -35,7 +35,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
@@ -165,7 +165,7 @@
      */
     @Test
     public void test6() throws Exception {
-        test2("test6Snippet", wr, new Long(referentOffset()), null);
+        test2("testUnsafeLoad", wr, new Long(referentOffset()), null);
     }
 
     /**
@@ -174,7 +174,7 @@
      */
     @Test
     public void test7() throws Exception {
-        test2("test6Snippet", con, new Long(referentOffset()), null);
+        test2("testUnsafeLoad", con, new Long(referentOffset()), null);
     }
 
     /**
@@ -184,7 +184,7 @@
      */
     @Test
     public void test8() throws Exception {
-        test2("test6Snippet", wr, new Long(32), null);
+        test2("testUnsafeLoad", wr, new Long(32), null);
     }
 
     /**
@@ -194,7 +194,7 @@
      */
     @Test
     public void test10() throws Exception {
-        test2("test6Snippet", wr, new Long(8), new Integer(8));
+        test2("testUnsafeLoad", wr, new Long(8), new Integer(8));
     }
 
     /**
@@ -204,10 +204,10 @@
      */
     @Test
     public void test9() throws Exception {
-        test2("test6Snippet", wr, new Long(16), new Integer(16));
+        test2("testUnsafeLoad", wr, new Long(16), new Integer(16));
     }
 
-    public static Object test6Snippet(Object a, Object b, Object c) throws Exception {
+    public static Object testUnsafeLoad(Object a, Object b, Object c) throws Exception {
         final int offset = (c == null ? 0 : ((Integer) c).intValue());
         final long displacement = (b == null ? 0 : ((Long) b).longValue());
         return UnsafeLoadNode.load(a, offset, displacement, Kind.Object);
@@ -233,20 +233,20 @@
 
                 int barriers = 0;
                 if (useG1GC()) {
-                    barriers = graph.getNodes(G1PreWriteBarrier.class).count() + graph.getNodes(G1PostWriteBarrier.class).count();
+                    barriers = graph.getNodes(G1ReferentFieldReadBarrier.class).count() + graph.getNodes(G1PreWriteBarrier.class).count() + graph.getNodes(G1PostWriteBarrier.class).count();
                 } else {
                     barriers = graph.getNodes(SerialWriteBarrier.class).count();
                 }
                 Assert.assertTrue(barriers == expectedBarriers);
                 for (WriteNode write : graph.getNodes(WriteNode.class)) {
                     if (useG1GC()) {
-                        if (write.getWriteBarrierType() != WriteBarrierType.NONE) {
+                        if (write.getBarrierType() != BarrierType.NONE) {
                             Assert.assertTrue(write.successors().count() == 1);
                             Assert.assertTrue(write.next() instanceof G1PostWriteBarrier);
                             Assert.assertTrue(write.predecessor() instanceof G1PreWriteBarrier);
                         }
                     } else {
-                        if (write.getWriteBarrierType() != WriteBarrierType.NONE) {
+                        if (write.getBarrierType() != BarrierType.NONE) {
                             Assert.assertTrue(write.successors().count() == 1);
                             Assert.assertTrue(write.next() instanceof SerialWriteBarrier);
                         }
@@ -254,15 +254,15 @@
                 }
 
                 for (ReadNode read : graph.getNodes(ReadNode.class)) {
-                    if (read.getWriteBarrierType() != WriteBarrierType.NONE) {
+                    if (read.getBarrierType() != BarrierType.NONE) {
                         if (read.location() instanceof ConstantLocationNode) {
                             Assert.assertTrue(((ConstantLocationNode) (read.location())).getDisplacement() == referentOffset());
                         } else {
                             Assert.assertTrue(((IndexedLocationNode) (read.location())).getDisplacement() == referentOffset());
                         }
                         Assert.assertTrue(useG1GC());
-                        Assert.assertTrue(read.getWriteBarrierType() == WriteBarrierType.PRECISE);
-                        Assert.assertTrue(read.next() instanceof G1PreWriteBarrier);
+                        Assert.assertTrue(read.getBarrierType() == BarrierType.PRECISE);
+                        Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier);
                     }
                 }
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Jul 22 16:19:39 2013 +0200
@@ -66,6 +66,7 @@
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect;
@@ -78,7 +79,7 @@
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -205,8 +206,8 @@
      *            be re-executed.
      * @param killedLocations the memory locations killed by the stub call
      */
-    protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, LocationIdentity... killedLocations) {
-        return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations));
+    protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, Transition transition, LocationIdentity... killedLocations) {
+        return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, transition, reexecutable, killedLocations));
     }
 
     /**
@@ -279,11 +280,11 @@
         registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
 
-        link(new NewInstanceStub(this, r, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, ANY_LOCATION)));
-        link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, ANY_LOCATION)));
+        link(new NewInstanceStub(this, r, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
+        link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
         link(new ExceptionHandlerStub(this, r, target, foreignCalls.get(EXCEPTION_HANDLER)));
-        link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, ANY_LOCATION)));
-        link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, NO_LOCATIONS)));
+        link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
+        link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF, NO_LOCATIONS)));
 
         linkForeignCall(r, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, MARK_WORD_LOCATION);
         linkForeignCall(r, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
@@ -487,7 +488,7 @@
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
             ValueNode array = arrayLengthNode.array();
             ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(),
-                            WriteBarrierType.NONE, false));
+                            BarrierType.NONE, false));
             tool.createNullCheckGuard(arrayLengthRead, array);
             graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
         } else if (n instanceof Invoke) {
@@ -522,7 +523,7 @@
                             // compiled code entry as HotSpot does not guarantee they are final
                             // values.
                             ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
-                                            StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false));
+                                            StampFactory.forKind(wordKind()), BarrierType.NONE, false));
 
                             loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
                                             CallingConvention.Type.JavaCall));
@@ -545,7 +546,7 @@
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
             ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object();
             assert loadField.kind() != Kind.Illegal;
-            WriteBarrierType barrierType = getFieldLoadBarrierType(field);
+            BarrierType barrierType = getFieldLoadBarrierType(field);
             ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object)));
             tool.createNullCheckGuard(memoryRead, object);
 
@@ -561,7 +562,7 @@
             StoreFieldNode storeField = (StoreFieldNode) n;
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
             ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object();
-            WriteBarrierType barrierType = getFieldStoreBarrierType(storeField);
+            BarrierType barrierType = getFieldStoreBarrierType(storeField);
             WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field), barrierType, storeField.field().getKind() == Kind.Object));
             tool.createNullCheckGuard(memoryWrite, object);
             memoryWrite.setStateAfter(storeField.stateAfter());
@@ -580,16 +581,16 @@
             CompareAndSwapNode cas = (CompareAndSwapNode) n;
             LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
             cas.setLocation(location);
-            cas.setWriteBarrierType(getCompareAndSwapBarrier(cas));
+            cas.setBarrierType(getCompareAndSwapBarrier(cas));
             if (cas.expected().kind() == Kind.Object) {
-                cas.setCompress();
+                cas.setCompressible();
             }
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
             GuardingNode boundsCheck = createBoundsCheck(loadIndexed, tool);
             Kind elementKind = loadIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index());
-            ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), WriteBarrierType.NONE, elementKind == Kind.Object));
+            ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object));
             memoryRead.setGuard(boundsCheck);
             graph.replaceFixedWithFixed(loadIndexed, memoryRead);
         } else if (n instanceof StoreIndexedNode) {
@@ -619,7 +620,7 @@
                     value = checkcast;
                 }
             }
-            WriteBarrierType barrierType = getArrayStoreBarrierType(storeIndexed);
+            BarrierType barrierType = getArrayStoreBarrierType(storeIndexed);
             WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object));
             memoryWrite.setGuard(boundsCheck);
             memoryWrite.setStateAfter(storeIndexed.stateAfter());
@@ -628,12 +629,12 @@
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != Kind.Illegal;
-            boolean compress = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
+            boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
             if (addReadBarrier(load, tool)) {
                 unsafeLoadSnippets.lower(load, tool);
             } else {
                 IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
-                ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), WriteBarrierType.NONE, compress));
+                ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible));
                 // 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));
@@ -643,7 +644,7 @@
             UnsafeStoreNode store = (UnsafeStoreNode) n;
             IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
             ValueNode object = store.object();
-            WriteBarrierType barrierType = getUnsafeStoreBarrierType(store);
+            BarrierType barrierType = getUnsafeStoreBarrierType(store);
             WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object));
             write.setStateAfter(store.stateAfter());
             graph.replaceFixedWithFixed(store, write);
@@ -704,7 +705,7 @@
                                 value = allocations[commit.getVirtualObjects().indexOf(value)];
                             }
                             if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i)), WriteBarrierType.NONE,
+                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i)), BarrierType.NONE,
                                                 virtualInstance.field(i).getKind() == Kind.Object);
 
                                 graph.addBeforeFixed(commit, graph.add(write));
@@ -722,7 +723,7 @@
                                 value = allocations[indexOf];
                             }
                             if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE,
+                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), BarrierType.NONE,
                                                 value.kind() == Kind.Object);
                                 graph.addBeforeFixed(commit, graph.add(write));
                             }
@@ -769,7 +770,7 @@
                     int size = FrameStateBuilder.stackSlots(osrLocal.kind());
                     int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
                     IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1);
-                    ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), WriteBarrierType.NONE, false));
+                    ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false));
                     osrLocal.replaceAndDelete(load);
                     graph.addBeforeFixed(migrationEnd, load);
                 }
@@ -806,6 +807,8 @@
             writeBarrierSnippets.lower((G1PreWriteBarrier) n, tool);
         } else if (n instanceof G1PostWriteBarrier) {
             writeBarrierSnippets.lower((G1PostWriteBarrier) n, tool);
+        } else if (n instanceof G1ReferentFieldReadBarrier) {
+            writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, tool);
         } else if (n instanceof SerialWriteBarrier) {
             writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
         } else if (n instanceof SerialArrayRangeWriteBarrier) {
@@ -849,68 +852,67 @@
         assert vtableEntryOffset > 0;
         // We use LocationNode.ANY_LOCATION for the reads that access the vtable
         // entry as HotSpot does not guarantee that this is a final value.
-        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()), WriteBarrierType.NONE,
-                        false));
+        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()), BarrierType.NONE, false));
         return metaspaceMethod;
     }
 
     private ReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object) {
         LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, config.useCompressedKlassPointers));
+        return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), BarrierType.NONE, config.useCompressedKlassPointers));
     }
 
     private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) {
         LocationNode location = ConstantLocationNode.create(ANY_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        return graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE, config.useCompressedKlassPointers));
+        return graph.add(new WriteNode(object, value, location, BarrierType.NONE, config.useCompressedKlassPointers));
     }
 
-    private static WriteBarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) {
-        WriteBarrierType barrierType = WriteBarrierType.NONE;
+    private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) {
+        BarrierType barrierType = BarrierType.NONE;
         if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) {
-            barrierType = WriteBarrierType.PRECISE;
+            barrierType = BarrierType.PRECISE;
         }
         return barrierType;
     }
 
-    private static WriteBarrierType getFieldStoreBarrierType(StoreFieldNode storeField) {
-        WriteBarrierType barrierType = WriteBarrierType.NONE;
+    private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) {
+        BarrierType barrierType = BarrierType.NONE;
         if (storeField.field().getKind() == Kind.Object && !storeField.value().objectStamp().alwaysNull()) {
-            barrierType = WriteBarrierType.IMPRECISE;
+            barrierType = BarrierType.IMPRECISE;
         }
         return barrierType;
     }
 
-    private static WriteBarrierType getArrayStoreBarrierType(StoreIndexedNode store) {
-        WriteBarrierType barrierType = WriteBarrierType.NONE;
+    private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) {
+        BarrierType barrierType = BarrierType.NONE;
         if (store.elementKind() == Kind.Object && !store.value().objectStamp().alwaysNull()) {
-            barrierType = WriteBarrierType.PRECISE;
+            barrierType = BarrierType.PRECISE;
         }
         return barrierType;
     }
 
-    private static WriteBarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) {
-        WriteBarrierType barrierType = WriteBarrierType.NONE;
+    private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) {
+        BarrierType barrierType = BarrierType.NONE;
         if (store.value().kind() == Kind.Object && !store.value().objectStamp().alwaysNull()) {
             ResolvedJavaType type = store.object().objectStamp().type();
             if (type != null && type.isArray()) {
-                barrierType = WriteBarrierType.PRECISE;
+                barrierType = BarrierType.PRECISE;
             } else {
-                barrierType = WriteBarrierType.IMPRECISE;
+                barrierType = BarrierType.IMPRECISE;
             }
         }
         return barrierType;
     }
 
-    private static WriteBarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
-        WriteBarrierType barrierType = WriteBarrierType.NONE;
+    private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
+        BarrierType barrierType = BarrierType.NONE;
         if (cas.expected().kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) {
             ResolvedJavaType type = cas.object().objectStamp().type();
             if (type != null && type.isArray()) {
-                barrierType = WriteBarrierType.PRECISE;
+                barrierType = BarrierType.PRECISE;
             } else {
-                barrierType = WriteBarrierType.IMPRECISE;
+                barrierType = BarrierType.IMPRECISE;
             }
         }
         return barrierType;
@@ -933,6 +935,44 @@
         return IndexedLocationNode.create(NamedLocationIdentity.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
     }
 
+    @Override
+    public ValueNode reconstructArrayIndex(LocationNode location) {
+        Kind elementKind = location.getValueKind();
+        assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind));
+
+        long base;
+        ValueNode index;
+        int scale = getScalingFactor(elementKind);
+
+        if (location instanceof ConstantLocationNode) {
+            base = ((ConstantLocationNode) location).getDisplacement();
+            index = null;
+        } else if (location instanceof IndexedLocationNode) {
+            IndexedLocationNode indexedLocation = (IndexedLocationNode) location;
+            assert indexedLocation.getIndexScaling() == scale;
+            base = indexedLocation.getDisplacement();
+            index = indexedLocation.getIndex();
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        base -= getArrayBaseOffset(elementKind);
+        assert base >= 0 && base % scale == 0;
+
+        base /= scale;
+        assert NumUtil.isInt(base);
+
+        if (index == null) {
+            return ConstantNode.forInt((int) base, location.graph());
+        } else {
+            if (base == 0) {
+                return index;
+            } else {
+                return IntegerArithmeticNode.add(ConstantNode.forInt((int) base, location.graph()), index);
+            }
+        }
+    }
+
     private static GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
         StructuredGraph graph = n.graph();
         ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array()));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Jul 22 16:19:39 2013 +0200
@@ -25,7 +25,7 @@
 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.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
@@ -54,22 +54,20 @@
     }
 
     private static void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
-        if (node.getWriteBarrierType() == WriteBarrierType.PRECISE) {
+        if (node.getBarrierType() == BarrierType.PRECISE) {
             assert useG1GC();
-            G1PreWriteBarrier barrier = graph.add(new G1PreWriteBarrier(node.object(), node, node.location(), false, node.getNullCheck()));
-            barrier.setDeoptimizationState(node.getDeoptimizationState());
-            node.setNullCheck(false);
+            G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.object(), node, node.location(), false, false));
             graph.addAfterFixed(node, barrier);
         } else {
-            assert node.getWriteBarrierType() == WriteBarrierType.NONE : "Non precise write barrier has been attached to read node.";
+            assert node.getBarrierType() == BarrierType.NONE : "Non precise read barrier has been attached to read node.";
         }
     }
 
     private static void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
-        WriteBarrierType barrierType = node.getWriteBarrierType();
-        if (barrierType == WriteBarrierType.PRECISE) {
+        BarrierType barrierType = node.getBarrierType();
+        if (barrierType == BarrierType.PRECISE) {
             if (useG1GC()) {
-                if (node.isInitialized()) {
+                if (!node.isInitialization()) {
                     G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck()));
                     preBarrier.setDeoptimizationState(node.getDeoptimizationState());
                     node.setNullCheck(false);
@@ -79,7 +77,7 @@
             } else {
                 graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), true)));
             }
-        } else if (barrierType == WriteBarrierType.IMPRECISE) {
+        } else if (barrierType == BarrierType.IMPRECISE) {
             if (useG1GC()) {
                 G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck()));
                 preBarrier.setDeoptimizationState(node.getDeoptimizationState());
@@ -90,21 +88,21 @@
                 graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), false)));
             }
         } else {
-            assert barrierType == WriteBarrierType.NONE;
+            assert barrierType == BarrierType.NONE;
         }
 
     }
 
     private static void addCASBarriers(CompareAndSwapNode node, StructuredGraph graph) {
-        WriteBarrierType barrierType = node.getWriteBarrierType();
-        if (barrierType == WriteBarrierType.PRECISE) {
+        BarrierType barrierType = node.getBarrierType();
+        if (barrierType == BarrierType.PRECISE) {
             if (useG1GC()) {
                 graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false, 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) {
+        } else if (barrierType == BarrierType.IMPRECISE) {
             if (useG1GC()) {
                 graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.expected(), node.getLocation(), false, false)));
                 graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.newValue(), node.getLocation(), false)));
@@ -112,13 +110,13 @@
                 graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getLocation(), false)));
             }
         } else {
-            assert barrierType == WriteBarrierType.NONE;
+            assert barrierType == BarrierType.NONE;
         }
     }
 
     private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) {
         if (useG1GC()) {
-            if (node.isInitialized()) {
+            if (!node.isInitialization()) {
                 G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
                 graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier);
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Mon Jul 22 16:19:39 2013 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
@@ -112,8 +112,8 @@
     }
 
     private static boolean isObjectWrite(Node node) {
-        if ((node instanceof WriteNode && (((WriteNode) node).getWriteBarrierType() != WriteBarrierType.NONE)) ||
-                        (node instanceof CompareAndSwapNode && (((CompareAndSwapNode) node).getWriteBarrierType() != WriteBarrierType.NONE))) {
+        if ((node instanceof WriteNode && (((WriteNode) node).getBarrierType() != BarrierType.NONE)) ||
+                        (node instanceof CompareAndSwapNode && (((CompareAndSwapNode) node).getBarrierType() != BarrierType.NONE))) {
             return true;
         }
         return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -83,8 +83,8 @@
     }
 
     @Override
-    public boolean isInitialized() {
-        return true;
+    public boolean isInitialization() {
+        return false;
     }
 
     public Kind getElementKind() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Mon Jul 22 16:19:39 2013 +0200
@@ -26,6 +26,7 @@
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
@@ -40,9 +41,9 @@
     public static Object lowerUnsafeLoad(Object object, long offset, int disp) {
         long displacement = disp + offset;
         if (object instanceof java.lang.ref.Reference && referentOffset() == displacement) {
-            return Word.fromObject(object).readObject((int) displacement, 1, true);
+            return Word.fromObject(object).readObject((int) displacement, BarrierType.PRECISE, true);
         } else {
-            return Word.fromObject(object).readObject((int) displacement, 0, true);
+            return Word.fromObject(object).readObject((int) displacement, BarrierType.NONE, true);
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Jul 22 16:19:39 2013 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
@@ -118,7 +119,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, 0, true));
+                previousOop = (Word) Word.fromObject(field.readObject(0, BarrierType.NONE, true));
                 if (trace) {
                     log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue());
                     verifyOop(previousOop.toObject());
@@ -225,7 +226,7 @@
 
         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.readObject(0, 0, true));
+            oop = (Word) Word.fromObject(address.readObject(0, BarrierType.NONE, true));
             if (oop.notEqual(0)) {
                 if (indexValue.notEqual(0)) {
                     Word nextIndex = indexValue.subtract(wordSize());
@@ -294,6 +295,8 @@
         private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier");
         private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier");
         private final SnippetInfo g1PreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier");
+
+        private final SnippetInfo g1ReferentReadBarrier = 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");
@@ -329,6 +332,17 @@
             template(args).instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, args);
         }
 
+        public void lower(G1ReferentFieldReadBarrier readBarrier, @SuppressWarnings("unused") LoweringTool tool) {
+            Arguments args = new Arguments(g1ReferentReadBarrier);
+            args.add("object", readBarrier.getObject());
+            args.add("expectedObject", readBarrier.getExpectedObject());
+            args.add("location", readBarrier.getLocation());
+            args.addConst("doLoad", readBarrier.doLoad());
+            args.addConst("nullCheck", readBarrier.getNullCheck());
+            args.addConst("trace", traceBarrier());
+            template(args).instantiate(runtime, readBarrier, DEFAULT_REPLACER, args);
+        }
+
         public void lower(G1PostWriteBarrier writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) {
             Arguments args = new Arguments(g1PostWriteBarrier);
             args.add("object", writeBarrierPost.getObject());
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Jul 22 16:19:39 2013 +0200
@@ -270,12 +270,12 @@
     public static class StoreConstantOp extends MemOp {
 
         protected final Constant input;
-        private final boolean compress;
+        private final boolean compressible;
 
-        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state, boolean compress) {
+        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state, boolean compressible) {
             super(kind, address, state);
             this.input = input;
-            this.compress = compress;
+            this.compressible = compressible;
         }
 
         @Override
@@ -294,7 +294,7 @@
                     break;
                 case Long:
                     if (NumUtil.isInt(input.asLong())) {
-                        if (compress) {
+                        if (compressible) {
                             masm.movl(address.toAddress(), (int) input.asLong());
                         } else {
                             masm.movslq(address.toAddress(), (int) input.asLong());
@@ -310,7 +310,7 @@
                     throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                 case Object:
                     if (input.isNull()) {
-                        if (compress) {
+                        if (compressible) {
                             masm.movl(address.toAddress(), 0);
                         } else {
                             masm.movptr(address.toAddress(), 0);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Mon Jul 22 16:19:39 2013 +0200
@@ -190,10 +190,13 @@
         }
 
         LIRInstruction branch = instructions.get(instructions.size() - 2);
-        if (!(branch instanceof StandardOp.BranchOp) || branch.hasState()) {
-            // not a valid case for optimization
-            // currently, only blocks that end with two branches (conditional branch followed
-            // by unconditional branch) are optimized
+        if (!(branch instanceof StandardOp.BranchOp) || branch.hasOperands()) {
+            // Only blocks that end with two branches (conditional branch followed
+            // by unconditional branch) are optimized.
+            // In addition, a conditional branch with operands (including state) cannot
+            // be optimized. Moving a successor instruction before such a branch may
+            // interfere with the operands of the branch. For example, a successive move
+            // instruction may redefine an input operand of the branch.
             return;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ReferentFieldReadBarrier.java	Mon Jul 22 16:19:39 2013 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * The {@code G1ReferentFieldReadBarrier} is added when a read access is performed to the referent
+ * field of a {@link java.lang.ref.Reference} object (through a {@code LoadFieldNode} or an
+ * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the
+ * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled.
+ */
+public class G1ReferentFieldReadBarrier extends WriteBarrier implements DeoptimizingNode {
+
+    @Input private ValueNode expectedObject;
+    private final boolean doLoad;
+
+    @Input private FrameState deoptimizationState;
+    private final boolean nullCheck;
+
+    public ValueNode getExpectedObject() {
+        return expectedObject;
+    }
+
+    public boolean doLoad() {
+        return doLoad;
+    }
+
+    public boolean getNullCheck() {
+        return nullCheck;
+    }
+
+    public G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) {
+        super(object, location, true);
+        this.doLoad = doLoad;
+        this.nullCheck = nullCheck;
+        this.expectedObject = expectedObject;
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return nullCheck;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptimizationState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState state) {
+        updateUsages(deoptimizationState, state);
+        deoptimizationState = state;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.NullCheckException;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -46,6 +46,10 @@
         return object;
     }
 
+    public LogicNode condition() {
+        return condition;
+    }
+
     /**
      * Constructor for {@link #guardingNonNull(Object)} node intrinsic.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/HeapAccess.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/HeapAccess.java	Mon Jul 22 16:19:39 2013 +0200
@@ -23,25 +23,24 @@
 package com.oracle.graal.nodes;
 
 /**
- * A HeapAccess is a node that access the heap and therefore may be subjected to certain rules of
- * the underlying runtime.
+ * Encapsulates properties of a node describing how it accesses the heap.
  */
 public interface HeapAccess {
 
-    /*
-     * The types of write barriers attached to stores.
+    /**
+     * The types of (write/read) barriers attached to stores.
      */
-    public enum WriteBarrierType {
-        /*
-         * Primitive stores which do not necessitate write barriers.
+    public enum BarrierType {
+        /**
+         * Primitive stores which do not necessitate barriers.
          */
         NONE,
-        /*
-         * Array object stores which necessitate precise write barriers.
+        /**
+         * Array object stores which necessitate precise barriers.
          */
         PRECISE,
-        /*
-         * Field object stores which necessitate imprecise write barriers.
+        /**
+         * Field object stores which necessitate imprecise barriers.
          */
         IMPRECISE
     }
@@ -49,10 +48,10 @@
     /**
      * Gets the write barrier type for that particular access.
      */
-    WriteBarrierType getWriteBarrierType();
+    BarrierType getBarrierType();
 
     /**
      * Returns whether or not the heap access is a compressed pointer candidate.
      */
-    boolean compress();
+    boolean isCompressible();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -200,9 +200,9 @@
             ConstantNode arrayConstant = ConstantNode.forObject(COUNTERS, runtime, graph);
             ConstantLocationNode location = ConstantLocationNode.create(NamedLocationIdentity.getArrayLocation(Kind.Long), Kind.Long, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE *
                             index, graph);
-            ReadNode read = graph.add(new ReadNode(arrayConstant, location, StampFactory.forKind(Kind.Long), WriteBarrierType.NONE, false));
+            ReadNode read = graph.add(new ReadNode(arrayConstant, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false));
             IntegerAddNode add = graph.add(new IntegerAddNode(Kind.Long, read, ConstantNode.forLong(increment, graph)));
-            WriteNode write = graph.add(new WriteNode(arrayConstant, add, location, WriteBarrierType.NONE, false));
+            WriteNode write = graph.add(new WriteNode(arrayConstant, add, location, BarrierType.NONE, false));
 
             graph.addBeforeFixed(position, read);
             graph.addBeforeFixed(position, write);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -37,8 +37,8 @@
     @Input private ValueNode object;
     @Input private ValueNode location;
     private boolean nullCheck;
-    private WriteBarrierType barrierType;
-    private boolean compress;
+    private BarrierType barrierType;
+    private boolean compressible;
 
     public ValueNode object() {
         return object;
@@ -61,20 +61,20 @@
     }
 
     public AccessNode(ValueNode object, ValueNode location, Stamp stamp) {
-        this(object, location, stamp, null, WriteBarrierType.NONE, false);
+        this(object, location, stamp, null, BarrierType.NONE, false);
     }
 
-    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
-        this(object, location, stamp, null, barrierType, compress);
+    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) {
+        this(object, location, stamp, null, barrierType, compressible);
     }
 
-    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
+    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) {
         super(stamp);
         this.object = object;
         this.location = location;
         this.guard = guard;
         this.barrierType = barrierType;
-        this.compress = compress;
+        this.compressible = compressible;
     }
 
     @Override
@@ -104,12 +104,12 @@
     }
 
     @Override
-    public WriteBarrierType getWriteBarrierType() {
+    public BarrierType getBarrierType() {
         return barrierType;
     }
 
     @Override
-    public boolean compress() {
-        return compress;
+    public boolean isCompressible() {
+        return compressible;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -56,8 +56,9 @@
     public abstract boolean isObjectArray();
 
     /**
-     * If {@link #isInitialized()} is true, the memory location contains a valid value. If
-     * {@link #isInitialized()} is false, the memory location is uninitialized or zero.
+     * 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 abstract boolean isInitialized();
+    public abstract boolean isInitialization();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -35,12 +35,12 @@
         super(object, location, stamp);
     }
 
-    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
-        super(object, location, stamp, guard, barrierType, compress);
+    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) {
+        super(object, location, stamp, guard, barrierType, compressible);
     }
 
-    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
-        super(object, location, stamp, barrierType, compress);
+    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) {
+        super(object, location, stamp, barrierType, compressible);
     }
 
     public abstract FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess);
@@ -51,6 +51,6 @@
      * an attached write barrier with pre-semantics can not also float.
      */
     public boolean canFloat() {
-        return location().getLocationIdentity() != LocationIdentity.ANY_LOCATION && getWriteBarrierType() == WriteBarrierType.NONE;
+        return location().getLocationIdentity() != LocationIdentity.ANY_LOCATION && getBarrierType() == BarrierType.NONE;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -32,8 +32,8 @@
     @Input private LocationNode location;
     @Input private FrameState deoptState;
     private boolean nullCheck;
-    private WriteBarrierType barrierType;
-    private boolean compress;
+    private BarrierType barrierType;
+    private boolean compressible;
 
     public ValueNode object() {
         return object;
@@ -61,12 +61,12 @@
         this.location = location;
     }
 
-    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
+    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) {
         super(stamp, guard);
         this.object = object;
         this.location = location;
         this.barrierType = barrierType;
-        this.compress = compress;
+        this.compressible = compressible;
     }
 
     @Override
@@ -96,13 +96,13 @@
     }
 
     @Override
-    public WriteBarrierType getWriteBarrierType() {
+    public BarrierType getBarrierType() {
         return barrierType;
     }
 
     @Override
-    public boolean compress() {
-        return compress;
+    public boolean isCompressible() {
+        return compressible;
     }
 
     public abstract Access asFixedNode();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -37,11 +37,11 @@
     @Input private Node lastLocationAccess;
 
     public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp) {
-        this(object, location, lastLocationAccess, stamp, null, WriteBarrierType.NONE, false);
+        this(object, location, lastLocationAccess, stamp, null, BarrierType.NONE, false);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
-        super(object, location, stamp, guard, barrierType, compress);
+    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) {
+        super(object, location, stamp, guard, barrierType, compressible);
         this.lastLocationAccess = lastLocationAccess;
     }
 
@@ -57,11 +57,11 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        return ReadNode.canonicalizeRead(this, location(), object(), tool, compress());
+        return ReadNode.canonicalizeRead(this, location(), object(), tool, isCompressible());
     }
 
     @Override
     public Access asFixedNode() {
-        return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard(), getWriteBarrierType(), compress()));
+        return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard(), getBarrierType(), isCompressible()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -34,12 +34,12 @@
  */
 public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable, Virtualizable {
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
-        super(object, location, stamp, barrierType, compress);
+    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) {
+        super(object, location, stamp, barrierType, compressible);
     }
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
-        super(object, location, stamp, guard, barrierType, compress);
+    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) {
+        super(object, location, stamp, guard, barrierType, compressible);
     }
 
     public ReadNode(ValueNode object, int displacement, LocationIdentity locationIdentity, Kind kind) {
@@ -51,7 +51,7 @@
          * Used by node intrinsics. Since the initial value for location is a parameter, i.e., a
          * LocalNode, the constructor cannot use the declared type LocationNode.
          */
-        super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, WriteBarrierType.NONE, false);
+        super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, BarrierType.NONE, false);
     }
 
     @Override
@@ -62,12 +62,12 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        return canonicalizeRead(this, location(), object(), tool, compress());
+        return canonicalizeRead(this, location(), object(), tool, isCompressible());
     }
 
     @Override
     public FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess) {
-        return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getWriteBarrierType(), compress()));
+        return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType(), isCompressible()));
     }
 
     public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool, boolean compressedPointer) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -37,7 +37,7 @@
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
-    private final boolean initialized;
+    private final boolean initialization;
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -58,21 +58,22 @@
     }
 
     /**
-     * If {@link #isInitialized()} is true, the memory location contains a valid value. If
-     * {@link #isInitialized()} is false, the memory location is uninitialized or zero.
+     * 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 isInitialized() {
-        return initialized;
+    public boolean isInitialization() {
+        return initialization;
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType, boolean compress) {
-        this(object, value, location, barrierType, compress, true);
+    public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible) {
+        this(object, value, location, barrierType, compressible, false);
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType, boolean compress, boolean initialized) {
-        super(object, location, StampFactory.forVoid(), barrierType, compress);
+    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.initialized = initialized;
+        this.initialization = initialization;
     }
 
     @Override
@@ -82,7 +83,7 @@
     }
 
     @NodeIntrinsic
-    public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter WriteBarrierType barrierType, @ConstantNodeParameter boolean compress);
+    public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter BarrierType barrierType, @ConstantNodeParameter boolean compressible);
 
     @Override
     public LocationIdentity getLocationIdentity() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -43,8 +43,8 @@
     @Input private ValueNode newValue;
     @Input private LocationNode location;
     private final int displacement;
-    private WriteBarrierType barrierType;
-    private boolean compress;
+    private BarrierType barrierType;
+    private boolean compressible;
 
     public ValueNode object() {
         return object;
@@ -76,21 +76,21 @@
     }
 
     @Override
-    public WriteBarrierType getWriteBarrierType() {
+    public BarrierType getBarrierType() {
         return barrierType;
     }
 
-    public void setWriteBarrierType(WriteBarrierType type) {
+    public void setBarrierType(BarrierType type) {
         this.barrierType = type;
     }
 
     @Override
-    public boolean compress() {
-        return compress;
+    public boolean isCompressible() {
+        return compressible;
     }
 
-    public void setCompress() {
-        this.compress = true;
+    public void setCompressible() {
+        this.compressible = true;
     }
 
     public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
@@ -101,8 +101,8 @@
         this.expected = expected;
         this.newValue = newValue;
         this.displacement = displacement;
-        this.barrierType = WriteBarrierType.NONE;
-        this.compress = false;
+        this.barrierType = BarrierType.NONE;
+        this.compressible = false;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -57,7 +57,20 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
-        if (tool.canonicalizeReads() && runtime != null) {
+        if (tool.canonicalizeReads()) {
+            ConstantNode constant = asConstant(runtime);
+            if (constant != null) {
+                return constant;
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Gets a constant value for this load if possible.
+     */
+    public ConstantNode asConstant(MetaAccessProvider runtime) {
+        if (runtime != null) {
             Constant constant = null;
             if (isStatic()) {
                 constant = field().readConstantValue(null);
@@ -68,7 +81,7 @@
                 return ConstantNode.forConstant(constant, runtime, graph());
             }
         }
-        return this;
+        return null;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Mon Jul 22 16:19:39 2013 +0200
@@ -25,6 +25,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 
 /**
  * Graal-specific extensions for the code cache provider interface.
@@ -44,4 +46,13 @@
     InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph);
 
     void lower(Node n, LoweringTool tool);
+
+    /**
+     * Reconstruct the array index from a location node that was created as a lowering of an indexed
+     * access to an array.
+     * 
+     * @param location a location pointing to an element in an array
+     * @return a node that gives the index of the element
+     */
+    ValueNode reconstructArrayIndex(LocationNode location);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Mon Jul 22 16:19:39 2013 +0200
@@ -68,7 +68,7 @@
         }
         long lowerBound = stamp1.lowerBound() + stamp2.lowerBound();
         long upperBound = stamp1.upperBound() + stamp2.upperBound();
-        long mask = IntegerStamp.maskFor(kind, lowerBound, upperBound) & (stamp1.mask() | stamp2.mask());
+        long mask = IntegerStamp.maskFor(kind, lowerBound, upperBound);
 
         return StampFactory.forInteger(kind, lowerBound, upperBound, mask);
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Jul 22 16:19:39 2013 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -66,7 +66,7 @@
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
         IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, value.kind(), displacement, offset, graph(), 1);
-        WriteNode write = graph().add(new WriteNode(object, value, location, WriteBarrierType.NONE, value.kind() == Kind.Object));
+        WriteNode write = graph().add(new WriteNode(object, value, location, BarrierType.NONE, value.kind() == Kind.Object));
         graph().replaceFixedWithFixed(this, write);
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Jul 22 16:19:39 2013 +0200
@@ -107,6 +107,7 @@
                     }
 
                     Assumptions tmpAssumptions = new Assumptions(false);
+
                     optimizeGraph(newGraph, tmpAssumptions);
 
                     HighTierContext context = new HighTierContext(metaAccessProvider, tmpAssumptions, replacements);
@@ -153,9 +154,11 @@
 
         CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), null, null);
 
+        EarlyReadEliminationPhase earlyRead = new EarlyReadEliminationPhase(new CanonicalizerPhase(true));
+        HighTierContext context = new HighTierContext(metaAccessProvider, assumptions, replacements);
         Integer maxNodes = TruffleCompilerOptions.TruffleOperationCacheMaxNodes.getValue();
 
-        contractGraph(newGraph, eliminate, convertDeoptimizeToGuardPhase, canonicalizerPhase);
+        contractGraph(newGraph, eliminate, convertDeoptimizeToGuardPhase, canonicalizerPhase, earlyRead, context);
 
         while (newGraph.getNodeCount() <= maxNodes) {
 
@@ -168,7 +171,7 @@
                 break;
             }
 
-            contractGraph(newGraph, eliminate, convertDeoptimizeToGuardPhase, canonicalizerPhase);
+            contractGraph(newGraph, eliminate, convertDeoptimizeToGuardPhase, canonicalizerPhase, earlyRead, context);
         }
 
         if (newGraph.getNodeCount() > maxNodes && (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue() || TruffleCompilerOptions.TraceTrufflePerformanceWarnings.getValue())) {
@@ -177,10 +180,13 @@
     }
 
     private static void contractGraph(StructuredGraph newGraph, ConditionalEliminationPhase eliminate, ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuardPhase,
-                    CanonicalizerPhase.Instance canonicalizerPhase) {
+                    CanonicalizerPhase.Instance canonicalizerPhase, EarlyReadEliminationPhase earlyRead, HighTierContext context) {
         // Canonicalize / constant propagate.
         canonicalizerPhase.apply(newGraph);
 
+        // Early read eliminiation
+        earlyRead.apply(newGraph, context);
+
         // Convert deopt to guards.
         convertDeoptimizeToGuardPhase.apply(newGraph);
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Jul 22 16:19:39 2013 +0200
@@ -54,7 +54,7 @@
     @Option(help = "")
     public static final OptionValue<Integer> TruffleConstantUnrollLimit = new OptionValue<>(32);
     @Option(help = "")
-    public static final OptionValue<Integer> TruffleOperationCacheMaxNodes = new OptionValue<>(200);
+    public static final OptionValue<Integer> TruffleOperationCacheMaxNodes = new OptionValue<>(350);
     @Option(help = "")
     public static final OptionValue<Integer> TruffleGraphMaxNodes = new OptionValue<>(12000);
     @Option(help = "")
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Mon Jul 22 16:19:39 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.word;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
 
 public interface Pointer extends Unsigned {
@@ -619,10 +620,10 @@
      * 
      * @param offset the signed offset for the memory access
      * @param barrierType the type of the read barrier to be added
-     * @param compress whether or not the object is a decompression candidate
+     * @param compressible whether or not the object is a decompression candidate
      * @return the result of the memory access
      */
-    Object readObject(WordBase offset, int barrierType, boolean compress);
+    Object readObject(WordBase offset, BarrierType barrierType, boolean compressible);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -711,10 +712,10 @@
      * 
      * @param offset the signed offset for the memory access
      * @param barrierType the type of the read barrier to be added
-     * @param compress whether or not the object is a decompression candidate
+     * @param compressible whether or not the object is a decompression candidate
      * @return the result of the memory access
      */
-    Object readObject(int offset, int barrierType, boolean compress);
+    Object readObject(int offset, BarrierType barrierType, boolean compressible);
 
     /**
      * 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	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Mon Jul 22 16:19:39 2013 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.calc.*;
 
 public abstract class Word implements Signed, Unsigned, Pointer {
@@ -881,7 +882,7 @@
     public native Object readObject(WordBase offset);
 
     @Operation(opcode = Opcode.READ_HEAP)
-    public native Object readObject(WordBase offset, int barrierType, boolean compress);
+    public native Object readObject(WordBase offset, BarrierType barrierType, boolean compressible);
 
     @Override
     @Operation(opcode = Opcode.READ)
@@ -938,8 +939,8 @@
     }
 
     @Operation(opcode = Opcode.READ_HEAP)
-    public Object readObject(int offset, int barrierType, boolean compress) {
-        return readObject(signed(offset), barrierType, compress);
+    public Object readObject(int offset, BarrierType barrierType, boolean compressible) {
+        return readObject(signed(offset), barrierType, compressible);
     }
 
     @Override
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Jul 22 16:19:39 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
+import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -98,6 +98,14 @@
             }
         }
 
+        // Fold constant field reads (e.g. enum constants)
+        for (LoadFieldNode load : graph.getNodes(LoadFieldNode.class).snapshot()) {
+            ConstantNode constant = load.asConstant(metaAccess);
+            if (constant != null) {
+                graph.replaceFixedWithFloating(load, constant);
+            }
+        }
+
         // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are
         // words
         for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) {
@@ -175,14 +183,15 @@
                         } else {
                             location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2));
                         }
-                        replace(invoke, readOp(graph, arguments.get(0), invoke, location, 0, false));
+                        replace(invoke, readOp(graph, arguments.get(0), invoke, location, BarrierType.NONE, false));
                         break;
                     }
                     case READ_HEAP: {
                         assert arguments.size() == 4;
                         Kind readKind = asKind(callTargetNode.returnType());
                         LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
-                        replace(invoke, readOp(graph, arguments.get(0), invoke, location, arguments.get(2).asConstant().asInt(), arguments.get(3).asConstant().asInt() == 0 ? false : true));
+                        BarrierType barrierType = (BarrierType) arguments.get(2).asConstant().asObject();
+                        replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, arguments.get(3).asConstant().asInt() == 0 ? false : true));
                         break;
                     }
                     case WRITE:
@@ -323,8 +332,8 @@
         return IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1);
     }
 
-    private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, int barrierType, boolean compress) {
-        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), WriteBarrierType.values()[barrierType], compress));
+    private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) {
+        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), barrierType, compressible));
         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
@@ -334,7 +343,7 @@
 
     private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location, Opcode op) {
         assert op == Opcode.WRITE || op == Opcode.INITIALIZE;
-        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE, false, op == Opcode.WRITE));
+        WriteNode write = graph.add(new WriteNode(base, value, location, BarrierType.NONE, false, op == Opcode.INITIALIZE));
         write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.asNode(), write);
         return write;
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java	Mon Jul 22 16:18:55 2013 +0200
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java	Mon Jul 22 16:19:39 2013 +0200
@@ -24,7 +24,7 @@
 
 import java.lang.annotation.*;
 
-@Retention(RetentionPolicy.CLASS)
+@Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD})
 public @interface Specialization {