changeset 7868:7a5bbcc36bb2

add location identity to Pointer read and write operations
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 26 Feb 2013 16:35:23 +0100
parents f4aec4c242ff
children cb7bab0fd666 b8f387456757
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java
diffstat 21 files changed, 390 insertions(+), 477 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Tue Feb 26 16:35:23 2013 +0100
@@ -32,8 +32,8 @@
 
 /**
  * A special purpose store node that differs from {@link CompareAndSwapNode} in that it is not a
- * {@link StateSplit} and it {@linkplain #compareAndSwap(Object, long, Word, Word) returns} either
- * the expected value or the compared against value instead of a boolean.
+ * {@link StateSplit} and it {@linkplain #compareAndSwap(Object, long, Word, Word, Object)} returns
+ * either the expected value or the compared against value instead of a boolean.
  */
 public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRGenLowerable, MemoryCheckpoint {
 
@@ -42,12 +42,15 @@
     @Input private ValueNode expectedValue;
     @Input private ValueNode newValue;
 
-    public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue) {
+    private final Object locationIdentity;
+
+    public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Object locationIdentity) {
         super(expected.stamp());
         this.object = object;
         this.offset = offset;
         this.expectedValue = expected;
         this.newValue = newValue;
+        this.locationIdentity = locationIdentity;
     }
 
     public ValueNode object() {
@@ -68,7 +71,7 @@
 
     @Override
     public Object getLocationIdentity() {
-        return LocationNode.ANY_LOCATION;
+        return locationIdentity;
     }
 
     @Override
@@ -89,5 +92,5 @@
      * @return either {@code expectedValue} or the actual value
      */
     @NodeIntrinsic
-    public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue);
+    public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue, @ConstantNodeParameter Object locationIdentity);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java	Tue Feb 26 16:35:23 2013 +0100
@@ -70,7 +70,7 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
-        Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset)).add(arrayBaseOffset(Kind.Byte));
+        Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Tue Feb 26 16:35:23 2013 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.snippets;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
 import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
 
@@ -33,17 +31,13 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
-import com.oracle.graal.snippets.Snippet.Fold;
 import com.oracle.graal.snippets.nodes.*;
 
 @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Tue Feb 26 16:35:23 2013 +0100
@@ -108,7 +108,7 @@
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
-            if (objectHub.readWord(superCheckOffset).notEqual(hub)) {
+            if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) {
                 probability(DEOPT_PATH_PROBABILITY);
                 displayMiss.inc();
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java	Tue Feb 26 16:35:23 2013 +0100
@@ -66,7 +66,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset));
+        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), UNKNOWN_LOCATION);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true);
         } else {
@@ -75,8 +75,8 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte));
-        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).add(arrayBaseOffset(Kind.Byte));
+        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
@@ -89,7 +89,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset));
+        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), UNKNOWN_LOCATION);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false);
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java	Tue Feb 26 16:35:23 2013 +0100
@@ -45,7 +45,7 @@
             // Class for primitive type
             return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
         } else {
-            return klass.readInt(klassModifierFlagsOffset());
+            return klass.readInt(klassModifierFlagsOffset(), FINAL_LOCATION);
         }
     }
 
@@ -55,7 +55,7 @@
         if (klass.equal(0)) {
             return false;
         } else {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset());
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION);
             return (accessFlags & Modifier.INTERFACE) != 0;
         }
     }
@@ -66,8 +66,7 @@
         if (klass.equal(0)) {
             return false;
         } else {
-            int layoutHelper = klass.readInt(klassLayoutHelperOffset());
-            return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0;
+            return (readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0;
         }
     }
 
@@ -81,17 +80,16 @@
     public static Class<?> getSuperclass(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset());
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION);
             if ((accessFlags & Modifier.INTERFACE) == 0) {
-                int layoutHelper = klass.readInt(klassLayoutHelperOffset());
-                if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
+                if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
                     return Object.class;
                 } else {
-                    Word superKlass = klass.readWord(klassSuperKlassOffset());
+                    Word superKlass = klass.readWord(klassSuperKlassOffset(), FINAL_LOCATION);
                     if (superKlass.equal(0)) {
                         return null;
                     } else {
-                        return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true);
+                        return unsafeCast(superKlass.readObject(classMirrorOffset(), FINAL_LOCATION), Class.class, true, true);
                     }
                 }
             }
@@ -103,9 +101,8 @@
     public static Class<?> getComponentType(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
-            int layoutHelper = klass.readInt(klassLayoutHelperOffset());
-            if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
-                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true);
+            if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
+                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), FINAL_LOCATION), Class.class, true, true);
             }
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Tue Feb 26 16:35:23 2013 +0100
@@ -43,6 +43,10 @@
  */
 public class HotSpotSnippetUtils {
 
+    public static final Object ANY_LOCATION = LocationNode.ANY_LOCATION;
+    public static final Object UNKNOWN_LOCATION = LocationNode.UNKNOWN_LOCATION;
+    public static final Object FINAL_LOCATION = LocationNode.FINAL_LOCATION;
+
     public static HotSpotVMConfig config() {
         return HotSpotGraalRuntime.getInstance().getConfig();
     }
@@ -52,16 +56,49 @@
         return config().verifyOops;
     }
 
+    public static final Object TLAB_TOP_LOCATION = LocationNode.createLocation("TlabTop");
+
     @Fold
     public static int threadTlabTopOffset() {
         return config().threadTlabTopOffset;
     }
 
+    public static final Object TLAB_END_LOCATION = LocationNode.createLocation("TlabEnd");
+
     @Fold
-    public static int threadTlabEndOffset() {
+    private static int threadTlabEndOffset() {
         return config().threadTlabEndOffset;
     }
 
+    public static final Object TLAB_START_LOCATION = LocationNode.createLocation("TlabStart");
+
+    @Fold
+    private static int threadTlabStartOffset() {
+        return config().threadTlabStartOffset;
+    }
+
+    public static Word readTlabTop(Word thread) {
+        return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION);
+    }
+
+    public static Word readTlabEnd(Word thread) {
+        return thread.readWord(threadTlabEndOffset(), TLAB_END_LOCATION);
+    }
+
+    public static Word readTlabStart(Word thread) {
+        return thread.readWord(threadTlabStartOffset(), TLAB_START_LOCATION);
+    }
+
+    public static void writeTlabTop(Word thread, Word top) {
+        thread.writeWord(threadTlabTopOffset(), top, TLAB_TOP_LOCATION);
+    }
+
+    public static void initializeTlab(Word thread, Word start, Word end) {
+        thread.writeWord(threadTlabStartOffset(), start, TLAB_START_LOCATION);
+        thread.writeWord(threadTlabTopOffset(), start, TLAB_TOP_LOCATION);
+        thread.writeWord(threadTlabEndOffset(), end, TLAB_END_LOCATION);
+    }
+
     @Fold
     public static int threadObjectOffset() {
         return config().threadObjectOffset;
@@ -102,6 +139,8 @@
         return Unsafe.getUnsafe().pageSize();
     }
 
+    public static final Object PROTOTYPE_MARK_WORD_LOCATION = LocationNode.createLocation("PrototypeMarkWord");
+
     @Fold
     public static int prototypeMarkWordOffset() {
         return config().prototypeMarkWordOffset;
@@ -118,10 +157,14 @@
     }
 
     @Fold
-    public static int klassLayoutHelperOffset() {
+    private static int klassLayoutHelperOffset() {
         return config().klassLayoutHelperOffset;
     }
 
+    public static int readLayoutHelper(Word klass) {
+        return klass.readInt(klassLayoutHelperOffset(), FINAL_LOCATION);
+    }
+
     @Fold
     public static int arrayKlassLayoutHelperIdentifier() {
         return config().arrayKlassLayoutHelperIdentifier;
@@ -137,11 +180,25 @@
         return config().klassSuperKlassOffset;
     }
 
+    public static final Object MARK_WORD_LOCATION = LocationNode.createLocation("MarkWord");
+
     @Fold
     public static int markOffset() {
         return config().markOffset;
     }
 
+    public static final Object HUB_LOCATION = LocationNode.createLocation("Hub");
+
+    @Fold
+    private static int hubOffset() {
+        return config().hubOffset;
+    }
+
+    public static void initializeObjectHeader(Word memory, Word markWord, Word hub) {
+        memory.writeWord(markOffset(), markWord, MARK_WORD_LOCATION);
+        memory.writeWord(hubOffset(), hub, HUB_LOCATION);
+    }
+
     @Fold
     public static int unlockedMask() {
         return config().unlockedMask;
@@ -188,11 +245,6 @@
     }
 
     @Fold
-    public static int hubOffset() {
-        return config().hubOffset;
-    }
-
-    @Fold
     public static int metaspaceArrayLengthOffset() {
         return config().metaspaceArrayLengthOffset;
     }
@@ -232,16 +284,22 @@
         return config().superCheckOffsetOffset;
     }
 
+    public static final Object SECONDARY_SUPER_CACHE_LOCATION = LocationNode.createLocation("SecondarySuperCache");
+
     @Fold
     public static int secondarySuperCacheOffset() {
         return config().secondarySuperCacheOffset;
     }
 
+    public static final Object SECONDARY_SUPERS_LOCATION = LocationNode.createLocation("SecondarySupers");
+
     @Fold
     public static int secondarySupersOffset() {
         return config().secondarySupersOffset;
     }
 
+    public static final Object DISPLACED_MARK_WORD_LOCATION = LocationNode.createLocation("DisplacedMarkWord");
+
     @Fold
     public static int lockDisplacedMarkOffset() {
         return config().basicLockDisplacedHeaderOffset;
@@ -308,12 +366,19 @@
         return CodeUtil.log2(wordSize());
     }
 
+    public static final Object CLASS_STATE_LOCATION = LocationNode.createLocation("ClassState");
+
     @Fold
     public static int klassStateOffset() {
         return config().klassStateOffset;
     }
 
     @Fold
+    public static int klassStateFullyInitialized() {
+        return config().klassStateFullyInitialized;
+    }
+
+    @Fold
     public static int klassModifierFlagsOffset() {
         return config().klassModifierFlagsOffset;
     }
@@ -333,22 +398,21 @@
         return config().klassInstanceSizeOffset;
     }
 
+    public static final Object HEAP_TOP_LOCATION = LocationNode.createLocation("HeapTop");
+
     @Fold
     public static long heapTopAddress() {
         return config().heapTopAddress;
     }
 
+    public static final Object HEAP_END_LOCATION = LocationNode.createLocation("HeapEnd");
+
     @Fold
     public static long heapEndAddress() {
         return config().heapEndAddress;
     }
 
     @Fold
-    public static int threadTlabStartOffset() {
-        return config().threadTlabStartOffset;
-    }
-
-    @Fold
     public static long tlabIntArrayMarkWord() {
         return config().tlabIntArrayMarkWord;
     }
@@ -363,36 +427,43 @@
         return config().tlabAlignmentReserve;
     }
 
+    public static final Object TLAB_SIZE_LOCATION = LocationNode.createLocation("TlabSize");
+
     @Fold
     public static int threadTlabSizeOffset() {
         return config().threadTlabSizeOffset;
     }
 
+    public static final Object TLAB_THREAD_ALLOCATED_BYTES_LOCATION = LocationNode.createLocation("TlabThreadAllocatedBytes");
+
     @Fold
     public static int threadAllocatedBytesOffset() {
         return config().threadAllocatedBytesOffset;
     }
 
-    @Fold
-    public static int klassStateFullyInitialized() {
-        return config().klassStateFullyInitialized;
-    }
+    public static final Object TLAB_REFILL_WASTE_LIMIT_LOCATION = LocationNode.createLocation("RefillWasteLimit");
 
     @Fold
     public static int tlabRefillWasteLimitOffset() {
         return config().tlabRefillWasteLimitOffset;
     }
 
+    public static final Object TLAB_NOF_REFILLS_LOCATION = LocationNode.createLocation("TlabNOfRefills");
+
     @Fold
     public static int tlabNumberOfRefillsOffset() {
         return config().tlabNumberOfRefillsOffset;
     }
 
+    public static final Object TLAB_FAST_REFILL_WASTE_LOCATION = LocationNode.createLocation("TlabFastRefillWaste");
+
     @Fold
     public static int tlabFastRefillWasteOffset() {
         return config().tlabFastRefillWasteOffset;
     }
 
+    public static final Object TLAB_SLOW_ALLOCATIONS_LOCATION = LocationNode.createLocation("TlabSlowAllocations");
+
     @Fold
     public static int tlabSlowAllocationsOffset() {
         return config().tlabSlowAllocationsOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Tue Feb 26 16:35:23 2013 +0100
@@ -99,7 +99,7 @@
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (objectHub.readWord(superCheckOffset).notEqual(hub)) {
+        if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) {
             probability(NOT_LIKELY_PROBABILITY);
             displayMiss.inc();
             return falseValue;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Tue Feb 26 16:35:23 2013 +0100
@@ -40,6 +40,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -109,7 +110,7 @@
                 // The bias pattern is present in the object's mark word. Need to check
                 // whether the bias owner and the epoch are both still current.
                 Word hub = loadHub(object);
-                final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
+                final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
                 final Word thread = thread();
                 final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace());
                 trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord);
@@ -154,7 +155,7 @@
                         Word biasedMark = unbiasedMark.or(thread);
                         trace(trace, "     unbiasedMark: 0x%016lx\n", unbiasedMark);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark).equal(unbiasedMark)) {
+                        if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark)) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:acquired}", object);
                             return;
@@ -175,7 +176,7 @@
                         // the bias from one thread to another directly in this situation.
                         Word biasedMark = prototypeMarkWord.or(thread);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (compareAndSwap(object, markOffset(), mark, biasedMark).equal(mark)) {
+                        if (compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark)) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:transfer}", object);
                             return;
@@ -197,7 +198,7 @@
                     // that another thread raced us for the privilege of revoking the
                     // bias of this particular object, so it's okay to continue in the
                     // normal locking code.
-                    Word result = compareAndSwap(object, markOffset(), mark, prototypeMarkWord);
+                    Word result = compareAndSwap(object, markOffset(), mark, prototypeMarkWord, MARK_WORD_LOCATION);
 
                     // Fall through to the normal CAS-based lock, because no matter what
                     // the result of the above CAS, some thread must have succeeded in
@@ -215,11 +216,11 @@
         trace(trace, "     unlockedMark: 0x%016lx\n", unlockedMark);
 
         // Copy this unlocked mark word into the lock slot on the stack
-        lock.writeWord(lockDisplacedMarkOffset(), unlockedMark);
+        lock.writeWord(lockDisplacedMarkOffset(), unlockedMark, DISPLACED_MARK_WORD_LOCATION);
 
         // Test if the object's mark word is unlocked, and if so, store the
         // (address of) the lock slot into the object's mark word.
-        Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock);
+        Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock, MARK_WORD_LOCATION);
         if (currentMark.notEqual(unlockedMark)) {
             trace(trace, "      currentMark: 0x%016lx\n", currentMark);
             // The mark word in the object header was not the same.
@@ -247,7 +248,7 @@
                 return;
             } else {
                 // Recursively locked => write 0 to the lock slot
-                lock.writeWord(lockDisplacedMarkOffset(), Word.zero());
+                lock.writeWord(lockDisplacedMarkOffset(), Word.zero(), DISPLACED_MARK_WORD_LOCATION);
                 traceObject(trace, "+lock{recursive}", object);
             }
         } else {
@@ -302,7 +303,7 @@
         final Word lock = CurrentLockNode.currentLock();
 
         // Load displaced mark
-        final Word displacedMark = lock.readWord(lockDisplacedMarkOffset());
+        final Word displacedMark = lock.readWord(lockDisplacedMarkOffset(), DISPLACED_MARK_WORD_LOCATION);
         trace(trace, "    displacedMark: 0x%016lx\n", displacedMark);
 
         if (displacedMark.equal(0)) {
@@ -313,7 +314,7 @@
             // Test if object's mark word is pointing to the displaced mark word, and if so, restore
             // the displaced mark in the object - if the object's mark word is not pointing to
             // the displaced mark word, do unlocking via runtime call.
-            if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark).notEqual(lock)) {
+            if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock)) {
                 // The object's mark word was not pointing to the displaced header,
                 // we do unlocking via runtime call.
                 probability(DEOPT_PATH_PROBABILITY);
@@ -365,35 +366,37 @@
      */
     private static final boolean ENABLE_BREAKPOINT = false;
 
+    private static final Object MONITOR_COUNTER_LOCATION = LocationNode.createLocation("MonitorCounter");
+
     @NodeIntrinsic(BreakpointNode.class)
     static native void bkpt(Object object, Word mark, Word tmp, Word value);
 
     private static void incCounter() {
         if (CHECK_BALANCED_MONITORS) {
             final Word counter = MonitorCounterNode.counter();
-            final int count = counter.readInt(0);
-            counter.writeInt(0, count + 1);
+            final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
+            counter.writeInt(0, count + 1, MONITOR_COUNTER_LOCATION);
         }
     }
 
     private static void decCounter() {
         if (CHECK_BALANCED_MONITORS) {
             final Word counter = MonitorCounterNode.counter();
-            final int count = counter.readInt(0);
-            counter.writeInt(0, count - 1);
+            final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
+            counter.writeInt(0, count - 1, MONITOR_COUNTER_LOCATION);
         }
     }
 
     @Snippet
     private static void initCounter() {
         final Word counter = MonitorCounterNode.counter();
-        counter.writeInt(0, 0);
+        counter.writeInt(0, 0, MONITOR_COUNTER_LOCATION);
     }
 
     @Snippet
     private static void checkCounter(String errMsg) {
         final Word counter = MonitorCounterNode.counter();
-        final int count = counter.readInt(0);
+        final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
         if (count != 0) {
             vmError(errMsg, count);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Tue Feb 26 16:35:23 2013 +0100
@@ -29,8 +29,8 @@
 import static com.oracle.graal.snippets.Snippet.Varargs.*;
 import static com.oracle.graal.snippets.SnippetTemplate.*;
 import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
+import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
 import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*;
-import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -62,13 +62,13 @@
     @Snippet
     public static Word allocate(@Parameter("size") int size) {
         Word thread = thread();
-        Word top = thread.readWord(threadTlabTopOffset());
-        Word end = thread.readWord(threadTlabEndOffset());
+        Word top = readTlabTop(thread);
+        Word end = readTlabEnd(thread);
         Word newTop = top.add(size);
         // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code)
         if (newTop.belowOrEqual(end)) {
             probability(FAST_PATH_PROBABILITY);
-            thread.writeWord(threadTlabTopOffset(), newTop);
+            writeTlabTop(thread, newTop);
             return top;
         }
         return Word.zero();
@@ -178,7 +178,7 @@
         Word dims = DimensionsNode.allocaDimsArray(rank);
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < rank; i++) {
-            dims.writeInt(i * 4, dimensions[i]);
+            dims.writeInt(i * 4, dimensions[i], ANY_LOCATION);
         }
         return NewMultiArrayStubCall.call(hub, rank, dims);
     }
@@ -194,20 +194,19 @@
      * Formats some allocated memory with an object header zeroes out the rest.
      */
     private static void formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents) {
-        Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset()) : compileTimePrototypeMarkWord;
-        memory.writeWord(markOffset(), prototypeMarkWord);
-        memory.writeWord(hubOffset(), hub);
+        Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
+        initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
             if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) {
                 new_seqInit.inc();
                 explodeLoop();
                 for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
-                    memory.writeWord(offset, Word.zero());
+                    memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                 }
             } else {
                 new_loopInit.inc();
                 for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
-                    memory.writeWord(offset, Word.zero());
+                    memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                 }
             }
         }
@@ -217,13 +216,12 @@
      * Formats some allocated memory with an object header zeroes out the rest.
      */
     public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
-        memory.writeWord(markOffset(), prototypeMarkWord);
-        memory.writeInt(arrayLengthOffset(), length);
+        memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION);
         // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null
-        memory.writeWord(hubOffset(), hub);
+        initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
             for (int offset = headerSize; offset < allocationSize; offset += wordSize()) {
-                memory.writeWord(offset, Word.zero());
+                memory.writeWord(offset, Word.zero(), ANY_LOCATION);
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java	Tue Feb 26 16:35:23 2013 +0100
@@ -53,12 +53,12 @@
     private static Object instanceClone(Object src, Word hub, int layoutHelper) {
         int instanceSize = layoutHelper;
         Pointer memory = NewObjectSnippets.allocate(instanceSize);
-        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
+        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
         Object result = NewObjectSnippets.initializeObject((Word) memory, hub, prototypeMarkWord, instanceSize, false, false);
 
         memory = Word.fromObject(result);
         for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) {
-            memory.writeWord(offset, Word.fromObject(src).readWord(offset));
+            memory.writeWord(offset, Word.fromObject(src).readWord(offset, UNKNOWN_LOCATION), ANY_LOCATION);
         }
 
         return result;
@@ -71,12 +71,12 @@
         int sizeInBytes = NewObjectSnippets.computeArrayAllocationSize(arrayLength, wordSize(), headerSize, log2ElementSize);
 
         Pointer memory = NewObjectSnippets.allocate(sizeInBytes);
-        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
+        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
         Object result = NewObjectSnippets.initializeArray((Word) memory, hub, arrayLength, sizeInBytes, prototypeMarkWord, headerSize, false, false);
 
         memory = Word.fromObject(result);
         for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) {
-            memory.writeWord(offset, Word.fromObject(src).readWord(offset));
+            memory.writeWord(offset, Word.fromObject(src).readWord(offset, UNKNOWN_LOCATION), ANY_LOCATION);
         }
         return result;
     }
@@ -94,14 +94,14 @@
     public static Object instanceClone(Object src) {
         instanceCloneCounter.inc();
         Word hub = getAndCheckHub(src);
-        return instanceClone(src, hub, hub.readInt(layoutHelperOffset()));
+        return instanceClone(src, hub, hub.readInt(layoutHelperOffset(), FINAL_LOCATION));
     }
 
     @Snippet
     public static Object arrayClone(Object src) {
         arrayCloneCounter.inc();
         Word hub = getAndCheckHub(src);
-        int layoutHelper = hub.readInt(layoutHelperOffset());
+        int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         return arrayClone(src, hub, layoutHelper);
     }
 
@@ -109,7 +109,7 @@
     public static Object genericClone(Object src) {
         genericCloneCounter.inc();
         Word hub = getAndCheckHub(src);
-        int layoutHelper = hub.readInt(layoutHelperOffset());
+        int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         if (layoutHelper < 0) {
             probability(LIKELY_PROBABILITY);
             genericArrayCloneCounter.inc();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java	Tue Feb 26 16:35:23 2013 +0100
@@ -25,8 +25,10 @@
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.snippets.*;
-import com.oracle.graal.snippets.ClassSubstitution.*;
+import com.oracle.graal.snippets.ClassSubstitution.MacroSubstitution;
+import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
 import com.oracle.graal.word.*;
 
 /**
@@ -38,7 +40,7 @@
     @MethodSubstitution(isStatic = false)
     public static Class<?> getClass(final Object thisObj) {
         Word hub = loadHub(thisObj);
-        return unsafeCast(hub.readFinalObject(Word.signed(classMirrorOffset())), Class.class, true, true);
+        return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationNode.FINAL_LOCATION), Class.class, true, true);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java	Tue Feb 26 16:35:23 2013 +0100
@@ -43,10 +43,10 @@
     @MethodSubstitution(isStatic = false)
     private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
         Word rawThread = HotSpotCurrentRawThreadNode.get();
-        Thread thread = (Thread) rawThread.readObject(threadObjectOffset());
+        Thread thread = (Thread) rawThread.readObject(threadObjectOffset(), FINAL_LOCATION);
         if (thisObject == thread) {
-            Word osThread = rawThread.readWord(osThreadOffset());
-            boolean interrupted = osThread.readInt(osThreadInterruptedOffset()) != 0;
+            Word osThread = rawThread.readWord(osThreadOffset(), FINAL_LOCATION);
+            boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), UNKNOWN_LOCATION) != 0;
             if (!interrupted || !clearInterrupted) {
                 return interrupted;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java	Tue Feb 26 16:35:23 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.word.*;
@@ -39,9 +40,11 @@
  */
 public class TypeCheckSnippetUtils {
 
+    public static final Object TYPE_DISPLAY_LOCATION = LocationNode.createLocation("TypeDisplay");
+
     static boolean checkSecondarySubType(Word t, Word s) {
         // if (S.cache == T) return true
-        if (s.readWord(secondarySuperCacheOffset()).equal(t)) {
+        if (s.readWord(secondarySuperCacheOffset(), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) {
             cacheHit.inc();
             return true;
         }
@@ -51,11 +54,11 @@
 
     static boolean checkUnknownSubType(Word t, Word s) {
         // int off = T.offset
-        int superCheckOffset = t.readInt(superCheckOffsetOffset());
+        int superCheckOffset = t.readInt(superCheckOffsetOffset(), FINAL_LOCATION);
         boolean primary = superCheckOffset != secondarySuperCacheOffset();
 
         // if (T = S[off]) return true
-        if (s.readWord(superCheckOffset).equal(t)) {
+        if (s.readWord(superCheckOffset, TYPE_DISPLAY_LOCATION).equal(t)) {
             if (primary) {
                 cacheHit.inc();
             } else {
@@ -81,12 +84,12 @@
         }
 
         // if (S.scan_s_s_array(T)) { S.cache = T; return true; }
-        Word secondarySupers = s.readWord(secondarySupersOffset());
-        int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
+        Word secondarySupers = s.readWord(secondarySupersOffset(), SECONDARY_SUPERS_LOCATION);
+        int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), FINAL_LOCATION);
         for (int i = 0; i < length; i++) {
-            if (t.equal(loadWordElement(secondarySupers, i))) {
+            if (t.equal(loadSecondarySupersElement(secondarySupers, i))) {
                 probability(NOT_LIKELY_PROBABILITY);
-                s.writeWord(secondarySuperCacheOffset(), t);
+                s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION);
                 secondariesHit.inc();
                 return true;
             }
@@ -103,8 +106,8 @@
         return hintHubs;
     }
 
-    static Word loadWordElement(Word metaspaceArray, int index) {
-        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize());
+    static Word loadSecondarySupersElement(Word metaspaceArray, int index) {
+        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), FINAL_LOCATION);
     }
 
     private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("TypeCheck") : null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Tue Feb 26 16:35:23 2013 +0100
@@ -67,7 +67,7 @@
      */
     @Snippet
     private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
-        int layoutHelper = hub.readInt(layoutHelperOffset());
+        int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
         int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Tue Feb 26 16:35:23 2013 +0100
@@ -67,16 +67,15 @@
      */
     @Snippet
     private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
-        int sizeInBytes = hub.readInt(klassInstanceSizeOffset());
+        int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION);
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
-            if (hub.readInt(klassStateOffset()) == klassStateFullyInitialized()) {
+            if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) {
                 Word memory = refillAllocate(intArrayHub, sizeInBytes, log);
                 if (memory.notEqual(0)) {
-                    Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
-                    memory.writeWord(markOffset(), prototypeMarkWord);
-                    memory.writeWord(hubOffset(), hub);
+                    Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
+                    initializeObjectHeader(memory, prototypeMarkWord, hub);
                     for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) {
-                        memory.writeWord(offset, Word.zero());
+                        memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                     }
                     return verifyOop(memory.toObject());
                 }
@@ -100,8 +99,8 @@
         int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords() * wordSize();
 
         Word thread = thread();
-        Word top = thread.readWord(threadTlabTopOffset());
-        Word end = thread.readWord(threadTlabEndOffset());
+        Word top = readTlabTop(thread);
+        Word end = readTlabEnd(thread);
 
         // calculate amount of free space
         Word tlabFreeSpaceInBytes = end.subtract(top);
@@ -115,16 +114,16 @@
 
         // Retain TLAB and allocate object in shared space if
         // the amount free in the TLAB is too large to discard.
-        Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset());
+        Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset(), TLAB_REFILL_WASTE_LIMIT_LOCATION);
         if (tlabFreeSpaceInWords.belowOrEqual(refillWasteLimit)) {
             if (tlabStats()) {
                 // increment number of refills
-                thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1);
-                log(log, "thread: %p -- number_of_refills %d\n", thread, thread.readInt(tlabNumberOfRefillsOffset()));
+                thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION) + 1, TLAB_NOF_REFILLS_LOCATION);
+                log(log, "thread: %p -- number_of_refills %d\n", thread, thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION));
                 // accumulate wastage
-                Word wastage = thread.readWord(tlabFastRefillWasteOffset()).add(tlabFreeSpaceInWords);
+                Word wastage = thread.readWord(tlabFastRefillWasteOffset(), TLAB_FAST_REFILL_WASTE_LOCATION).add(tlabFreeSpaceInWords);
                 log(log, "thread: %p -- accumulated wastage %d\n", thread, wastage);
-                thread.writeWord(tlabFastRefillWasteOffset(), wastage);
+                thread.writeWord(tlabFastRefillWasteOffset(), wastage, TLAB_FAST_REFILL_WASTE_LOCATION);
             }
 
             // if TLAB is currently allocated (top or end != null) then
@@ -137,22 +136,19 @@
                 int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts;
                 NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false);
 
-                Word allocated = thread.readWord(threadAllocatedBytesOffset());
-                allocated = allocated.add(top.subtract(thread.readWord(threadTlabStartOffset())));
-                thread.writeWord(threadAllocatedBytesOffset(), allocated);
+                Word allocated = thread.readWord(threadAllocatedBytesOffset(), TLAB_THREAD_ALLOCATED_BYTES_LOCATION);
+                allocated = allocated.add(top.subtract(readTlabStart(thread)));
+                thread.writeWord(threadAllocatedBytesOffset(), allocated, TLAB_THREAD_ALLOCATED_BYTES_LOCATION);
             }
 
             // refill the TLAB with an eden allocation
-            Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset());
+            Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset(), TLAB_SIZE_LOCATION);
             Word tlabRefillSizeInBytes = tlabRefillSizeInWords.multiply(wordSize());
             // allocate new TLAB, address returned in top
             top = edenAllocate(tlabRefillSizeInBytes, log);
             if (top.notEqual(0)) {
-                thread.writeWord(threadTlabStartOffset(), top);
-                thread.writeWord(threadTlabTopOffset(), top);
-
                 end = top.add(tlabRefillSizeInBytes.subtract(alignmentReserveInBytes));
-                thread.writeWord(threadTlabEndOffset(), end);
+                initializeTlab(thread, top, end);
 
                 return allocate(sizeInBytes);
             } else {
@@ -161,11 +157,11 @@
         } else {
             // Retain TLAB
             Word newRefillWasteLimit = refillWasteLimit.add(tlabRefillWasteIncrement());
-            thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit);
+            thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit, TLAB_REFILL_WASTE_LIMIT_LOCATION);
             log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit);
 
             if (tlabStats()) {
-                thread.writeInt(tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1);
+                thread.writeInt(tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset(), TLAB_SLOW_ALLOCATIONS_LOCATION) + 1, TLAB_SLOW_ALLOCATIONS_LOCATION);
             }
 
             return edenAllocate(Word.unsigned(sizeInBytes), log);
@@ -184,18 +180,18 @@
         Word heapEndAddress = Word.unsigned(heapEndAddress());
 
         while (true) {
-            Word heapTop = heapTopAddress.readWord(0);
+            Word heapTop = heapTopAddress.readWord(0, HEAP_TOP_LOCATION);
             Word newHeapTop = heapTop.add(sizeInBytes);
             if (newHeapTop.belowOrEqual(heapTop)) {
                 return Word.zero();
             }
 
-            Word heapEnd = heapEndAddress.readWord(0);
+            Word heapEnd = heapEndAddress.readWord(0, HEAP_END_LOCATION);
             if (newHeapTop.aboveThan(heapEnd)) {
                 return Word.zero();
             }
 
-            if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop).equal(heapTop)) {
+            if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop, HEAP_TOP_LOCATION).equal(heapTop)) {
                 return heapTop;
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Tue Feb 26 16:35:23 2013 +0100
@@ -43,27 +43,37 @@
     private Object locationIdentity;
 
     /**
+     * Creates a new unique location identity for read and write operations.
+     * 
+     * @param name the name of the new location identity, for debugging purposes
+     * @return the new location identity
+     */
+    public static Object createLocation(final String name) {
+        return new Object() {
+
+            @Override
+            public String toString() {
+                return name;
+            }
+        };
+    }
+
+    /**
      * Denotes any location. A write to such a location kills all values in a memory map during an
      * analysis of memory accesses in a graph.
      */
-    public static final Object ANY_LOCATION = new Object() {
+    public static final Object ANY_LOCATION = createLocation("ANY_LOCATION");
 
-        @Override
-        public String toString() {
-            return "ANY_LOCATION";
-        }
-    };
+    /**
+     * Denotes an unknown location. A read from this location cannot be moved or coalesced with
+     * other reads because its interaction with other reads is not known.
+     */
+    public static final Object UNKNOWN_LOCATION = createLocation("UNKNOWN_LOCATION");
 
     /**
      * Denotes the location of a value that is guaranteed to be final.
      */
-    public static final Object FINAL_LOCATION = new Object() {
-
-        @Override
-        public String toString() {
-            return "FINAL_LOCATION";
-        }
-    };
+    public static final Object FINAL_LOCATION = createLocation("FINAL_LOCATION");
 
     public static Object getArrayLocation(Kind elementKind) {
         return elementKind;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Feb 26 16:35:23 2013 +0100
@@ -206,20 +206,22 @@
         StructuredGraph graph = (StructuredGraph) readNode.graph();
         assert readNode.getNullCheck() == false;
         Object locationIdentity = readNode.location().locationIdentity();
-        ValueNode lastLocationAccess = getLastLocationAccessForRead(state, locationIdentity);
-        FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies()));
-        floatingRead.setNullCheck(readNode.getNullCheck());
-        ValueAnchorNode anchor = null;
-        for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
-            if (anchor == null) {
-                anchor = graph.add(new ValueAnchorNode());
+        if (locationIdentity != LocationNode.UNKNOWN_LOCATION) {
+            ValueNode lastLocationAccess = getLastLocationAccessForRead(state, locationIdentity);
+            FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies()));
+            floatingRead.setNullCheck(readNode.getNullCheck());
+            ValueAnchorNode anchor = null;
+            for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
+                if (anchor == null) {
+                    anchor = graph.add(new ValueAnchorNode());
+                }
+                anchor.addAnchoredNode(guard);
             }
-            anchor.addAnchoredNode(guard);
+            if (anchor != null) {
+                graph.addAfterFixed(readNode, anchor);
+            }
+            graph.replaceFixedWithFloating(readNode, floatingRead);
         }
-        if (anchor != null) {
-            graph.addAfterFixed(readNode, anchor);
-        }
-        graph.replaceFixedWithFloating(readNode, floatingRead);
     }
 
     private ValueNode getLastLocationAccessForRead(MemoryMap state, Object locationIdentity) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Tue Feb 26 16:35:23 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.word;
 
+import com.oracle.graal.nodes.extended.*;
+
 public interface Pointer extends Unsigned {
 
     /**
@@ -42,9 +44,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    byte readByte(WordBase offset);
+    byte readByte(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -55,9 +58,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    char readChar(WordBase offset);
+    char readChar(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -68,9 +72,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    short readShort(WordBase offset);
+    short readShort(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -81,9 +86,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    int readInt(WordBase offset);
+    int readInt(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -94,9 +100,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    long readLong(WordBase offset);
+    long readLong(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -107,9 +114,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    float readFloat(WordBase offset);
+    float readFloat(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -120,9 +128,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    double readDouble(WordBase offset);
+    double readDouble(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -133,9 +142,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    Word readWord(WordBase offset);
+    Word readWord(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -146,234 +156,142 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    Object readObject(WordBase offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    byte readByte(int offset);
+    Object readObject(WordBase offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    char readChar(int offset);
+    byte readByte(int offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    short readShort(int offset);
+    char readChar(int offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    int readInt(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    long readLong(int offset);
+    short readShort(int offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    float readFloat(int offset);
+    int readInt(int offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    double readDouble(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    Word readWord(int offset);
+    long readLong(int offset, Object locationIdentity);
 
     /**
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    Object readObject(int offset);
+    float readFloat(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    double readDouble(int offset, Object locationIdentity);
 
     /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <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).
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
      * @return the result of the memory access
      */
-    byte readFinalByte(WordBase offset);
+    Word readWord(int offset, Object locationIdentity);
 
     /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    Object readObject(int offset, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
      * <p>
      * The offset is always treated as a {@link Signed} value. However, the static type is
      * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
-     * @return the result of the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
      */
-    char readFinalChar(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    short readFinalShort(WordBase offset);
+    void writeByte(WordBase offset, byte val, Object locationIdentity);
 
     /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    int readFinalInt(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
      * <p>
      * The offset is always treated as a {@link Signed} value. However, the static type is
      * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
-     * @return the result of the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
      */
-    long readFinalLong(WordBase offset);
+    void writeChar(WordBase offset, char val, Object locationIdentity);
 
     /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    float readFinalFloat(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
      * <p>
      * The offset is always treated as a {@link Signed} value. However, the static type is
      * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    double readFinalDouble(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <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
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
      */
-    Word readFinalWord(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <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 readFinalObject(WordBase offset);
+    void writeShort(WordBase offset, Short val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -384,9 +302,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeByte(WordBase offset, byte val);
+    void writeInt(WordBase offset, int val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -397,22 +316,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeChar(WordBase offset, char val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeShort(WordBase offset, Short val);
+    void writeLong(WordBase offset, long val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -423,9 +330,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeInt(WordBase offset, int val);
+    void writeFloat(WordBase offset, float val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -436,9 +344,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeLong(WordBase offset, long val);
+    void writeDouble(WordBase offset, double val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -449,22 +358,10 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeFloat(WordBase offset, float val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeDouble(WordBase offset, double val);
+    void writeWord(WordBase offset, WordBase val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
@@ -475,103 +372,100 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeWord(WordBase offset, WordBase val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeObject(WordBase offset, Object val);
+    void writeObject(WordBase offset, Object val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeByte(int offset, byte val);
+    void writeByte(int offset, byte val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeChar(int offset, char val);
+    void writeChar(int offset, char val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeShort(int offset, short val);
+    void writeShort(int offset, short val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeInt(int offset, int val);
+    void writeInt(int offset, int val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeLong(int offset, long val);
+    void writeLong(int offset, long val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeFloat(int offset, float val);
+    void writeFloat(int offset, float val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeDouble(int offset, double val);
+    void writeDouble(int offset, double val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeWord(int offset, WordBase val);
+    void writeWord(int offset, WordBase val, Object locationIdentity);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
-    void writeObject(int offset, Object val);
+    void writeObject(int offset, Object val, Object locationIdentity);
 
     // Math functions that are defined in Unsigned, but known to preserve the
     // pointer-characteristics.
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Tue Feb 26 16:35:23 2013 +0100
@@ -58,7 +58,6 @@
          COMPARISON,
          NOT,
          READ,
-         READ_FINAL,
          WRITE,
          ZERO,
          FROM_UNSIGNED,
@@ -598,268 +597,214 @@
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public byte readByte(WordBase offset) {
+    public byte readByte(WordBase offset, Object locationIdentity) {
         return unsafe.getByte(add((Word) offset).unbox());
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public char readChar(WordBase offset) {
+    public char readChar(WordBase offset, Object locationIdentity) {
         return unsafe.getChar(add((Word) offset).unbox());
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public short readShort(WordBase offset) {
+    public short readShort(WordBase offset, Object locationIdentity) {
         return unsafe.getShort(add((Word) offset).unbox());
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public int readInt(WordBase offset) {
+    public int readInt(WordBase offset, Object locationIdentity) {
         return unsafe.getInt(add((Word) offset).unbox());
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public long readLong(WordBase offset) {
+    public long readLong(WordBase offset, Object locationIdentity) {
         return unsafe.getLong(add((Word) offset).unbox());
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public float readFloat(WordBase offset) {
+    public float readFloat(WordBase offset, Object locationIdentity) {
         return unsafe.getFloat(add((Word) offset).unbox());
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public double readDouble(WordBase offset) {
+    public double readDouble(WordBase offset, Object locationIdentity) {
         return unsafe.getDouble(add((Word) offset).unbox());
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public Word readWord(WordBase offset) {
+    public Word readWord(WordBase offset, Object locationIdentity) {
         return box(unsafe.getAddress(add((Word) offset).unbox()));
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public native Object readObject(WordBase offset);
+    public native Object readObject(WordBase offset, Object locationIdentity);
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public byte readByte(int offset) {
-        return readByte(signed(offset));
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ)
-    public char readChar(int offset) {
-        return readChar(signed(offset));
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ)
-    public short readShort(int offset) {
-        return readShort(signed(offset));
+    public byte readByte(int offset, Object locationIdentity) {
+        return readByte(signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public int readInt(int offset) {
-        return readInt(signed(offset));
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ)
-    public long readLong(int offset) {
-        return readLong(signed(offset));
+    public char readChar(int offset, Object locationIdentity) {
+        return readChar(signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public float readFloat(int offset) {
-        return readFloat(signed(offset));
+    public short readShort(int offset, Object locationIdentity) {
+        return readShort(signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public double readDouble(int offset) {
-        return readDouble(signed(offset));
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ)
-    public Word readWord(int offset) {
-        return readWord(signed(offset));
+    public int readInt(int offset, Object locationIdentity) {
+        return readInt(signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ)
-    public Object readObject(int offset) {
-        return readObject(signed(offset));
+    public long readLong(int offset, Object locationIdentity) {
+        return readLong(signed(offset), locationIdentity);
     }
 
     @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public byte readFinalByte(WordBase offset) {
-        return readByte(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public char readFinalChar(WordBase offset) {
-        return readChar(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public short readFinalShort(WordBase offset) {
-        return readShort(offset);
+    @Operation(opcode = Opcode.READ)
+    public float readFloat(int offset, Object locationIdentity) {
+        return readFloat(signed(offset), locationIdentity);
     }
 
     @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public int readFinalInt(WordBase offset) {
-        return readInt(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public long readFinalLong(WordBase offset) {
-        return readLong(offset);
+    @Operation(opcode = Opcode.READ)
+    public double readDouble(int offset, Object locationIdentity) {
+        return readDouble(signed(offset), locationIdentity);
     }
 
     @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public float readFinalFloat(WordBase offset) {
-        return readFloat(offset);
+    @Operation(opcode = Opcode.READ)
+    public Word readWord(int offset, Object locationIdentity) {
+        return readWord(signed(offset), locationIdentity);
     }
 
     @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public double readFinalDouble(WordBase offset) {
-        return readDouble(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public Word readFinalWord(WordBase offset) {
-        return readWord(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public Object readFinalObject(WordBase offset) {
-        return readObject(offset);
+    @Operation(opcode = Opcode.READ)
+    public Object readObject(int offset, Object locationIdentity) {
+        return readObject(signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeByte(WordBase offset, byte val) {
+    public void writeByte(WordBase offset, byte val, Object locationIdentity) {
         unsafe.putByte(add((Word) offset).unbox(), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeChar(WordBase offset, char val) {
+    public void writeChar(WordBase offset, char val, Object locationIdentity) {
         unsafe.putChar(add((Word) offset).unbox(), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeShort(WordBase offset, Short val) {
+    public void writeShort(WordBase offset, Short val, Object locationIdentity) {
         unsafe.putShort(add((Word) offset).unbox(), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeInt(WordBase offset, int val) {
+    public void writeInt(WordBase offset, int val, Object locationIdentity) {
         unsafe.putInt(add((Word) offset).unbox(), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeLong(WordBase offset, long val) {
+    public void writeLong(WordBase offset, long val, Object locationIdentity) {
         unsafe.putLong(add((Word) offset).unbox(), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeFloat(WordBase offset, float val) {
+    public void writeFloat(WordBase offset, float val, Object locationIdentity) {
         unsafe.putFloat(add((Word) offset).unbox(), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeDouble(WordBase offset, double val) {
+    public void writeDouble(WordBase offset, double val, Object locationIdentity) {
         unsafe.putDouble(add((Word) offset).unbox(), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeWord(WordBase offset, WordBase val) {
+    public void writeWord(WordBase offset, WordBase val, Object locationIdentity) {
         unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public native void writeObject(WordBase offset, Object val);
+    public native void writeObject(WordBase offset, Object val, Object locationIdentity);
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeByte(int offset, byte val) {
-        writeByte(signed(offset), val);
+    public void writeByte(int offset, byte val, Object locationIdentity) {
+        writeByte(signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeChar(int offset, char val) {
-        writeChar(signed(offset), val);
+    public void writeChar(int offset, char val, Object locationIdentity) {
+        writeChar(signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeShort(int offset, short val) {
-        writeShort(signed(offset), val);
+    public void writeShort(int offset, short val, Object locationIdentity) {
+        writeShort(signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeInt(int offset, int val) {
-        writeInt(signed(offset), val);
+    public void writeInt(int offset, int val, Object locationIdentity) {
+        writeInt(signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeLong(int offset, long val) {
-        writeLong(signed(offset), val);
+    public void writeLong(int offset, long val, Object locationIdentity) {
+        writeLong(signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeFloat(int offset, float val) {
-        writeFloat(signed(offset), val);
+    public void writeFloat(int offset, float val, Object locationIdentity) {
+        writeFloat(signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeDouble(int offset, double val) {
-        writeDouble(signed(offset), val);
+    public void writeDouble(int offset, double val, Object locationIdentity) {
+        writeDouble(signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeWord(int offset, WordBase val) {
-        writeWord(signed(offset), val);
+    public void writeWord(int offset, WordBase val, Object locationIdentity) {
+        writeWord(signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeObject(int offset, Object val) {
-        writeObject(signed(offset), val);
+    public void writeObject(int offset, Object val, Object locationIdentity) {
+        writeObject(signed(offset), val, locationIdentity);
     }
 
     @Override
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Feb 13 17:35:43 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Tue Feb 26 16:35:23 2013 +0100
@@ -138,18 +138,13 @@
                         break;
 
                     case READ:
-                        assert arguments.size() == 2;
-                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.ANY_LOCATION));
-                        break;
-
-                    case READ_FINAL:
-                        assert arguments.size() == 2;
-                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.FINAL_LOCATION));
+                        assert arguments.size() == 3;
+                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, arguments.get(2).asConstant().asObject()));
                         break;
 
                     case WRITE:
-                        assert arguments.size() == 3;
-                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, LocationNode.ANY_LOCATION));
+                        assert arguments.size() == 4;
+                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, arguments.get(3).asConstant().asObject()));
                         break;
 
                     case ZERO: