changeset 7275:4f220c85044d

replaces node intrinsics for loadinf from a Word with methods directly in the Word class itself
author Doug Simon <doug.simon@oracle.com>
date Tue, 18 Dec 2012 22:23:46 +0100
parents 19f5c9b96fa7
children 0dbcda32b5e9
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.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/ClassSnippets.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/ObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.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/StructuredGraph.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java
diffstat 15 files changed, 98 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Tue Dec 18 22:23:46 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.phases;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.*;
 import com.oracle.graal.api.meta.*;
@@ -29,6 +31,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -89,7 +92,7 @@
         } while (true);
 
 
-        LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(Kind.Long)));
+        LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
         RuntimeCallNode migrationEnd = graph.add(new RuntimeCallNode(OSR_MIGRATION_END, buffer));
         FrameState osrState = osr.stateAfter();
         migrationEnd.setStateAfter(osrState);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Tue Dec 18 22:23:46 2012 +0100
@@ -99,7 +99,7 @@
             return object;
         }
         Word objectHub = loadHub(object);
-        if (loadWordFromWord(objectHub, superCheckOffset) != hub) {
+        if (objectHub.readWord(superCheckOffset) != hub) {
             displayMiss.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ClassCastException);
         }
@@ -157,12 +157,12 @@
     }
 
     static Word loadWordElement(Word metaspaceArray, int index) {
-        return loadWordFromWord(metaspaceArray, metaspaceArrayBaseOffset() + index * wordSize());
+        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize());
     }
 
     static boolean checkSecondarySubType(Word t, Word s) {
         // if (S.cache == T) return true
-        if (loadWordFromWord(s, secondarySuperCacheOffset()) == t) {
+        if (s.readWord(secondarySuperCacheOffset()) == t) {
             cacheHit.inc();
             return true;
         }
@@ -174,8 +174,8 @@
         }
 
         // if (S.scan_s_s_array(T)) { S.cache = T; return true; }
-        Word secondarySupers = loadWordFromWord(s, secondarySupersOffset());
-        int length = loadIntFromWord(secondarySupers, metaspaceArrayLengthOffset());
+        Word secondarySupers = s.readWord(secondarySupersOffset());
+        int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
         for (int i = 0; i < length; i++) {
             if (t == loadWordElement(secondarySupers, i)) {
                 DirectObjectStoreNode.storeWord(s, secondarySuperCacheOffset(), 0, t);
@@ -189,11 +189,11 @@
 
     static boolean checkUnknownSubType(Word t, Word s) {
         // int off = T.offset
-        int superCheckOffset = UnsafeLoadNode.load(t, 0, superCheckOffsetOffset(), Kind.Int);
+        int superCheckOffset = t.readInt(superCheckOffsetOffset());
         boolean primary = superCheckOffset != secondarySuperCacheOffset();
 
         // if (T = S[off]) return true
-        if (loadWordFromWord(s, superCheckOffset) == t) {
+        if (s.readWord(superCheckOffset) == t) {
             if (primary) {
                 cacheHit.inc();
             } else {
@@ -215,8 +215,8 @@
         }
 
         // if (S.scan_s_s_array(T)) { S.cache = T; return true; }
-        Word secondarySupers = loadWordFromWord(s, secondarySupersOffset());
-        int length = loadIntFromWord(secondarySupers, metaspaceArrayLengthOffset());
+        Word secondarySupers = s.readWord(secondarySupersOffset());
+        int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
         for (int i = 0; i < length; i++) {
             if (t == loadWordElement(secondarySupers, i)) {
                 DirectObjectStoreNode.storeWord(s, secondarySuperCacheOffset(), 0, t);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java	Tue Dec 18 22:23:46 2012 +0100
@@ -42,7 +42,7 @@
             // Class for primitive type
             return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
         } else {
-            return loadIntFromWord(klass, klassModifierFlagsOffset());
+            return klass.readInt(klassModifierFlagsOffset());
         }
     }
 
@@ -52,7 +52,7 @@
         if (klass == Word.zero()) {
             return false;
         } else {
-            int accessFlags = loadIntFromWord(klass, klassAccessFlagsOffset());
+            int accessFlags = klass.readInt(klassAccessFlagsOffset());
             return (accessFlags & Modifier.INTERFACE) != 0;
         }
     }
@@ -63,7 +63,7 @@
         if (klass == Word.zero()) {
             return false;
         } else {
-            int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+            int layoutHelper = klass.readInt(klassLayoutHelperOffset());
             return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0;
         }
     }
@@ -78,17 +78,17 @@
     public static Class<?> getSuperclass(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass != Word.zero()) {
-            int accessFlags = loadIntFromWord(klass, klassAccessFlagsOffset());
+            int accessFlags = klass.readInt(klassAccessFlagsOffset());
             if ((accessFlags & Modifier.INTERFACE) == 0) {
-                int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+                int layoutHelper = klass.readInt(klassLayoutHelperOffset());
                 if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
                     return Object.class;
                 } else {
-                    Word superKlass = loadWordFromWord(klass, klassSuperKlassOffset());
+                    Word superKlass = klass.readWord(klassSuperKlassOffset());
                     if (superKlass == Word.zero()) {
                         return null;
                     } else {
-                        return unsafeCast(loadObjectFromWord(superKlass, classMirrorOffset()), Class.class, true, true);
+                        return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true);
                     }
                 }
             }
@@ -100,9 +100,9 @@
     public static Class<?> getComponentType(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass != Word.zero()) {
-            int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+            int layoutHelper = klass.readInt(klassLayoutHelperOffset());
             if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
-                return unsafeCast(loadObjectFromWord(klass, arrayKlassComponentMirrorOffset()), Class.class, true, true);
+                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true);
             }
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Tue Dec 18 22:23:46 2012 +0100
@@ -285,36 +285,16 @@
         return HotSpotSnippetUtils.registerAsWord(threadRegister());
     }
 
-    public static int loadIntFromWord(Word address, int offset) {
-        Integer value = UnsafeLoadNode.load(address, 0, offset, Kind.Int);
-        return value;
-    }
-
-    public static Word loadWordFromWord(Word address, int offset) {
-        return loadWordFromWordIntrinsic(address, 0, offset, wordKind());
-    }
-
-    static Object loadObjectFromWord(Word address, int offset) {
-        return UnsafeLoadNode.load(address, 0, offset, Kind.Object);
-    }
-
     public static Word loadWordFromObject(Object object, int offset) {
         return loadWordFromObjectIntrinsic(object, 0, offset, wordKind());
     }
 
-    public static Object readFinalObject(Word base, @ConstantNodeParameter int displacement) {
-        return ReadNode.read(base, displacement, LocationNode.FINAL_LOCATION, Kind.Object);
-    }
-
     @NodeIntrinsic(value = RegisterNode.class, setStampFromReturnType = true)
     public static native Word registerAsWord(@ConstantNodeParameter Register register);
 
     @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
     private static native Word loadWordFromObjectIntrinsic(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind);
 
-    @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
-    private static native Word loadWordFromWordIntrinsic(Word address, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind);
-
     @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true)
     static native Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Tue Dec 18 22:23:46 2012 +0100
@@ -93,7 +93,7 @@
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (loadWordFromWord(objectHub, superCheckOffset) != hub) {
+        if (objectHub.readWord(superCheckOffset) != hub) {
             displayMiss.inc();
             return falseValue;
         }
@@ -134,7 +134,7 @@
 
     static boolean checkSecondarySubType(Word t, Word s) {
         // if (S.cache == T) return true
-        if (loadWordFromWord(s, secondarySuperCacheOffset()) == t) {
+        if (s.readWord(secondarySuperCacheOffset()) == t) {
             cacheHit.inc();
             return true;
         }
@@ -146,8 +146,8 @@
         }
 
         // if (S.scan_s_s_array(T)) { S.cache = T; return true; }
-        Word secondarySupers = loadWordFromWord(s, secondarySupersOffset());
-        int length = loadIntFromWord(secondarySupers, metaspaceArrayLengthOffset());
+        Word secondarySupers = s.readWord(secondarySupersOffset());
+        int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
         for (int i = 0; i < length; i++) {
             if (t == loadWordElement(secondarySupers, i)) {
                 DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Tue Dec 18 22:23:46 2012 +0100
@@ -107,7 +107,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 = loadWordFromWord(hub, prototypeMarkWordOffset());
+                final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
                 final Word thread = thread();
                 final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace());
                 trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord.toLong());
@@ -293,7 +293,7 @@
         final Word lock = CurrentLockNode.currentLock();
 
         // Load displaced mark
-        final Word displacedMark = loadWordFromWord(lock, lockDisplacedMarkOffset());
+        final Word displacedMark = lock.readWord(lockDisplacedMarkOffset());
         trace(trace, "    displacedMark: 0x%016lx\n", displacedMark.toLong());
 
         if (displacedMark == Word.zero()) {
@@ -360,7 +360,7 @@
     private static void incCounter() {
         if (CHECK_BALANCED_MONITORS) {
             final Word counter = MonitorCounterNode.counter();
-            final int count = UnsafeLoadNode.load(counter, 0, 0, Kind.Int);
+            final int count = counter.readInt(0);
             DirectObjectStoreNode.storeInt(counter, 0, 0, count + 1);
         }
     }
@@ -368,7 +368,7 @@
     private static void decCounter() {
         if (CHECK_BALANCED_MONITORS) {
             final Word counter = MonitorCounterNode.counter();
-            final int count = UnsafeLoadNode.load(counter, 0, 0, Kind.Int);
+            final int count = counter.readInt(0);
             DirectObjectStoreNode.storeInt(counter, 0, 0, count - 1);
         }
     }
@@ -382,7 +382,7 @@
     @Snippet
     private static void checkCounter(String errMsg) {
         final Word counter = MonitorCounterNode.counter();
-        final int count = UnsafeLoadNode.load(counter, 0, 0, Kind.Int);
+        final int count = counter.readInt(0);
         if (count != 0) {
             vmError(errMsg, count);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Tue Dec 18 22:23:46 2012 +0100
@@ -59,8 +59,8 @@
     @Snippet
     public static Word allocate(@Parameter("size") int size) {
         Word thread = thread();
-        Word top = loadWordFromWord(thread, threadTlabTopOffset());
-        Word end = loadWordFromWord(thread, threadTlabEndOffset());
+        Word top = thread.readWord(threadTlabTopOffset());
+        Word end = thread.readWord(threadTlabEndOffset());
         Word newTop = top.plus(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)) {
@@ -187,7 +187,7 @@
      * 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() ? loadWordFromWord(hub, prototypeMarkWordOffset()) : compileTimePrototypeMarkWord;
+        Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset()) : compileTimePrototypeMarkWord;
         storeWord(memory, 0, markOffset(), prototypeMarkWord);
         storeWord(memory, 0, hubOffset(), hub);
         if (fillContents) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java	Tue Dec 18 22:23:46 2012 +0100
@@ -37,7 +37,7 @@
     @MethodSubstitution(isStatic = false)
     public static Class<?> getClass(final Object thisObj) {
         Word hub = loadHub(thisObj);
-        return unsafeCast(readFinalObject(hub, classMirrorOffset()), Class.class, true, true);
+        return unsafeCast(hub.readFinalObject(classMirrorOffset()), Class.class, true, true);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java	Tue Dec 18 22:23:46 2012 +0100
@@ -40,10 +40,10 @@
     @MethodSubstitution(isStatic = false)
     private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
         Word rawThread = HotSpotCurrentRawThreadNode.get();
-        Thread thread = (Thread) loadObjectFromWord(rawThread, threadObjectOffset());
+        Thread thread = (Thread) rawThread.readObject(threadObjectOffset());
         if (thisObject == thread) {
-            Word osThread = loadWordFromWord(rawThread, osThreadOffset());
-            boolean interrupted = loadIntFromWord(osThread, osThreadInterruptedOffset()) != 0;
+            Word osThread = rawThread.readWord(osThreadOffset());
+            boolean interrupted = osThread.readInt(osThreadInterruptedOffset()) != 0;
             if (!interrupted || !clearInterrupted) {
                 return interrupted;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Tue Dec 18 22:23:46 2012 +0100
@@ -70,7 +70,7 @@
                     @Parameter("length") int length,
                     @ConstantParameter("intArrayHub") Word intArrayHub,
                     @ConstantParameter("log") boolean log) {
-        int layoutHelper = loadIntFromWord(hub, layoutHelperOffset());
+        int layoutHelper = hub.readInt(layoutHelperOffset());
         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	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Tue Dec 18 22:23:46 2012 +0100
@@ -68,12 +68,12 @@
                     @Parameter("hub") Word hub,
                     @ConstantParameter("intArrayHub") Word intArrayHub,
                     @ConstantParameter("log") boolean log) {
-        int sizeInBytes = loadIntFromWord(hub, klassInstanceSizeOffset());
+        int sizeInBytes = hub.readInt(klassInstanceSizeOffset());
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
-            if (loadIntFromWord(hub, klassStateOffset()) == klassStateFullyInitialized()) {
+            if (hub.readInt(klassStateOffset()) == klassStateFullyInitialized()) {
                 Word memory = refillAllocate(intArrayHub, sizeInBytes, log);
                 if (memory != Word.zero()) {
-                    Word prototypeMarkWord = loadWordFromWord(hub, prototypeMarkWordOffset());
+                    Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
                     storeWord(memory, 0, markOffset(), prototypeMarkWord);
                     storeWord(memory, 0, hubOffset(), hub);
                     for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) {
@@ -100,8 +100,8 @@
         int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords() * wordSize();
 
         Word thread = thread();
-        Word top = loadWordFromWord(thread, threadTlabTopOffset());
-        Word end = loadWordFromWord(thread, threadTlabEndOffset());
+        Word top = thread.readWord(threadTlabTopOffset());
+        Word end = thread.readWord(threadTlabEndOffset());
 
         // calculate amount of free space
         Word tlabFreeSpaceInBytes = end.minus(top);
@@ -116,14 +116,14 @@
 
         // Retain TLAB and allocate object in shared space if
         // the amount free in the TLAB is too large to discard.
-        Word refillWasteLimit = loadWordFromWord(thread, tlabRefillWasteLimitOffset());
+        Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset());
         if (tlabFreeSpaceInWords.belowOrEqual(refillWasteLimit)) {
             if (tlabStats()) {
                 // increment number of refills
-                storeInt(thread, 0, tlabNumberOfRefillsOffset(), loadIntFromWord(thread, tlabNumberOfRefillsOffset()) + 1);
-                log(log, "thread: %p -- number_of_refills %d\n", thread.toLong(), loadIntFromWord(thread, tlabNumberOfRefillsOffset()));
+                storeInt(thread, 0, tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1);
+                log(log, "thread: %p -- number_of_refills %d\n", thread.toLong(), thread.readInt(tlabNumberOfRefillsOffset()));
                 // accumulate wastage
-                Word wastage = loadWordFromWord(thread, tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords);
+                Word wastage = thread.readWord(tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords);
                 log(log, "thread: %p -- accumulated wastage %d\n", thread.toLong(), wastage.toLong());
                 storeWord(thread, 0, tlabFastRefillWasteOffset(), wastage);
             }
@@ -137,13 +137,13 @@
                 int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts;
                 NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false);
 
-                Word allocated = loadWordFromWord(thread, threadAllocatedBytesOffset());
-                allocated = allocated.plus(top.minus(loadWordFromWord(thread, threadTlabStartOffset())));
+                Word allocated = thread.readWord(threadAllocatedBytesOffset());
+                allocated = allocated.plus(top.minus(thread.readWord(threadTlabStartOffset())));
                 storeWord(thread, 0, threadAllocatedBytesOffset(), allocated);
             }
 
             // refill the TLAB with an eden allocation
-            Word tlabRefillSizeInWords = loadWordFromWord(thread, threadTlabSizeOffset());
+            Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset());
             Word tlabRefillSizeInBytes = Word.fromLong(tlabRefillSizeInWords.toLong() * wordSize());
             // allocate new TLAB, address returned in top
             top = edenAllocate(tlabRefillSizeInBytes, log);
@@ -165,7 +165,7 @@
             log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.toLong());
 
             if (tlabStats()) {
-                storeInt(thread, 0, tlabSlowAllocationsOffset(), loadIntFromWord(thread, tlabSlowAllocationsOffset()) + 1);
+                storeInt(thread, 0, tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1);
             }
 
             return edenAllocate(Word.fromInt(sizeInBytes), log);
@@ -184,13 +184,13 @@
         Word heapEndAddress = Word.fromLong(heapEndAddress());
 
         while (true) {
-            Word heapTop = loadWordFromWord(heapTopAddress, 0);
+            Word heapTop = heapTopAddress.readWord(0);
             Word newHeapTop = heapTop.plus(sizeInBytes);
             if (newHeapTop.belowOrEqual(heapTop)) {
                 return Word.zero();
             }
 
-            Word heapEnd = loadWordFromWord(heapEndAddress, 0);
+            Word heapEnd = heapEndAddress.readWord(0);
             if (newHeapTop.above(heapEnd)) {
                 return Word.zero();
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Dec 18 22:23:46 2012 +0100
@@ -311,7 +311,7 @@
     public void addBeforeFixed(FixedNode node, FixedWithNextNode newNode) {
         assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " before " + node;
         assert node.predecessor() != null && node.predecessor() instanceof FixedWithNextNode : "cannot add " + newNode + " before " + node;
-        assert newNode.next() == null;
+        assert newNode.next() == null : newNode;
         newNode.setProbability(node.probability());
         FixedWithNextNode pred = (FixedWithNextNode) node.predecessor();
         pred.setNext(newNode);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Dec 18 22:23:46 2012 +0100
@@ -99,7 +99,4 @@
 
     @NodeIntrinsic
     public static native <T> T load(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind kind);
-
-    @NodeIntrinsic
-    public static native Object loadObject(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter boolean nonNull);
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java	Tue Dec 18 22:23:46 2012 +0100
@@ -58,6 +58,10 @@
         OR,
         AND,
         XOR,
+        READ_INT,
+        READ_WORD,
+        READ_OBJECT,
+        READ_FINAL_OBJECT,
         BELOW,
         BELOW_EQUAL,
         ABOVE,
@@ -237,4 +241,20 @@
         return new Word(value | other.value, null);
     }
 
+    @Operation(READ_INT)
+    public native int readInt(int offset);
+
+    @Operation(READ_WORD)
+    public native Word readWord(int offset);
+
+    @Operation(READ_OBJECT)
+    public native Object readObject(int offset);
+
+    /**
+     * Reads an object value from a location that is guaranteed not be to modified after this read.
+     *
+     * @param offset the offset from this base address of the location to be read
+     */
+    @Operation(READ_FINAL_OBJECT)
+    public native Object readFinalObject(int offset);
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Tue Dec 18 17:59:32 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Tue Dec 18 22:23:46 2012 +0100
@@ -212,6 +212,18 @@
                         break;
                     }
 
+                    case READ_INT:
+                    case READ_OBJECT:
+                    case READ_WORD: {
+                        replaceRead(graph, arguments, invoke, LocationNode.ANY_LOCATION);
+                        break;
+                    }
+
+                    case READ_FINAL_OBJECT: {
+                        replaceRead(graph, arguments, invoke, LocationNode.FINAL_LOCATION);
+                        break;
+                    }
+
                     default: {
                         throw new GraalInternalError("Unknown opcode: %s", opcode);
                     }
@@ -220,6 +232,17 @@
         }
     }
 
+    protected void replaceRead(StructuredGraph graph, NodeInputList<ValueNode> arguments, Invoke invoke, Object locationIdentity) {
+        assert arguments.size() == 2;
+        ValueNode base = arguments.first();
+        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, invoke.node().kind(), 0, arguments.last(), graph, false);
+        ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp()));
+        graph.addBeforeFixed(invoke.node(), read);
+        // The read must not float outside its block otherwise it may float above an explicit zero check on its base address
+        read.dependencies().add(BeginNode.prevBegin(invoke.node()));
+        replace(invoke, read);
+    }
+
     protected void replace(Invoke invoke, ValueNode value) {
         FixedNode next = invoke.next();
         invoke.setNext(null);