changeset 21783:a858c5f56d8a

Introduce AddressNode to represent pointer arithmetic, remove LocationNode.
author Roland Schatz <roland.schatz@oracle.com>
date Mon, 08 Jun 2015 18:47:58 +0200
parents 9c454c650b29
children f4e1d958f1c3
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/RawPointerStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/MetaspacePointer.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/AbstractWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/Access.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FixedAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatableAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatingAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatingReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/address/AddressNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/address/OffsetAddressNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/address/RawAddressNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringProvider.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/AddressLoweringPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PEGraphDecoderTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/NativeCallStubGraphBuilder.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java graal/com.oracle.graal.word/src/com/oracle/graal/word/BarrieredAccess.java graal/com.oracle.graal.word/src/com/oracle/graal/word/ObjectAccess.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/nodes/SnippetLocationNode.java graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java
diffstat 76 files changed, 1203 insertions(+), 1446 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/RawPointerStamp.java	Mon Jun 08 18:47:58 2015 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.common.type;
+
+import com.oracle.graal.compiler.common.spi.*;
+import com.oracle.jvmci.common.*;
+import com.oracle.jvmci.meta.*;
+
+/**
+ * Type describing pointers to raw memory. This stamp is used for example for direct pointers to
+ * fields or array elements.
+ */
+public class RawPointerStamp extends AbstractPointerStamp {
+
+    protected RawPointerStamp() {
+        super(false, false);
+    }
+
+    @Override
+    public LIRKind getLIRKind(LIRKindTool tool) {
+        return tool.getWordKind();
+    }
+
+    @Override
+    protected AbstractPointerStamp copyWith(boolean newNonNull, boolean newAlwaysNull) {
+        // RawPointerStamp is a singleton
+        assert newNonNull == nonNull() && newAlwaysNull == alwaysNull();
+        return this;
+    }
+
+    @Override
+    public Stamp meet(Stamp other) {
+        assert isCompatible(other);
+        return this;
+    }
+
+    @Override
+    public Stamp improveWith(Stamp other) {
+        return this;
+    }
+
+    @Override
+    public Stamp join(Stamp other) {
+        assert isCompatible(other);
+        return this;
+    }
+
+    @Override
+    public Stamp unrestricted() {
+        return this;
+    }
+
+    @Override
+    public Stamp empty() {
+        // there is no empty pointer stamp
+        return this;
+    }
+
+    @Override
+    public boolean hasValues() {
+        return true;
+    }
+
+    @Override
+    public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
+        throw JVMCIError.shouldNotReachHere("pointer has no Java type");
+    }
+
+    @Override
+    public Stamp constant(Constant c, MetaAccessProvider meta) {
+        return this;
+    }
+
+    @Override
+    public boolean isCompatible(Stamp other) {
+        return other instanceof RawPointerStamp;
+    }
+
+    @Override
+    public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) {
+        throw JVMCIError.shouldNotReachHere("can't read raw pointer");
+    }
+
+    @Override
+    public String toString() {
+        return "void*";
+    }
+}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java	Mon Jun 08 18:47:58 2015 +0200
@@ -45,6 +45,7 @@
     private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
     private static final Stamp booleanTrue = forInteger(Kind.Boolean, -1, -1, 1, 1);
     private static final Stamp booleanFalse = forInteger(Kind.Boolean, 0, 0, 0, 0);
+    private static final Stamp rawPointer = new RawPointerStamp();
 
     private static void setCache(Kind kind, Stamp stamp) {
         stampCache[kind.ordinal()] = stamp;
@@ -350,4 +351,8 @@
 
         return result;
     }
+
+    public static Stamp pointer() {
+        return rawPointer;
+    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,22 +22,20 @@
  */
 package com.oracle.graal.compiler.test;
 
-import com.oracle.jvmci.meta.ResolvedJavaType;
-import com.oracle.jvmci.meta.ResolvedJavaField;
 import org.junit.*;
 
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.jvmci.debug.*;
 import com.oracle.jvmci.debug.Debug.Scope;
+import com.oracle.jvmci.meta.*;
 
 public class PushNodesThroughPiTest extends GraalCompilerTest {
 
@@ -72,17 +70,17 @@
         try (Scope s = Debug.scope("PushThroughPi", new DebugDumpScope(snippet))) {
             StructuredGraph graph = compileTestSnippet(snippet);
             for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) {
-                if (rn.location() instanceof ConstantLocationNode && rn.object().stamp() instanceof ObjectStamp) {
-                    long disp = ((ConstantLocationNode) rn.location()).getDisplacement();
-                    ResolvedJavaType receiverType = StampTool.typeOrNull(rn.object());
-                    ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp, rn.getKind());
+                OffsetAddressNode address = (OffsetAddressNode) rn.getAddress();
+                long disp = address.getOffset().asJavaConstant().asLong();
+
+                ResolvedJavaType receiverType = StampTool.typeOrNull(address.getBase());
+                ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp, rn.getKind());
 
-                    assert field != null : "Node " + rn + " tries to access a field which doesn't exists for this type";
-                    if (field.getName().equals("x")) {
-                        Assert.assertTrue(rn.object() instanceof ParameterNode);
-                    } else {
-                        Assert.assertTrue(rn.object().toString(), rn.object() instanceof PiNode);
-                    }
+                assert field != null : "Node " + rn + " tries to access a field which doesn't exists for this type";
+                if (field.getName().equals("x")) {
+                    Assert.assertTrue(address.getBase() instanceof ParameterNode);
+                } else {
+                    Assert.assertTrue(address.getBase().toString(), address.getBase() instanceof PiNode);
                 }
             }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Jun 08 18:47:58 2015 +0200
@@ -94,7 +94,7 @@
             for (FloatingReadNode node : graph.getNodes(ParameterNode.TYPE).first().usages().filter(FloatingReadNode.class)) {
                 // Checking that the parameter a is not directly used for the access to field
                 // x10 (because x10 must be guarded by the checkcast).
-                Assert.assertTrue(node.location().getLocationIdentity().isImmutable());
+                Assert.assertTrue(node.getLocationIdentity().isImmutable());
             }
         } catch (Throwable e) {
             throw Debug.handle(e);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Jun 08 18:47:58 2015 +0200
@@ -68,16 +68,16 @@
  */
 @MatchableNode(nodeClass = ConstantNode.class, shareable = true)
 @MatchableNode(nodeClass = FloatConvertNode.class, inputs = {"value"})
-@MatchableNode(nodeClass = FloatingReadNode.class, inputs = {"object", "location"})
+@MatchableNode(nodeClass = FloatingReadNode.class, inputs = {"address"})
 @MatchableNode(nodeClass = IfNode.class, inputs = {"condition"})
 @MatchableNode(nodeClass = SubNode.class, inputs = {"x", "y"})
 @MatchableNode(nodeClass = LeftShiftNode.class, inputs = {"x", "y"})
 @MatchableNode(nodeClass = NarrowNode.class, inputs = {"value"})
-@MatchableNode(nodeClass = ReadNode.class, inputs = {"object", "location"})
+@MatchableNode(nodeClass = ReadNode.class, inputs = {"address"})
 @MatchableNode(nodeClass = ReinterpretNode.class, inputs = {"value"})
 @MatchableNode(nodeClass = SignExtendNode.class, inputs = {"value"})
 @MatchableNode(nodeClass = UnsignedRightShiftNode.class, inputs = {"x", "y"})
-@MatchableNode(nodeClass = WriteNode.class, inputs = {"object", "location", "value"})
+@MatchableNode(nodeClass = WriteNode.class, inputs = {"address", "value"})
 @MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"value"})
 @MatchableNode(nodeClass = AndNode.class, inputs = {"x", "y"}, commutative = true)
 @MatchableNode(nodeClass = FloatEqualsNode.class, inputs = {"x", "y"}, commutative = true)
@@ -92,7 +92,6 @@
 @MatchableNode(nodeClass = OrNode.class, inputs = {"x", "y"}, commutative = true)
 @MatchableNode(nodeClass = XorNode.class, inputs = {"x", "y"}, commutative = true)
 @MatchableNode(nodeClass = PiNode.class, inputs = {"object"})
-@MatchableNode(nodeClass = ConstantLocationNode.class, shareable = true)
 public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGenerationDebugContext {
 
     private final NodeMap<Value> nodeOperands;
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.test;
 
-import com.oracle.jvmci.meta.ResolvedJavaMethod;
 import static com.oracle.jvmci.common.UnsafeAccess.*;
 
 import java.lang.ref.*;
@@ -38,9 +37,9 @@
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -50,6 +49,7 @@
 import com.oracle.jvmci.debug.*;
 import com.oracle.jvmci.debug.Debug.Scope;
 import com.oracle.jvmci.hotspot.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * The following unit tests assert the presence of write barriers for both Serial and G1 GCs.
@@ -284,9 +284,10 @@
 
             for (ReadNode read : graph.getNodes().filter(ReadNode.class)) {
                 if (read.getBarrierType() != BarrierType.NONE) {
-                    if (read.location() instanceof ConstantLocationNode) {
-                        Assert.assertEquals(referentOffset, ((ConstantLocationNode) (read.location())).getDisplacement());
-                    }
+                    Assert.assertTrue(read.getAddress() instanceof OffsetAddressNode);
+                    JavaConstant constDisp = ((OffsetAddressNode) read.getAddress()).getOffset().asJavaConstant();
+                    Assert.assertNotNull(constDisp);
+                    Assert.assertEquals(referentOffset, constDisp.asLong());
                     Assert.assertTrue(config.useG1GC);
                     Assert.assertEquals(BarrierType.PRECISE, read.getBarrierType());
                     Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -147,4 +147,6 @@
     Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull);
 
     Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull);
+
+    void emitPrefetchAllocate(Value address);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java	Mon Jun 08 18:47:58 2015 +0200
@@ -43,8 +43,6 @@
 
     void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc);
 
-    void emitPrefetchAllocate(ValueNode address, ValueNode distance);
-
     void visitDirectCompareAndSwap(DirectCompareAndSwapNode x);
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,23 +22,11 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import com.oracle.jvmci.code.ForeignCallsProvider;
-import com.oracle.jvmci.code.CallingConvention;
-import com.oracle.jvmci.code.TargetDescription;
-import com.oracle.jvmci.meta.ResolvedJavaField;
-import com.oracle.jvmci.meta.JavaType;
-import com.oracle.jvmci.meta.MetaAccessProvider;
-import com.oracle.jvmci.meta.JavaConstant;
-import com.oracle.jvmci.meta.LocationIdentity;
-import com.oracle.jvmci.meta.ResolvedJavaType;
-import com.oracle.jvmci.meta.ForeignCallDescriptor;
-import com.oracle.jvmci.meta.Kind;
-
-import static com.oracle.jvmci.meta.LocationIdentity.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
+import static com.oracle.jvmci.meta.LocationIdentity.*;
 
 import java.lang.ref.*;
 
@@ -56,12 +44,15 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
+import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.common.*;
 import com.oracle.jvmci.hotspot.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * HotSpot implementation of {@link LoweringProvider}.
@@ -212,9 +203,9 @@
             return;
         }
         StructuredGraph graph = n.graph();
-        LocationNode location = graph.unique(new ConstantLocationNode(KLASS_LAYOUT_HELPER_LOCATION, runtime.getConfig().klassLayoutHelperOffset));
         assert !n.getHub().isConstant();
-        graph.replaceFloating(n, graph.unique(new FloatingReadNode(n.getHub(), location, null, n.stamp(), n.getGuard(), BarrierType.NONE)));
+        AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getConfig().klassLayoutHelperOffset);
+        graph.replaceFloating(n, graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)));
     }
 
     private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) {
@@ -223,9 +214,9 @@
         }
 
         StructuredGraph graph = n.graph();
-        LocationNode location = graph.unique(new ConstantLocationNode(CLASS_MIRROR_LOCATION, runtime.getConfig().classMirrorOffset));
         assert !n.getHub().isConstant();
-        FloatingReadNode read = graph.unique(new FloatingReadNode(n.getHub(), location, null, n.stamp(), n.getGuard(), BarrierType.NONE));
+        AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getConfig().classMirrorOffset);
+        FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE));
         graph.replaceFloating(n, read);
     }
 
@@ -235,9 +226,9 @@
         }
 
         StructuredGraph graph = n.graph();
-        LocationNode location = graph.unique(new ConstantLocationNode(CLASS_KLASS_LOCATION, runtime.getConfig().klassOffset));
         assert !n.getValue().isConstant();
-        FloatingReadNode read = graph.unique(new FloatingReadNode(n.getValue(), location, null, n.stamp(), n.getGuard(), BarrierType.NONE));
+        AddressNode address = createOffsetAddress(graph, n.getValue(), runtime.getConfig().klassOffset);
+        FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE));
         graph.replaceFloating(n, read);
     }
 
@@ -266,8 +257,8 @@
                     // compiled code entry as HotSpot does not guarantee they are final
                     // values.
                     int methodCompiledEntryOffset = runtime.getConfig().methodCompiledEntryOffset;
-                    ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, graph.unique(new ConstantLocationNode(any(), methodCompiledEntryOffset)), StampFactory.forKind(wordKind),
-                                    BarrierType.NONE));
+                    AddressNode address = createOffsetAddress(graph, metaspaceMethod, methodCompiledEntryOffset);
+                    ReadNode compiledEntry = graph.add(new ReadNode(address, any(), StampFactory.forKind(wordKind), BarrierType.NONE));
 
                     loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
                                     CallingConvention.Type.JavaCall, callTarget.invokeKind()));
@@ -318,12 +309,12 @@
 
     @Override
     protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor) {
-        LocationNode location = graph.unique(new ConstantLocationNode(OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION, runtime.getConfig().arrayClassElementOffset));
         /*
          * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass
          * is an object class, which might not be the case in other parts of the compiled method.
          */
-        return graph.unique(new FloatingReadNode(arrayHub, location, null, KlassPointerStamp.klassNonNull(), AbstractBeginNode.prevBegin(anchor)));
+        AddressNode address = createOffsetAddress(graph, arrayHub, runtime.getConfig().arrayClassElementOffset);
+        return graph.unique(new FloatingReadNode(address, OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION, null, KlassPointerStamp.klassNonNull(), AbstractBeginNode.prevBegin(anchor)));
     }
 
     @Override
@@ -386,8 +377,8 @@
             for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.TYPE)) {
                 int size = osrLocal.getKind().getSlotCount();
                 int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
-                IndexedLocationNode location = graph.unique(new IndexedLocationNode(any(), offset, ConstantNode.forLong(0, graph), 1));
-                ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE));
+                AddressNode address = createOffsetAddress(graph, buffer, offset);
+                ReadNode load = graph.add(new ReadNode(address, any(), osrLocal.stamp(), BarrierType.NONE));
                 osrLocal.replaceAndDelete(load);
                 graph.addBeforeFixed(migrationEnd, load);
             }
@@ -464,14 +455,14 @@
         // We use LocationNode.ANY_LOCATION for the reads that access the vtable
         // entry as HotSpot does not guarantee that this is a final value.
         Stamp methodStamp = MethodPointerStamp.method();
-        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, graph.unique(new ConstantLocationNode(any(), vtableEntryOffset)), methodStamp, BarrierType.NONE));
+        AddressNode address = createOffsetAddress(graph, hub, vtableEntryOffset);
+        ReadNode metaspaceMethod = graph.add(new ReadNode(address, any(), methodStamp, BarrierType.NONE));
         return metaspaceMethod;
     }
 
     @Override
     protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard) {
         HotSpotVMConfig config = runtime.getConfig();
-        LocationNode location = graph.unique(new ConstantLocationNode(HUB_LOCATION, config.hubOffset));
         assert !object.isConstant() || object.isNullConstant();
 
         KlassPointerStamp hubStamp = KlassPointerStamp.klassNonNull();
@@ -479,7 +470,8 @@
             hubStamp = hubStamp.compressed(config.getKlassEncoding());
         }
 
-        FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(object, location, null, hubStamp, guard, BarrierType.NONE));
+        AddressNode address = createOffsetAddress(graph, object, config.hubOffset);
+        FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, HUB_LOCATION, null, hubStamp, guard, BarrierType.NONE));
         if (config.useCompressedClassPointers) {
             return CompressionNode.uncompress(memoryRead, config.getKlassEncoding());
         } else {
@@ -489,7 +481,6 @@
 
     private WriteNode createWriteHub(StructuredGraph graph, ValueNode object, ValueNode value) {
         HotSpotVMConfig config = runtime.getConfig();
-        LocationNode location = graph.unique(new ConstantLocationNode(HUB_WRITE_LOCATION, config.hubOffset));
         assert !object.isConstant() || object.asConstant().isDefaultForKind();
 
         ValueNode writeValue = value;
@@ -497,7 +488,8 @@
             writeValue = CompressionNode.compress(value, config.getKlassEncoding());
         }
 
-        return graph.add(new WriteNode(object, writeValue, location, BarrierType.NONE));
+        AddressNode address = createOffsetAddress(graph, object, config.hubOffset);
+        return graph.add(new WriteNode(address, HUB_WRITE_LOCATION, writeValue, BarrierType.NONE));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,13 +22,6 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import com.oracle.jvmci.code.ForeignCallsProvider;
-import com.oracle.jvmci.meta.MetaAccessProvider;
-import com.oracle.jvmci.meta.JavaConstant;
-import com.oracle.jvmci.meta.ConstantReflectionProvider;
-import com.oracle.jvmci.meta.ResolvedJavaMethod;
-import com.oracle.jvmci.meta.Kind;
-
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
 import static com.oracle.graal.java.BytecodeParser.Options.*;
@@ -48,13 +41,15 @@
 import com.oracle.graal.hotspot.replacements.arraycopy.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
+import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.hotspot.*;
+import com.oracle.jvmci.meta.*;
 import com.oracle.jvmci.options.*;
 
 /**
@@ -214,9 +209,10 @@
         r.register0("currentThread", new InvocationPlugin() {
             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
                 CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(wordTypes.getWordKind()));
-                ConstantLocationNode location = b.add(new ConstantLocationNode(JAVA_THREAD_THREAD_OBJECT_LOCATION, config.threadObjectOffset));
                 boolean compressible = false;
-                ValueNode javaThread = WordOperationPlugin.readOp(b, Kind.Object, thread, location, BarrierType.NONE, compressible);
+                ValueNode offset = b.add(ConstantNode.forLong(config.threadObjectOffset));
+                AddressNode address = b.add(new OffsetAddressNode(thread, offset));
+                ValueNode javaThread = WordOperationPlugin.readOp(b, Kind.Object, address, JAVA_THREAD_THREAD_OBJECT_LOCATION, BarrierType.NONE, compressible);
                 boolean exactType = compressible;
                 boolean nonNull = true;
                 b.addPush(Kind.Object, new PiNode(javaThread, metaAccess.lookupJavaType(Thread.class), exactType, nonNull));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,13 +22,12 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import com.oracle.jvmci.meta.Kind;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.hotspot.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * HotSpot implementation of {@link LoweringProvider}.
@@ -39,7 +38,7 @@
 
     int arrayScalingFactor(Kind kind);
 
-    IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization);
+    AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, Kind elementKind, ValueNode index);
 
     Stamp loadStamp(Stamp stamp, Kind kind);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java	Mon Jun 08 18:47:58 2015 +0200
@@ -35,10 +35,10 @@
 import com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
@@ -126,13 +126,15 @@
             case READ_KLASS_POINTER:
                 assert args.length == 2 || args.length == 3;
                 Stamp readStamp = KlassPointerStamp.klass();
-                LocationNode location;
+                AddressNode address = makeAddress(b, args[0], args[1]);
+                LocationIdentity location;
                 if (args.length == 2) {
-                    location = makeLocation(b, args[1], any());
+                    location = any();
                 } else {
-                    location = makeLocation(b, args[1], args[2]);
+                    assert args[2].isConstant();
+                    location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant());
                 }
-                ReadNode read = b.add(new ReadNode(args[0], location, readStamp, BarrierType.NONE));
+                ReadNode read = b.add(new ReadNode(address, location, readStamp, BarrierType.NONE));
                 /*
                  * The read must not float outside its block otherwise it may float above an
                  * explicit zero check on its base address.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,23 +22,31 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public abstract class ArrayRangeWriteBarrier extends WriteBarrier {
+public abstract class ArrayRangeWriteBarrier extends FixedWithNextNode implements Lowerable {
 
     public static final NodeClass<ArrayRangeWriteBarrier> TYPE = NodeClass.create(ArrayRangeWriteBarrier.class);
+    @Input ValueNode object;
     @Input ValueNode startIndex;
     @Input ValueNode length;
 
     protected ArrayRangeWriteBarrier(NodeClass<? extends ArrayRangeWriteBarrier> c, ValueNode object, ValueNode startIndex, ValueNode length) {
-        super(c, object, null, null, true);
+        super(c, StampFactory.forVoid());
+        this.object = object;
         this.startIndex = startIndex;
         this.length = length;
     }
 
+    public ValueNode getObject() {
+        return object;
+    }
+
     public ValueNode getStartIndex() {
         return startIndex;
     }
@@ -46,4 +54,10 @@
     public ValueNode getLength() {
         return length;
     }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        assert graph().getGuardsStage().areFrameStatesAtDeopts();
+        tool.getLowerer().lower(this, tool);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -29,41 +29,36 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.graal.nodes.memory.address.AddressNode.Address;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
  * 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, LocationIdentity)} returns either the
- * expected value or the compared against value instead of a boolean.
+ * {@link StateSplit} and it {@linkplain #compareAndSwap(Address, Word, Word, LocationIdentity)}
+ * returns either the expected value or the compared against value instead of a boolean.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public final class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single {
 
     public static final NodeClass<DirectCompareAndSwapNode> TYPE = NodeClass.create(DirectCompareAndSwapNode.class);
-    @Input ValueNode object;
-    @Input ValueNode offset;
+    @Input(InputType.Association) AddressNode address;
     @Input ValueNode expectedValue;
     @Input ValueNode newValue;
 
     protected final LocationIdentity locationIdentity;
 
-    public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) {
+    public DirectCompareAndSwapNode(ValueNode address, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) {
         super(TYPE, expected.stamp());
-        this.object = object;
-        this.offset = offset;
+        this.address = (AddressNode) address;
         this.expectedValue = expected;
         this.newValue = newValue;
         this.locationIdentity = locationIdentity;
     }
 
-    public ValueNode object() {
-        return object;
-    }
-
-    public ValueNode offset() {
-        return offset;
+    public AddressNode getAddress() {
+        return address;
     }
 
     public ValueNode expectedValue() {
@@ -85,17 +80,16 @@
     }
 
     /**
-     * Compares an expected value with the actual value in a location denoted by an object and a
-     * given offset. Iff they are same, {@code newValue} is placed into the location and the
-     * {@code expectedValue} is returned. Otherwise, the actual value is returned. All of the above
-     * is performed in one atomic hardware transaction.
+     * Compares an expected value with the actual value in a location denoted by an address. Iff
+     * they are same, {@code newValue} is placed into the location and the {@code expectedValue} is
+     * returned. Otherwise, the actual value is returned. All of the above is performed in one
+     * atomic hardware transaction.
      *
-     * @param object the object containing a field to be atomically tested and updated
-     * @param offset offset from {@code object} of the field
+     * @param address the address to be atomically tested and updated
      * @param expectedValue if this value is currently in the field, perform the swap
      * @param newValue the new value to put into the field
      * @return either {@code expectedValue} or the actual value
      */
     @NodeIntrinsic
-    public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue, @ConstantNodeParameter LocationIdentity locationIdentity);
+    public static native Word compareAndSwap(Address address, Word expectedValue, Word newValue, @ConstantNodeParameter LocationIdentity locationIdentity);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 
 @NodeInfo
 public class G1PostWriteBarrier extends WriteBarrier {
@@ -33,12 +33,12 @@
     public static final NodeClass<G1PostWriteBarrier> TYPE = NodeClass.create(G1PostWriteBarrier.class);
     protected final boolean alwaysNull;
 
-    public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) {
-        this(TYPE, object, value, location, precise, alwaysNull);
+    public G1PostWriteBarrier(AddressNode address, ValueNode value, boolean precise, boolean alwaysNull) {
+        this(TYPE, address, value, precise, alwaysNull);
     }
 
-    protected G1PostWriteBarrier(NodeClass<? extends G1PostWriteBarrier> c, ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) {
-        super(c, object, value, location, precise);
+    protected G1PostWriteBarrier(NodeClass<? extends G1PostWriteBarrier> c, AddressNode address, ValueNode value, boolean precise, boolean alwaysNull) {
+        super(c, address, value, precise);
         this.alwaysNull = alwaysNull;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 
 @NodeInfo
 public final class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore {
@@ -36,8 +36,8 @@
     protected final boolean nullCheck;
     protected final boolean doLoad;
 
-    public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) {
-        super(TYPE, object, expectedObject, location, true);
+    public G1PreWriteBarrier(AddressNode address, ValueNode expectedObject, boolean doLoad, boolean nullCheck) {
+        super(TYPE, address, expectedObject, true);
         this.doLoad = doLoad;
         this.nullCheck = nullCheck;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 
 /**
  * The {@code G1ReferentFieldReadBarrier} is added when a read access is performed to the referent
@@ -39,8 +39,8 @@
 
     protected final boolean doLoad;
 
-    public G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) {
-        super(TYPE, object, expectedObject, location, true);
+    public G1ReferentFieldReadBarrier(AddressNode address, ValueNode expectedObject, boolean doLoad) {
+        super(TYPE, address, expectedObject, true);
         this.doLoad = doLoad;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -28,27 +28,26 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.graal.nodes.memory.address.AddressNode.Address;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.word.*;
 
 @NodeInfo
 public final class PrefetchAllocateNode extends FixedWithNextNode implements LIRLowerable {
 
     public static final NodeClass<PrefetchAllocateNode> TYPE = NodeClass.create(PrefetchAllocateNode.class);
-    @Input ValueNode distance;
-    @Input ValueNode address;
+    @Input(InputType.Association) AddressNode address;
 
-    public PrefetchAllocateNode(ValueNode address, ValueNode distance) {
+    public PrefetchAllocateNode(ValueNode address) {
         super(TYPE, StampFactory.forVoid());
-        this.address = address;
-        this.distance = distance;
+        this.address = (AddressNode) address;
     }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        ((HotSpotNodeLIRBuilder) gen).emitPrefetchAllocate(address, distance);
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitPrefetchAllocate(gen.operand(address));
     }
 
     @NodeIntrinsic
-    public static native void prefetch(Word address, Word distance);
+    public static native void prefetch(Address address);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java	Mon Jun 08 18:47:58 2015 +0200
@@ -24,19 +24,18 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 
 @NodeInfo
 public class SerialWriteBarrier extends WriteBarrier {
 
     public static final NodeClass<SerialWriteBarrier> TYPE = NodeClass.create(SerialWriteBarrier.class);
 
-    public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise) {
-        this(TYPE, object, location, precise);
+    public SerialWriteBarrier(AddressNode address, boolean precise) {
+        this(TYPE, address, precise);
     }
 
-    protected SerialWriteBarrier(NodeClass<? extends SerialWriteBarrier> c, ValueNode object, LocationNode location, boolean precise) {
-        super(c, object, null, location, precise);
+    protected SerialWriteBarrier(NodeClass<? extends SerialWriteBarrier> c, AddressNode address, boolean precise) {
+        super(c, address, null, precise);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,23 +26,21 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
 public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable {
 
     public static final NodeClass<WriteBarrier> TYPE = NodeClass.create(WriteBarrier.class);
-    @Input protected ValueNode object;
+    @Input(InputType.Association) protected AddressNode address;
     @OptionalInput protected ValueNode value;
-    @OptionalInput(InputType.Association) protected LocationNode location;
     protected final boolean precise;
 
-    protected WriteBarrier(NodeClass<? extends WriteBarrier> c, ValueNode object, ValueNode value, LocationNode location, boolean precise) {
+    protected WriteBarrier(NodeClass<? extends WriteBarrier> c, AddressNode address, ValueNode value, boolean precise) {
         super(c, StampFactory.forVoid());
-        this.object = object;
+        this.address = address;
         this.value = value;
-        this.location = location;
         this.precise = precise;
     }
 
@@ -50,12 +48,8 @@
         return value;
     }
 
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public LocationNode getLocation() {
-        return location;
+    public AddressNode getAddress() {
+        return address;
     }
 
     public boolean usePrecise() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Mon Jun 08 18:47:58 2015 +0200
@@ -34,8 +34,8 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -74,8 +74,8 @@
 
                 if (type instanceof HotSpotResolvedObjectType) {
                     ConstantNode klass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph);
-                    LocationNode location = graph.unique(new ConstantLocationNode(CLASS_MIRROR_LOCATION, classMirrorOffset));
-                    ValueNode read = graph.unique(new FloatingReadNode(klass, location, null, stamp));
+                    AddressNode address = graph.unique(new OffsetAddressNode(klass, ConstantNode.forLong(classMirrorOffset, graph)));
+                    ValueNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, stamp));
 
                     if (((HotSpotObjectConstant) constant).isCompressed()) {
                         return CompressionNode.compress(read, oopEncoding);
@@ -102,11 +102,11 @@
                         throw new JVMCIError("Can't find TYPE field in class");
                     }
 
-                    LocationNode location = graph.unique(new ConstantLocationNode(FINAL_LOCATION, typeField.offset()));
                     if (oopEncoding != null) {
                         stamp = NarrowOopStamp.compressed((AbstractObjectStamp) stamp, oopEncoding);
                     }
-                    ValueNode read = graph.unique(new FloatingReadNode(clazz, location, null, stamp));
+                    AddressNode address = graph.unique(new OffsetAddressNode(clazz, ConstantNode.forLong(typeField.offset(), graph)));
+                    ValueNode read = graph.unique(new FloatingReadNode(address, FINAL_LOCATION, null, stamp));
 
                     if (oopEncoding == null || ((HotSpotObjectConstant) constant).isCompressed()) {
                         return read;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Jun 08 18:47:58 2015 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.jvmci.common.*;
@@ -66,34 +67,33 @@
     private void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
         if (node.getBarrierType() == BarrierType.PRECISE) {
             assert config.useG1GC;
-            G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.object(), node, node.location(), false));
+            G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.getAddress(), node, false));
             graph.addAfterFixed(node, barrier);
         } else {
             assert node.getBarrierType() == BarrierType.NONE : "Non precise read barrier has been attached to read node.";
         }
     }
 
-    protected static void addG1PreWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean doLoad, boolean nullCheck, StructuredGraph graph) {
-        G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(object, value, location, doLoad, nullCheck));
+    protected static void addG1PreWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean doLoad, boolean nullCheck, StructuredGraph graph) {
+        G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(address, value, doLoad, nullCheck));
         preBarrier.setStateBefore(node.stateBefore());
         node.setNullCheck(false);
         node.setStateBefore(null);
         graph.addBeforeFixed(node, preBarrier);
     }
 
-    protected void addG1PostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) {
+    protected void addG1PostWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean precise, StructuredGraph graph) {
         final boolean alwaysNull = StampTool.isPointerAlwaysNull(value);
-        graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(object, value, location, precise, alwaysNull)));
+        graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(address, value, precise, alwaysNull)));
     }
 
-    protected void addSerialPostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) {
+    protected void addSerialPostWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean precise, StructuredGraph graph) {
         final boolean alwaysNull = StampTool.isPointerAlwaysNull(value);
         if (alwaysNull) {
             // Serial barrier isn't needed for null value
             return;
         }
-        final LocationNode loc = (precise ? location : null);
-        graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(object, loc, precise)));
+        graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(address, precise)));
     }
 
     private void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
@@ -107,11 +107,11 @@
                 boolean precise = barrierType == BarrierType.PRECISE;
                 if (config.useG1GC) {
                     if (!node.isInitialization()) {
-                        addG1PreWriteBarrier(node, node.object(), null, node.location(), true, node.getNullCheck(), graph);
+                        addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
                     }
-                    addG1PostWriteBarrier(node, node.object(), node.value(), node.location(), precise, graph);
+                    addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
                 } else {
-                    addSerialPostWriteBarrier(node, node.object(), node.value(), node.location(), precise, graph);
+                    addSerialPostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
                 }
                 break;
             default:
@@ -129,10 +129,10 @@
             case PRECISE:
                 boolean precise = barrierType == BarrierType.PRECISE;
                 if (config.useG1GC) {
-                    addG1PreWriteBarrier(node, node.object(), null, node.location(), true, node.getNullCheck(), graph);
-                    addG1PostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), precise, graph);
+                    addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
+                    addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
                 } else {
-                    addSerialPostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), precise, graph);
+                    addSerialPostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
                 }
                 break;
             default:
@@ -150,10 +150,10 @@
             case PRECISE:
                 boolean precise = barrierType == BarrierType.PRECISE;
                 if (config.useG1GC) {
-                    addG1PreWriteBarrier(node, node.object(), node.getExpectedValue(), node.location(), false, false, graph);
-                    addG1PostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), precise, graph);
+                    addG1PreWriteBarrier(node, node.getAddress(), node.getExpectedValue(), false, false, graph);
+                    addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
                 } else {
-                    addSerialPostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), precise, graph);
+                    addSerialPostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
                 }
                 break;
             default:
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Mon Jun 08 18:47:58 2015 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.jvmci.common.*;
@@ -151,9 +152,11 @@
 
     private static boolean validateBarrier(FixedAccessNode write, WriteBarrier barrier) {
         assert write instanceof WriteNode || write instanceof LoweredCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write;
-        if ((barrier.getObject() == write.object()) && (!barrier.usePrecise() || (barrier.usePrecise() && barrier.getLocation() == write.location()))) {
-            return true;
+        if (!barrier.usePrecise()) {
+            if (barrier.getAddress() instanceof OffsetAddressNode && write.getAddress() instanceof OffsetAddressNode) {
+                return ((OffsetAddressNode) barrier.getAddress()).getBase() == ((OffsetAddressNode) write.getAddress()).getBase();
+            }
         }
-        return false;
+        return barrier.getAddress() == write.getAddress();
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,11 +22,6 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import com.oracle.jvmci.meta.MetaAccessProvider;
-import com.oracle.jvmci.meta.JavaConstant;
-import com.oracle.jvmci.meta.ConstantReflectionProvider;
-import com.oracle.jvmci.meta.ResolvedJavaType;
-import com.oracle.jvmci.meta.Constant;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -37,14 +32,16 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.hotspot.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * Read {@code Class::_klass} to get the hub for a {@link java.lang.Class}. This node mostly exists
  * to replace {@code _klass._java_mirror._klass} with {@code _klass}. The constant folding could be
  * handled by
- * {@link ReadNode#canonicalizeRead(ValueNode, LocationNode, ValueNode, CanonicalizerTool)}.
+ * {@link ReadNode#canonicalizeRead(ValueNode, AddressNode, LocationIdentity, CanonicalizerTool)}.
  */
 @NodeInfo
 public final class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,7 @@
 import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.inlining.*;
@@ -180,7 +181,7 @@
                         Word biasedMark = unbiasedMark.or(thread);
                         trace(trace, "     unbiasedMark: 0x%016lx\n", unbiasedMark);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (probability(VERY_FAST_PATH_PROBABILITY, compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) {
+                        if (probability(VERY_FAST_PATH_PROBABILITY, compareAndSwap(OffsetAddressNode.address(object, markOffset()), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:acquired}", object, true);
                             lockBiasAcquired.inc();
@@ -200,7 +201,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 (probability(VERY_FAST_PATH_PROBABILITY, compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) {
+                        if (probability(VERY_FAST_PATH_PROBABILITY, compareAndSwap(OffsetAddressNode.address(object, markOffset()), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:transfer}", object, true);
                             lockBiasTransfer.inc();
@@ -223,7 +224,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, MARK_WORD_LOCATION);
+                    Word result = compareAndSwap(OffsetAddressNode.address(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
@@ -246,7 +247,7 @@
 
         // 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, MARK_WORD_LOCATION);
+        Word currentMark = compareAndSwap(OffsetAddressNode.address(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.
@@ -337,7 +338,8 @@
             // 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 (probability(VERY_SLOW_PATH_PROBABILITY, DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock))) {
+            if (probability(VERY_SLOW_PATH_PROBABILITY,
+                            DirectCompareAndSwapNode.compareAndSwap(OffsetAddressNode.address(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.
                 traceObject(trace, "-lock{stub}", object, false);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Jun 08 18:47:58 2015 +0200
@@ -54,6 +54,7 @@
 import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.replacements.*;
@@ -135,7 +136,7 @@
             int distance = config().allocatePrefetchDistance;
             ExplodeLoopNode.explodeLoop();
             for (int i = 0; i < lines; i++) {
-                PrefetchAllocateNode.prefetch(address, Word.signed(distance));
+                PrefetchAllocateNode.prefetch(OffsetAddressNode.address(address, distance));
                 distance += stepSize;
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,17 +22,11 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import com.oracle.jvmci.code.Register;
-import com.oracle.jvmci.code.TargetDescription;
-import com.oracle.jvmci.meta.NamedLocationIdentity;
-import com.oracle.jvmci.meta.LocationIdentity;
-import com.oracle.jvmci.meta.ForeignCallDescriptor;
-import com.oracle.jvmci.meta.Kind;
-import static com.oracle.jvmci.code.MemoryBarriers.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
+import static com.oracle.jvmci.code.MemoryBarriers.*;
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
@@ -43,6 +37,8 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.graal.nodes.memory.address.AddressNode.Address;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -51,7 +47,9 @@
 import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
+import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.hotspot.HotSpotVMConfig.CompressEncoding;
+import com.oracle.jvmci.meta.*;
 
 public class WriteBarrierSnippets implements Snippets {
 
@@ -72,14 +70,8 @@
     public static final LocationIdentity GC_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Index");
 
     @Snippet
-    public static void serialWriteBarrier(Object object, Object location, @ConstantParameter boolean usePrecise) {
-        Object fixedObject = FixedValueAnchorNode.getObject(object);
-        Pointer oop;
-        if (usePrecise) {
-            oop = Word.fromArray(fixedObject, SnippetLocationProxyNode.location(location));
-        } else {
-            oop = Word.fromObject(fixedObject);
-        }
+    public static void serialWriteBarrier(Address address) {
+        Pointer oop = Word.fromAddress(address);
         serialWriteBarrierCounter.inc();
         int cardTableShift = (isImmutableCode() && generatePIC()) ? CardTableShiftNode.cardTableShift() : cardTableShift();
         long cardTableAddress = (isImmutableCode() && generatePIC()) ? CardTableAddressNode.cardTableAddress() : cardTableStart();
@@ -114,16 +106,15 @@
     }
 
     @Snippet
-    public static void g1PreWriteBarrier(Object object, Object expectedObject, Object location, @ConstantParameter boolean doLoad, @ConstantParameter boolean nullCheck,
+    public static void g1PreWriteBarrier(Address address, Object object, Object expectedObject, @ConstantParameter boolean doLoad, @ConstantParameter boolean nullCheck,
                     @ConstantParameter Register threadRegister, @ConstantParameter boolean trace) {
         if (nullCheck) {
-            NullCheckNode.nullCheck(object);
+            NullCheckNode.nullCheck(address);
         }
         Word thread = registerAsWord(threadRegister);
-        Object fixedObject = FixedValueAnchorNode.getObject(object);
-        verifyOop(fixedObject);
+        verifyOop(object);
         Object fixedExpectedObject = FixedValueAnchorNode.getObject(expectedObject);
-        Word field = Word.fromWordBase(Word.fromArray(fixedObject, SnippetLocationProxyNode.location(location)));
+        Word field = Word.fromWordBase(Word.fromAddress(address));
         Word previousOop = Word.fromWordBase(Word.fromObject(fixedExpectedObject));
         byte markingValue = thread.readByte(g1SATBQueueMarkingOffset());
         Word bufferAddress = thread.readWord(g1SATBQueueBufferOffset());
@@ -132,7 +123,7 @@
         int gcCycle = 0;
         if (trace) {
             gcCycle = (int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress()).readLong(0);
-            log(trace, "[%d] G1-Pre Thread %p Object %p\n", gcCycle, thread.rawValue(), Word.fromObject(fixedObject).rawValue());
+            log(trace, "[%d] G1-Pre Thread %p Object %p\n", gcCycle, thread.rawValue(), Word.fromObject(object).rawValue());
             log(trace, "[%d] G1-Pre Thread %p Expected Object %p\n", gcCycle, thread.rawValue(), Word.fromObject(fixedExpectedObject).rawValue());
             log(trace, "[%d] G1-Pre Thread %p Field %p\n", gcCycle, thread.rawValue(), field.rawValue());
             log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue);
@@ -170,24 +161,17 @@
     }
 
     @Snippet
-    public static void g1PostWriteBarrier(Object object, Object value, Object location, @ConstantParameter boolean usePrecise, @ConstantParameter Register threadRegister,
-                    @ConstantParameter boolean trace) {
+    public static void g1PostWriteBarrier(Address address, Object object, Object value, @ConstantParameter Register threadRegister, @ConstantParameter boolean trace) {
         Word thread = registerAsWord(threadRegister);
-        Object fixedObject = FixedValueAnchorNode.getObject(object);
         Object fixedValue = FixedValueAnchorNode.getObject(value);
-        verifyOop(fixedObject);
+        verifyOop(object);
         verifyOop(fixedValue);
-        validateObject(fixedObject, fixedValue);
-        Word oop;
-        if (usePrecise) {
-            oop = Word.fromWordBase(Word.fromArray(fixedObject, SnippetLocationProxyNode.location(location)));
-        } else {
-            oop = Word.fromWordBase(Word.fromObject(fixedObject));
-        }
+        validateObject(object, fixedValue);
+        Word oop = Word.fromWordBase(Word.fromAddress(address));
         int gcCycle = 0;
         if (trace) {
             gcCycle = (int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress()).readLong(0);
-            log(trace, "[%d] G1-Post Thread: %p Object: %p\n", gcCycle, thread.rawValue(), Word.fromObject(fixedObject).rawValue());
+            log(trace, "[%d] G1-Post Thread: %p Object: %p\n", gcCycle, thread.rawValue(), Word.fromObject(object).rawValue());
             log(trace, "[%d] G1-Post Thread: %p Field: %p\n", gcCycle, thread.rawValue(), oop.rawValue());
         }
         Word writtenValue = Word.fromWordBase(Word.fromObject(fixedValue));
@@ -355,9 +339,7 @@
 
         public void lower(SerialWriteBarrier writeBarrier, LoweringTool tool) {
             Arguments args = new Arguments(serialWriteBarrier, writeBarrier.graph().getGuardsStage(), tool.getLoweringStage());
-            args.add("object", writeBarrier.getObject());
-            args.add("location", writeBarrier.getLocation());
-            args.addConst("usePrecise", writeBarrier.usePrecise());
+            args.add("address", writeBarrier.getAddress());
             template(args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args);
         }
 
@@ -371,7 +353,13 @@
 
         public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers, LoweringTool tool) {
             Arguments args = new Arguments(g1PreWriteBarrier, writeBarrierPre.graph().getGuardsStage(), tool.getLoweringStage());
-            args.add("object", writeBarrierPre.getObject());
+            AddressNode address = writeBarrierPre.getAddress();
+            args.add("address", address);
+            if (address instanceof OffsetAddressNode) {
+                args.add("object", ((OffsetAddressNode) address).getBase());
+            } else {
+                args.add("object", null);
+            }
 
             ValueNode expected = writeBarrierPre.getExpectedObject();
             if (expected != null && expected.stamp() instanceof NarrowOopStamp) {
@@ -380,7 +368,6 @@
             }
             args.add("expectedObject", expected);
 
-            args.add("location", writeBarrierPre.getLocation());
             args.addConst("doLoad", writeBarrierPre.doLoad());
             args.addConst("nullCheck", writeBarrierPre.getNullCheck());
             args.addConst("threadRegister", registers.getThreadRegister());
@@ -390,7 +377,13 @@
 
         public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
             Arguments args = new Arguments(g1ReferentReadBarrier, readBarrier.graph().getGuardsStage(), tool.getLoweringStage());
-            args.add("object", readBarrier.getObject());
+            AddressNode address = readBarrier.getAddress();
+            args.add("address", address);
+            if (address instanceof OffsetAddressNode) {
+                args.add("object", ((OffsetAddressNode) address).getBase());
+            } else {
+                args.add("object", null);
+            }
 
             ValueNode expected = readBarrier.getExpectedObject();
             if (expected != null && expected.stamp() instanceof NarrowOopStamp) {
@@ -399,7 +392,6 @@
             }
 
             args.add("expectedObject", expected);
-            args.add("location", readBarrier.getLocation());
             args.addConst("doLoad", readBarrier.doLoad());
             args.addConst("nullCheck", false);
             args.addConst("threadRegister", registers.getThreadRegister());
@@ -414,7 +406,13 @@
                 return;
             }
             Arguments args = new Arguments(g1PostWriteBarrier, graph.getGuardsStage(), tool.getLoweringStage());
-            args.add("object", writeBarrierPost.getObject());
+            AddressNode address = writeBarrierPost.getAddress();
+            args.add("address", address);
+            if (address instanceof OffsetAddressNode) {
+                args.add("object", ((OffsetAddressNode) address).getBase());
+            } else {
+                args.add("object", null);
+            }
 
             ValueNode value = writeBarrierPost.getValue();
             if (value.stamp() instanceof NarrowOopStamp) {
@@ -423,8 +421,6 @@
             }
             args.add("value", value);
 
-            args.add("location", writeBarrierPost.getLocation());
-            args.addConst("usePrecise", writeBarrierPost.usePrecise());
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("trace", traceBarrier());
             template(args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -23,12 +23,6 @@
 //JaCoCo Exclude
 package com.oracle.graal.hotspot.replacements.arraycopy;
 
-import com.oracle.jvmci.meta.NamedLocationIdentity;
-import com.oracle.jvmci.meta.JavaConstant;
-import com.oracle.jvmci.meta.PrimitiveConstant;
-import com.oracle.jvmci.meta.LocationIdentity;
-import com.oracle.jvmci.meta.ForeignCallDescriptor;
-import com.oracle.jvmci.meta.Kind;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
@@ -41,9 +35,12 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.runtime.*;
+import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.hotspot.*;
+import com.oracle.jvmci.meta.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single, MemoryAccess, Canonicalizable {
@@ -123,9 +120,11 @@
     private ValueNode computeBase(ValueNode base, ValueNode pos) {
         FixedWithNextNode basePtr = graph().add(new GetObjectAddressNode(base));
         graph().addBeforeFixed(this, basePtr);
-        ValueNode loc = graph().unique(
-                        new IndexedLocationNode(getLocationIdentity(), runtime.getJVMCIRuntime().getArrayBaseOffset(elementKind), pos, runtime.getJVMCIRuntime().getArrayIndexScale(elementKind)));
-        return graph().unique(new ComputeAddressNode(basePtr, loc, StampFactory.forKind(Kind.Long)));
+        HotSpotJVMCIRuntimeProvider jvmciRuntime = runtime.getJVMCIRuntime();
+        int shift = CodeUtil.log2(jvmciRuntime.getArrayIndexScale(elementKind));
+        ValueNode scaledIndex = graph().unique(new LeftShiftNode(pos, ConstantNode.forInt(shift, graph())));
+        ValueNode offset = graph().unique(new AddNode(scaledIndex, ConstantNode.forInt(jvmciRuntime.getArrayBaseOffset(elementKind), graph())));
+        return graph().unique(new OffsetAddressNode(basePtr, offset));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -23,9 +23,6 @@
 //JaCoCo Exclude
 package com.oracle.graal.hotspot.replacements.arraycopy;
 
-import com.oracle.jvmci.meta.LocationIdentity;
-import com.oracle.jvmci.meta.ForeignCallDescriptor;
-import com.oracle.jvmci.meta.Kind;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
@@ -36,9 +33,12 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
+import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.hotspot.*;
+import com.oracle.jvmci.meta.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory, InputType.Value})
 public final class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
@@ -97,9 +97,12 @@
     private ValueNode computeBase(ValueNode base, ValueNode pos) {
         FixedWithNextNode basePtr = graph().add(new GetObjectAddressNode(base));
         graph().addBeforeFixed(this, basePtr);
+
         HotSpotJVMCIRuntimeProvider jvmciRuntime = runtime.getJVMCIRuntime();
-        ValueNode loc = graph().unique(new IndexedLocationNode(getLocationIdentity(), jvmciRuntime.getArrayBaseOffset(Kind.Object), pos, jvmciRuntime.getArrayIndexScale(Kind.Object)));
-        return graph().unique(new ComputeAddressNode(basePtr, loc, StampFactory.forKind(Kind.Long)));
+        int shift = CodeUtil.log2(jvmciRuntime.getArrayIndexScale(Kind.Object));
+        ValueNode scaledIndex = graph().unique(new LeftShiftNode(pos, ConstantNode.forInt(shift, graph())));
+        ValueNode offset = graph().unique(new AddNode(scaledIndex, ConstantNode.forInt(jvmciRuntime.getArrayBaseOffset(Kind.Object), graph())));
+        return graph().unique(new OffsetAddressNode(basePtr, offset));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.word.*;
@@ -246,7 +247,7 @@
                 return Word.zero();
             }
 
-            if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop, HEAP_TOP_LOCATION).equal(heapTop)) {
+            if (compareAndSwap(RawAddressNode.address(heapTopAddress), heapTop, newHeapTop, HEAP_TOP_LOCATION).equal(heapTop)) {
                 return heapTop;
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/MetaspacePointer.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/MetaspacePointer.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,14 +22,13 @@
  */
 package com.oracle.graal.hotspot.word;
 
-import com.oracle.jvmci.meta.LocationIdentity;
 import static com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode.*;
 
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
 import com.oracle.graal.word.*;
 import com.oracle.graal.word.Word.Opcode;
 import com.oracle.graal.word.Word.Operation;
+import com.oracle.jvmci.meta.*;
 
 /**
  * Marker type for a metaspace pointer.
@@ -51,7 +50,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -66,7 +65,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -81,7 +80,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -96,7 +95,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -111,7 +110,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -126,7 +125,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -141,7 +140,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -156,7 +155,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -171,7 +170,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -182,7 +181,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -193,7 +192,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -204,7 +203,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -215,7 +214,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -226,7 +225,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -237,7 +236,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -248,7 +247,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -259,7 +258,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -270,7 +269,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_POINTER)
@@ -285,7 +284,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -300,7 +299,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -315,7 +314,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -330,7 +329,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -345,7 +344,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -360,7 +359,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -375,7 +374,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -390,7 +389,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -405,7 +404,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.INITIALIZE)
@@ -420,7 +419,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -431,7 +430,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -442,7 +441,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -453,7 +452,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -464,7 +463,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -475,7 +474,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -486,7 +485,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -497,7 +496,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -508,7 +507,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
@@ -519,7 +518,7 @@
      * are in bytes. The memory must be uninitialized or zero prior to this operation.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.INITIALIZE)
@@ -530,7 +529,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_POINTER)
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Jun 08 18:47:58 2015 +0200
@@ -142,8 +142,6 @@
      */
     void emitData(AllocatableValue dst, byte[] data);
 
-    Value emitAddress(Value base, long displacement, Value index, int scale);
-
     Variable emitAddress(StackSlotValue slot);
 
     void emitMembar(int barriers);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.lir.gen.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.jvmci.meta.*;
-
-/**
- * Location node that is the sum of two other location nodes. Can represent locations in the form of
- * [(base + x) + y] where base is a node and x and y are location nodes.
- */
-@NodeInfo(nameTemplate = "&+({p#locationIdentity/s})")
-public final class AddLocationNode extends LocationNode implements Canonicalizable.Binary<LocationNode> {
-
-    public static final NodeClass<AddLocationNode> TYPE = NodeClass.create(AddLocationNode.class);
-    @Input(InputType.Association) ValueNode x;
-    @Input(InputType.Association) ValueNode y;
-
-    public LocationNode getX() {
-        return (LocationNode) x;
-    }
-
-    public LocationNode getY() {
-        return (LocationNode) y;
-    }
-
-    public AddLocationNode(LocationNode x, LocationNode y) {
-        super(TYPE, StampFactory.forVoid());
-        assert x.getLocationIdentity().equals(y.getLocationIdentity());
-        this.x = x;
-        this.y = y;
-    }
-
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        return getX().getLocationIdentity();
-    }
-
-    public LocationNode canonical(CanonicalizerTool tool, LocationNode forX, LocationNode forY) {
-        if (forX instanceof ConstantLocationNode) {
-            return canonical((ConstantLocationNode) forX, forY);
-        }
-        if (forY instanceof ConstantLocationNode) {
-            return canonical((ConstantLocationNode) forY, forX);
-        }
-        if (forX instanceof IndexedLocationNode && forY instanceof IndexedLocationNode) {
-            IndexedLocationNode xIdx = (IndexedLocationNode) forX;
-            IndexedLocationNode yIdx = (IndexedLocationNode) forY;
-            if (xIdx.getIndexScaling() == yIdx.getIndexScaling()) {
-                long displacement = xIdx.getDisplacement() + yIdx.getDisplacement();
-                ValueNode index = BinaryArithmeticNode.add(xIdx.getIndex(), yIdx.getIndex());
-                return new IndexedLocationNode(getLocationIdentity(), displacement, index, xIdx.getIndexScaling());
-            }
-        }
-        return this;
-    }
-
-    private LocationNode canonical(ConstantLocationNode constant, LocationNode other) {
-        if (other instanceof ConstantLocationNode) {
-            ConstantLocationNode otherConst = (ConstantLocationNode) other;
-            return new ConstantLocationNode(getLocationIdentity(), otherConst.getDisplacement() + constant.getDisplacement());
-        } else if (other instanceof IndexedLocationNode) {
-            IndexedLocationNode otherIdx = (IndexedLocationNode) other;
-            return new IndexedLocationNode(getLocationIdentity(), otherIdx.getDisplacement() + constant.getDisplacement(), otherIdx.getIndex(), otherIdx.getIndexScaling());
-        } else if (other instanceof AddLocationNode) {
-            AddLocationNode otherAdd = (AddLocationNode) other;
-            LocationNode newInner = otherAdd.canonical(constant, otherAdd.getX());
-            if (newInner != otherAdd) {
-                return new AddLocationNode(newInner, otherAdd.getY());
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
-        Value xAddr = getX().generateAddress(builder, gen, base);
-        return getY().generateAddress(builder, gen, xAddr);
-    }
-
-    @Override
-    public IntegerStamp getDisplacementStamp() {
-        return (IntegerStamp) IntegerStamp.OPS.getAdd().foldStamp(getX().getDisplacementStamp(), getY().getDisplacementStamp());
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.jvmci.meta.*;
-
-@NodeInfo
-public final class ComputeAddressNode extends FloatingNode implements LIRLowerable {
-
-    public static final NodeClass<ComputeAddressNode> TYPE = NodeClass.create(ComputeAddressNode.class);
-    @Input ValueNode object;
-    @Input(InputType.Association) ValueNode location;
-
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public LocationNode getLocation() {
-        return (LocationNode) location;
-    }
-
-    public ComputeAddressNode(ValueNode object, ValueNode location, Stamp stamp) {
-        super(TYPE, stamp);
-        this.object = object;
-        this.location = location;
-    }
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value addr = getLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(getObject()));
-        gen.setResult(this, gen.getLIRGeneratorTool().asAllocatable(addr));
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.gen.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.jvmci.meta.*;
-
-/**
- * Location node that has a constant displacement. Can represent addresses of the form [base + disp]
- * where base is a node and disp is a constant.
- */
-@NodeInfo(nameTemplate = "&({p#locationIdentity/s})")
-public final class ConstantLocationNode extends LocationNode {
-
-    public static final NodeClass<ConstantLocationNode> TYPE = NodeClass.create(ConstantLocationNode.class);
-    protected final LocationIdentity locationIdentity;
-    protected final long displacement;
-
-    public ConstantLocationNode(LocationIdentity identity, long displacement) {
-        super(TYPE, StampFactory.forVoid());
-        this.locationIdentity = identity;
-        this.displacement = displacement;
-    }
-
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        return locationIdentity;
-    }
-
-    public long getDisplacement() {
-        return displacement;
-    }
-
-    @Override
-    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
-        return gen.emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
-    }
-
-    @Override
-    public IntegerStamp getDisplacementStamp() {
-        return StampFactory.forInteger(64, displacement, displacement);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.lir.gen.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.jvmci.code.*;
-import com.oracle.jvmci.meta.*;
-
-/**
- * Location node that has a displacement and a scaled index. Can represent locations in the form of
- * [base + index * scale + disp] where base and index are nodes and scale and disp are integer
- * constants.
- */
-@NodeInfo(nameTemplate = "&({p#locationIdentity/s})[{i#index}]")
-public final class IndexedLocationNode extends LocationNode implements Canonicalizable {
-    public static final NodeClass<IndexedLocationNode> TYPE = NodeClass.create(IndexedLocationNode.class);
-
-    protected final LocationIdentity locationIdentity;
-    protected final long displacement;
-    @Input ValueNode index;
-    protected final int indexScaling;
-
-    /**
-     * Gets the index or offset of this location.
-     */
-    public ValueNode getIndex() {
-        return index;
-    }
-
-    public long getDisplacement() {
-        return displacement;
-    }
-
-    /**
-     * @return Constant that is used to scale the index.
-     */
-    public int getIndexScaling() {
-        return indexScaling;
-    }
-
-    public IndexedLocationNode(LocationIdentity identity, long displacement, ValueNode index, int indexScaling) {
-        super(TYPE, StampFactory.forVoid());
-        assert index != null;
-        assert indexScaling != 0;
-        this.locationIdentity = identity;
-        this.index = index;
-        this.displacement = displacement;
-        this.indexScaling = indexScaling;
-    }
-
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        return locationIdentity;
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (index.isConstant()) {
-            return new ConstantLocationNode(getLocationIdentity(), index.asJavaConstant().asLong() * indexScaling + displacement);
-        }
-        return this;
-    }
-
-    @Override
-    public IntegerStamp getDisplacementStamp() {
-        assert indexScaling > 0 && CodeUtil.isPowerOf2(indexScaling);
-        int scale = CodeUtil.log2(indexScaling);
-        return (IntegerStamp) IntegerStamp.OPS.getAdd().foldStamp(StampFactory.forInteger(64, displacement, displacement),
-                        IntegerStamp.OPS.getSignExtend().foldStamp(32, 64, IntegerStamp.OPS.getShl().foldStamp(index.stamp(), StampFactory.forInteger(64, scale, scale))));
-    }
-
-    @Override
-    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
-        return gen.emitAddress(base, displacement, builder.operand(getIndex()), getIndexScaling());
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -26,8 +26,8 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.meta.*;
 
@@ -42,8 +42,8 @@
     protected final Kind readKind;
     protected final boolean compressible;
 
-    public JavaReadNode(Kind readKind, ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
-        super(TYPE, object, location, StampFactory.forKind(readKind), barrierType);
+    public JavaReadNode(Kind readKind, AddressNode address, LocationIdentity location, BarrierType barrierType, boolean compressible) {
+        super(TYPE, address, location, StampFactory.forKind(readKind), barrierType);
         this.readKind = readKind;
         this.compressible = compressible;
     }
@@ -66,6 +66,6 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        return ReadNode.canonicalizeRead(this, location(), object(), tool);
+        return ReadNode.canonicalizeRead(this, getAddress(), getLocationIdentity(), tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.meta.*;
 
@@ -40,8 +41,8 @@
     protected final Kind writeKind;
     protected final boolean compressible;
 
-    public JavaWriteNode(Kind writeKind, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
-        super(TYPE, object, value, location, barrierType, initialization);
+    public JavaWriteNode(Kind writeKind, AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType, boolean compressible, boolean initialization) {
+        super(TYPE, address, location, value, barrierType, initialization);
         this.writeKind = writeKind;
         this.compressible = compressible;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.Node.ValueNumberable;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.gen.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.jvmci.meta.*;
-
-/**
- * A location for a memory access in terms of the kind of value accessed and how to access it. All
- * locations have the form [base + location], where base is a node and location is defined by
- * subclasses of the {@link LocationNode}.
- */
-@NodeInfo(allowedUsageTypes = {InputType.Association})
-public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable {
-
-    public static final NodeClass<LocationNode> TYPE = NodeClass.create(LocationNode.class);
-
-    /**
-     * Marker interface for locations in snippets.
-     */
-    public interface Location {
-    }
-
-    protected LocationNode(NodeClass<? extends LocationNode> c, Stamp stamp) {
-        super(c, stamp);
-    }
-
-    /**
-     * Returns the identity of the accessed memory location.
-     */
-    public abstract LocationIdentity getLocationIdentity();
-
-    @Override
-    public final void generate(NodeLIRBuilderTool generator) {
-        // nothing to do...
-    }
-
-    public abstract Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base);
-
-    /**
-     * @return the range of the displacement as a 64-bit integer stamp
-     */
-    public abstract IntegerStamp getDisplacementStamp();
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -62,20 +63,31 @@
                 if (((FixedValueAnchorNode) usage).usages().isNotEmpty()) {
                     return;
                 }
-            } else if (usage instanceof WriteNode) {
-                if (((WriteNode) usage).object() != this || usage.usages().isNotEmpty()) {
-                    // we would need to fix up the memory graph if the write has usages
+            } else if (usage instanceof OffsetAddressNode) {
+                if (((OffsetAddressNode) usage).getBase() != this) {
                     return;
                 }
+                for (Node access : usage.usages()) {
+                    if (access instanceof WriteNode) {
+                        if (access.usages().isNotEmpty()) {
+                            // we would need to fix up the memory graph if the write has usages
+                            return;
+                        }
+                    } else {
+                        return;
+                    }
+                }
             } else {
                 return;
             }
         }
         for (Node usage : usages().distinct().snapshot()) {
-            List<Node> snapshot = usage.inputs().snapshot();
-            graph().removeFixed((FixedWithNextNode) usage);
-            for (Node input : snapshot) {
-                tool.removeIfUnused(input);
+            if (usage instanceof OffsetAddressNode) {
+                for (Node access : usage.usages().snapshot()) {
+                    removeUsage(tool, (FixedWithNextNode) access);
+                }
+            } else {
+                removeUsage(tool, (FixedWithNextNode) usage);
             }
         }
         List<Node> snapshot = inputs().snapshot();
@@ -85,6 +97,14 @@
         }
     }
 
+    private void removeUsage(SimplifierTool tool, FixedWithNextNode usage) {
+        List<Node> snapshot = usage.inputs().snapshot();
+        graph().removeFixed(usage);
+        for (Node input : snapshot) {
+            tool.removeIfUnused(input);
+        }
+    }
+
     @Override
     public void lower(LoweringTool tool) {
         tool.getLowerer().lower(this, tool);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -28,8 +28,8 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.meta.*;
 
@@ -40,28 +40,18 @@
 public final class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single {
 
     public static final NodeClass<AtomicReadAndAddNode> TYPE = NodeClass.create(AtomicReadAndAddNode.class);
-    @Input ValueNode object;
-    @Input ValueNode offset;
+    @Input(InputType.Association) AddressNode address;
     @Input ValueNode delta;
 
     protected final LocationIdentity locationIdentity;
 
-    public AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) {
+    public AtomicReadAndAddNode(AddressNode address, ValueNode delta, LocationIdentity locationIdentity) {
         super(TYPE, StampFactory.forKind(delta.getKind()));
-        this.object = object;
-        this.offset = offset;
+        this.address = address;
         this.delta = delta;
         this.locationIdentity = locationIdentity;
     }
 
-    public ValueNode object() {
-        return object;
-    }
-
-    public ValueNode offset() {
-        return offset;
-    }
-
     public ValueNode delta() {
         return delta;
     }
@@ -71,9 +61,7 @@
     }
 
     public void generate(NodeLIRBuilderTool gen) {
-        LocationNode location = graph().unique(new IndexedLocationNode(getLocationIdentity(), 0, offset, 1));
-        Value address = location.generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
-        Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(address, gen.operand(delta));
+        Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(gen.operand(address), gen.operand(delta));
         gen.setResult(this, result);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -27,8 +27,8 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.meta.*;
 
@@ -43,8 +43,8 @@
     @Input ValueNode newValue;
     @OptionalInput(InputType.State) FrameState stateAfter;
 
-    public LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType) {
-        super(TYPE, object, location, newValue.stamp().unrestricted(), barrierType);
+    public LoweredAtomicReadAndWriteNode(AddressNode address, LocationIdentity location, ValueNode newValue, BarrierType barrierType) {
+        super(TYPE, address, location, newValue.stamp().unrestricted(), barrierType);
         this.newValue = newValue;
     }
 
@@ -62,13 +62,8 @@
         return true;
     }
 
-    public LocationIdentity getLocationIdentity() {
-        return location().getLocationIdentity();
-    }
-
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
-        Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(address, gen.operand(getNewValue()));
+        Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(gen.operand(getAddress()), gen.operand(getNewValue()));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -26,8 +26,8 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.meta.*;
 
@@ -64,18 +64,13 @@
         return newValue;
     }
 
-    public LoweredCompareAndSwapNode(ValueNode object, LocationNode location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) {
-        super(TYPE, object, location, StampFactory.forKind(Kind.Boolean.getStackKind()), barrierType);
+    public LoweredCompareAndSwapNode(AddressNode address, LocationIdentity location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) {
+        super(TYPE, address, location, StampFactory.forKind(Kind.Boolean.getStackKind()), barrierType);
         assert expectedValue.getKind() == newValue.getKind();
         this.expectedValue = expectedValue;
         this.newValue = newValue;
     }
 
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        return location().getLocationIdentity();
-    }
-
     public boolean canNullCheck() {
         return false;
     }
@@ -83,8 +78,7 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         assert getNewValue().stamp().isCompatible(getExpectedValue().stamp());
-        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
-        Value result = gen.getLIRGeneratorTool().emitCompareAndSwap(address, gen.operand(getExpectedValue()), gen.operand(getNewValue()), JavaConstant.INT_1, JavaConstant.INT_0);
+        Value result = gen.getLIRGeneratorTool().emitCompareAndSwap(gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()), JavaConstant.INT_1, JavaConstant.INT_0);
         gen.setResult(this, result);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/AbstractWriteNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/AbstractWriteNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.jvmci.meta.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
@@ -66,18 +67,19 @@
         return initialization;
     }
 
-    protected AbstractWriteNode(NodeClass<? extends AbstractWriteNode> c, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) {
-        this(c, object, value, location, barrierType, false);
+    protected AbstractWriteNode(NodeClass<? extends AbstractWriteNode> c, AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) {
+        this(c, address, location, value, barrierType, false);
     }
 
-    protected AbstractWriteNode(NodeClass<? extends AbstractWriteNode> c, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) {
-        super(c, object, location, StampFactory.forVoid(), barrierType);
+    protected AbstractWriteNode(NodeClass<? extends AbstractWriteNode> c, AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType, boolean initialization) {
+        super(c, address, location, StampFactory.forVoid(), barrierType);
         this.value = value;
         this.initialization = initialization;
     }
 
-    protected AbstractWriteNode(NodeClass<? extends AbstractWriteNode> c, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) {
-        super(c, object, location, StampFactory.forVoid(), guard, barrierType, false, null);
+    protected AbstractWriteNode(NodeClass<? extends AbstractWriteNode> c, AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType, GuardingNode guard,
+                    boolean initialization) {
+        super(c, address, location, StampFactory.forVoid(), guard, barrierType, false, null);
         this.value = value;
         this.initialization = initialization;
     }
@@ -87,11 +89,6 @@
         return (type == InputType.Guard && getNullCheck()) ? true : super.isAllowedUsageType(type);
     }
 
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        return location().getLocationIdentity();
-    }
-
     public MemoryNode getLastLocationAccess() {
         return (MemoryNode) lastLocationAccess;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/Access.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/Access.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,14 +22,15 @@
  */
 package com.oracle.graal.nodes.memory;
 
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.jvmci.meta.*;
 
 public interface Access extends GuardedNode, HeapAccess {
 
-    ValueNode object();
+    AddressNode getAddress();
 
-    LocationNode accessLocation();
+    LocationIdentity getLocationIdentity();
 
     boolean canNullCheck();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FixedAccessNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FixedAccessNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -27,36 +27,36 @@
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.jvmci.meta.*;
 
 /**
- * Accesses a value at an memory address specified by an {@linkplain #object object} and a
- * {@linkplain #accessLocation() location}. The access does not include a null check on the object.
+ * Accesses a value at an memory address specified by an {@linkplain #address address}. The access
+ * does not include a null check on the object.
  */
 @NodeInfo
 public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode implements Access {
     public static final NodeClass<FixedAccessNode> TYPE = NodeClass.create(FixedAccessNode.class);
 
     @OptionalInput(InputType.Guard) protected GuardingNode guard;
-    @Input protected ValueNode object;
-    @Input(InputType.Association) protected ValueNode location;
+
+    @Input(InputType.Association) AddressNode address;
+    protected final LocationIdentity location;
+
     protected boolean nullCheck;
     protected BarrierType barrierType;
 
-    public ValueNode object() {
-        return object;
+    public AddressNode getAddress() {
+        return address;
     }
 
-    protected void setObject(ValueNode x) {
-        updateUsages(object, x);
-        object = x;
+    public void setAddress(AddressNode address) {
+        updateUsages(this.address, address);
+        this.address = address;
     }
 
-    public LocationNode location() {
-        return (LocationNode) location;
-    }
-
-    public LocationNode accessLocation() {
-        return (LocationNode) location;
+    public LocationIdentity getLocationIdentity() {
+        return location;
     }
 
     public boolean getNullCheck() {
@@ -67,18 +67,18 @@
         this.nullCheck = check;
     }
 
-    protected FixedAccessNode(NodeClass<? extends FixedAccessNode> c, ValueNode object, ValueNode location, Stamp stamp) {
-        this(c, object, location, stamp, BarrierType.NONE);
+    protected FixedAccessNode(NodeClass<? extends FixedAccessNode> c, AddressNode address, LocationIdentity location, Stamp stamp) {
+        this(c, address, location, stamp, BarrierType.NONE);
     }
 
-    protected FixedAccessNode(NodeClass<? extends FixedAccessNode> c, ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) {
-        this(c, object, location, stamp, null, barrierType, false, null);
+    protected FixedAccessNode(NodeClass<? extends FixedAccessNode> c, AddressNode address, LocationIdentity location, Stamp stamp, BarrierType barrierType) {
+        this(c, address, location, stamp, null, barrierType, false, null);
     }
 
-    protected FixedAccessNode(NodeClass<? extends FixedAccessNode> c, ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
+    protected FixedAccessNode(NodeClass<? extends FixedAccessNode> c, AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
                     FrameState stateBefore) {
         super(c, stamp, stateBefore);
-        this.object = object;
+        this.address = address;
         this.location = location;
         this.guard = guard;
         this.barrierType = barrierType;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatableAccessNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatableAccessNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -27,6 +27,8 @@
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * An {@link FixedAccessNode} that can be converted to a {@link FloatingAccessNode}.
@@ -35,17 +37,17 @@
 public abstract class FloatableAccessNode extends FixedAccessNode {
     public static final NodeClass<FloatableAccessNode> TYPE = NodeClass.create(FloatableAccessNode.class);
 
-    protected FloatableAccessNode(NodeClass<? extends FloatableAccessNode> c, ValueNode object, ValueNode location, Stamp stamp) {
-        super(c, object, location, stamp);
+    protected FloatableAccessNode(NodeClass<? extends FloatableAccessNode> c, AddressNode address, LocationIdentity location, Stamp stamp) {
+        super(c, address, location, stamp);
     }
 
-    protected FloatableAccessNode(NodeClass<? extends FloatableAccessNode> c, ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
-        super(c, object, location, stamp, guard, barrierType, false, null);
+    protected FloatableAccessNode(NodeClass<? extends FloatableAccessNode> c, AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
+        super(c, address, location, stamp, guard, barrierType, false, null);
     }
 
-    protected FloatableAccessNode(NodeClass<? extends FloatableAccessNode> c, ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
-                    FrameState stateBefore) {
-        super(c, object, location, stamp, guard, barrierType, nullCheck, stateBefore);
+    protected FloatableAccessNode(NodeClass<? extends FloatableAccessNode> c, AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType,
+                    boolean nullCheck, FrameState stateBefore) {
+        super(c, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
     }
 
     public abstract FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess);
@@ -62,6 +64,6 @@
      * an attached write barrier with pre-semantics can not also float.
      */
     public boolean canFloat() {
-        return !forceFixed && location().getLocationIdentity().isSingle() && getBarrierType() == BarrierType.NONE;
+        return !forceFixed && getLocationIdentity().isSingle() && getBarrierType() == BarrierType.NONE;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatingAccessNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatingAccessNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -27,50 +27,47 @@
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.jvmci.meta.*;
 
 @NodeInfo
 public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess {
     public static final NodeClass<FloatingAccessNode> TYPE = NodeClass.create(FloatingAccessNode.class);
 
-    @Input ValueNode object;
-    @Input(InputType.Association) LocationNode location;
+    @Input(InputType.Association) AddressNode address;
+    protected final LocationIdentity location;
+
     protected BarrierType barrierType;
 
-    public ValueNode object() {
-        return object;
-    }
-
-    public LocationNode location() {
-        return location;
-    }
-
-    public LocationNode accessLocation() {
-        return location;
-    }
-
-    public LocationIdentity getLocationIdentity() {
-        return location.getLocationIdentity();
-    }
-
-    protected FloatingAccessNode(NodeClass<? extends FloatingAccessNode> c, ValueNode object, LocationNode location, Stamp stamp) {
+    protected FloatingAccessNode(NodeClass<? extends FloatingAccessNode> c, AddressNode address, LocationIdentity location, Stamp stamp) {
         super(c, stamp);
-        this.object = object;
+        this.address = address;
         this.location = location;
     }
 
-    protected FloatingAccessNode(NodeClass<? extends FloatingAccessNode> c, ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
+    protected FloatingAccessNode(NodeClass<? extends FloatingAccessNode> c, AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
         super(c, stamp, guard);
-        this.object = object;
+        this.address = address;
         this.location = location;
         this.barrierType = barrierType;
     }
 
     @Override
+    public AddressNode getAddress() {
+        return address;
+    }
+
+    @Override
+    public LocationIdentity getLocationIdentity() {
+        return location;
+    }
+
+    @Override
     public BarrierType getBarrierType() {
         return barrierType;
     }
 
+    @Override
     public boolean canNullCheck() {
         return true;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatingReadNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatingReadNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.meta.*;
 
@@ -41,16 +42,16 @@
 
     @OptionalInput(InputType.Memory) MemoryNode lastLocationAccess;
 
-    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) {
-        this(object, location, lastLocationAccess, stamp, null, BarrierType.NONE);
+    public FloatingReadNode(AddressNode address, LocationIdentity location, MemoryNode lastLocationAccess, Stamp stamp) {
+        this(address, location, lastLocationAccess, stamp, null, BarrierType.NONE);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) {
-        this(object, location, lastLocationAccess, stamp, guard, BarrierType.NONE);
+    public FloatingReadNode(AddressNode address, LocationIdentity location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) {
+        this(address, location, lastLocationAccess, stamp, guard, BarrierType.NONE);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
-        super(TYPE, object, location, stamp, guard, barrierType);
+    public FloatingReadNode(AddressNode address, LocationIdentity location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
+        super(TYPE, address, location, stamp, guard, barrierType);
         this.lastLocationAccess = lastLocationAccess;
     }
 
@@ -65,22 +66,25 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, null));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, gen.operand(address), null));
     }
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
-            return new FloatingReadNode(((PiNode) object()).getOriginalNode(), location(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType());
+        if (getAddress() instanceof OffsetAddressNode) {
+            OffsetAddressNode objAddress = (OffsetAddressNode) getAddress();
+            if (objAddress.getBase() instanceof PiNode && ((PiNode) objAddress.getBase()).getGuard() == getGuard()) {
+                OffsetAddressNode newAddress = new OffsetAddressNode(((PiNode) objAddress.getBase()).getOriginalNode(), objAddress.getOffset());
+                return new FloatingReadNode(newAddress, getLocationIdentity(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType());
+            }
         }
-        return ReadNode.canonicalizeRead(this, location(), object(), tool);
+        return ReadNode.canonicalizeRead(this, getAddress(), getLocationIdentity(), tool);
     }
 
     @Override
     public FixedAccessNode asFixedNode() {
-        return graph().add(new ReadNode(object(), accessLocation(), stamp(), getGuard(), getBarrierType()));
+        return graph().add(new ReadNode(getAddress(), getLocationIdentity(), stamp(), getGuard(), getBarrierType()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -28,8 +28,8 @@
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.jvmci.common.*;
 import com.oracle.jvmci.meta.*;
@@ -38,36 +38,35 @@
  * Reads an {@linkplain FixedAccessNode accessed} value.
  */
 @NodeInfo
-public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode {
+public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, Virtualizable, GuardingNode {
 
     public static final NodeClass<ReadNode> TYPE = NodeClass.create(ReadNode.class);
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) {
-        super(TYPE, object, location, stamp, null, barrierType);
+    public ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, BarrierType barrierType) {
+        super(TYPE, address, location, stamp, null, barrierType);
     }
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
-        super(TYPE, object, location, stamp, guard, barrierType);
+    public ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
+        super(TYPE, address, location, stamp, guard, barrierType);
     }
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) {
-        super(TYPE, object, location, stamp, guard, barrierType, nullCheck, stateBefore);
+    public ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) {
+        super(TYPE, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
     }
 
-    public ReadNode(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) {
+    public ReadNode(AddressNode address, LocationIdentity location, ValueNode guard, BarrierType barrierType) {
         /*
          * Used by node intrinsics. Really, you can trust me on that! Since the initial value for
          * location is a parameter, i.e., a ParameterNode, the constructor cannot use the declared
          * type LocationNode.
          */
-        super(TYPE, object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, barrierType);
+        super(TYPE, address, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, barrierType);
     }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, gen.operand(address), gen.state(this)));
     }
 
     @Override
@@ -81,11 +80,15 @@
                 return null;
             }
         }
-        if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
-            return new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), getNullCheck(), stateBefore());
+        if (getAddress() instanceof OffsetAddressNode) {
+            OffsetAddressNode objAddress = (OffsetAddressNode) getAddress();
+            if (objAddress.getBase() instanceof PiNode && ((PiNode) objAddress.getBase()).getGuard() == getGuard()) {
+                OffsetAddressNode newAddress = new OffsetAddressNode(((PiNode) objAddress.getBase()).getOriginalNode(), objAddress.getOffset());
+                return new ReadNode(newAddress, getLocationIdentity(), stamp(), getGuard(), getBarrierType(), getNullCheck(), stateBefore());
+            }
         }
         if (!getNullCheck()) {
-            return canonicalizeRead(this, location(), object(), tool);
+            return canonicalizeRead(this, getAddress(), getLocationIdentity(), tool);
         } else {
             // if this read is a null check, then replacing it with the value is incorrect for
             // guard-type usages
@@ -95,7 +98,7 @@
 
     @Override
     public FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess) {
-        return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType()));
+        return graph().unique(new FloatingReadNode(getAddress(), getLocationIdentity(), lastLocationAccess, stamp(), getGuard(), getBarrierType()));
     }
 
     @Override
@@ -103,12 +106,14 @@
         return (getNullCheck() && type == InputType.Guard) ? true : super.isAllowedUsageType(type);
     }
 
-    public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool) {
+    public static ValueNode canonicalizeRead(ValueNode read, AddressNode address, LocationIdentity locationIdentity, CanonicalizerTool tool) {
         MetaAccessProvider metaAccess = tool.getMetaAccess();
-        if (tool.canonicalizeReads()) {
-            if (metaAccess != null && object != null && object.isConstant() && !object.isNullConstant() && location instanceof ConstantLocationNode) {
-                long displacement = ((ConstantLocationNode) location).getDisplacement();
-                if ((location.getLocationIdentity().isImmutable())) {
+        if (tool.canonicalizeReads() && address instanceof OffsetAddressNode) {
+            OffsetAddressNode objAddress = (OffsetAddressNode) address;
+            ValueNode object = objAddress.getBase();
+            if (metaAccess != null && object.isConstant() && !object.isNullConstant() && objAddress.getOffset().isConstant()) {
+                long displacement = objAddress.getOffset().asJavaConstant().asLong();
+                if (locationIdentity.isImmutable()) {
                     Constant constant = read.stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), object.asConstant(), displacement);
                     if (constant != null) {
                         return ConstantNode.forConstant(read.stamp(), constant, metaAccess);
@@ -120,7 +125,7 @@
                     return ConstantNode.forConstant(read.stamp(), constant, metaAccess);
                 }
             }
-            if (location.getLocationIdentity().equals(LocationIdentity.ARRAY_LENGTH_LOCATION)) {
+            if (locationIdentity.equals(LocationIdentity.ARRAY_LENGTH_LOCATION)) {
                 ValueNode length = GraphUtil.arrayLength(object);
                 if (length != null) {
                     // TODO Does this need a PiCastNode to the positive range?
@@ -132,36 +137,6 @@
     }
 
     @Override
-    public boolean push(PiNode parent) {
-        if (!(location() instanceof ConstantLocationNode && parent.stamp() instanceof ObjectStamp && parent.object().stamp() instanceof ObjectStamp)) {
-            return false;
-        }
-
-        ObjectStamp piStamp = (ObjectStamp) parent.stamp();
-        ResolvedJavaType receiverType = piStamp.type();
-        if (receiverType == null) {
-            return false;
-        }
-        ConstantLocationNode constantLocationNode = (ConstantLocationNode) location();
-        ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(constantLocationNode.getDisplacement(), constantLocationNode.getKind());
-        if (field == null) {
-            // field was not declared by receiverType
-            return false;
-        }
-
-        ObjectStamp valueStamp = (ObjectStamp) parent.object().stamp();
-        ResolvedJavaType valueType = StampTool.typeOrNull(valueStamp);
-        if (valueType != null && field.getDeclaringClass().isAssignableFrom(valueType)) {
-            if (piStamp.nonNull() == valueStamp.nonNull() && piStamp.alwaysNull() == valueStamp.alwaysNull()) {
-                replaceFirstInput(parent, parent.object());
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    @Override
     public void virtualize(VirtualizerTool tool) {
         throw JVMCIError.shouldNotReachHere("unexpected ReadNode before PEA");
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -27,7 +27,8 @@
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.LocationNode.Location;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.graal.nodes.memory.address.AddressNode.Address;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.common.*;
 import com.oracle.jvmci.meta.*;
@@ -40,34 +41,42 @@
 
     public static final NodeClass<WriteNode> TYPE = NodeClass.create(WriteNode.class);
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) {
-        super(TYPE, object, value, location, barrierType);
+    private WriteNode(ValueNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) {
+        this((AddressNode) address, location, value, barrierType);
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) {
-        super(TYPE, object, value, location, barrierType, initialization);
+    public WriteNode(AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) {
+        super(TYPE, address, location, value, barrierType);
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) {
-        super(TYPE, object, value, location, barrierType, guard, initialization);
+    public WriteNode(AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType, boolean initialization) {
+        super(TYPE, address, location, value, barrierType, initialization);
+    }
+
+    public WriteNode(AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType, GuardingNode guard, boolean initialization) {
+        super(TYPE, address, location, value, barrierType, guard, initialization);
     }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         LIRKind writeKind = gen.getLIRGeneratorTool().getLIRKind(value().stamp());
-        gen.getLIRGeneratorTool().emitStore(writeKind, address, gen.operand(value()), gen.state(this));
+        gen.getLIRGeneratorTool().emitStore(writeKind, gen.operand(address), gen.operand(value()), gen.state(this));
     }
 
     @Override
     public void simplify(SimplifierTool tool) {
-        if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
-            setObject(((PiNode) object()).getOriginalNode());
+        if (getAddress() instanceof OffsetAddressNode) {
+            OffsetAddressNode objAddress = (OffsetAddressNode) getAddress();
+            if (objAddress.getBase() instanceof PiNode && ((PiNode) objAddress.getBase()).getGuard() == getGuard()) {
+                OffsetAddressNode newAddress = graph().unique(new OffsetAddressNode(((PiNode) objAddress.getBase()).getOriginalNode(), objAddress.getOffset()));
+                setAddress(newAddress);
+                tool.addToWorkList(newAddress);
+            }
         }
     }
 
     @NodeIntrinsic
-    public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter BarrierType barrierType);
+    public static native void writeMemory(Address address, @ConstantNodeParameter LocationIdentity location, Object value, @ConstantNodeParameter BarrierType barrierType);
 
     @Override
     public void virtualize(VirtualizerTool tool) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/address/AddressNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.memory.address;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.calc.*;
+
+/**
+ * Base class for nodes that deal with addressing calculation.
+ */
+@NodeInfo(allowedUsageTypes = InputType.Association)
+public abstract class AddressNode extends FloatingNode {
+    public static final NodeClass<AddressNode> TYPE = NodeClass.create(AddressNode.class);
+
+    protected AddressNode(NodeClass<? extends AddressNode> c) {
+        super(c, StampFactory.pointer());
+    }
+
+    public abstract static class Address extends StructuralInput.Association {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/address/OffsetAddressNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.memory.address;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.jvmci.meta.*;
+
+/**
+ * Represents an address that is composed of a base and an offset. The base can be either a
+ * {@link Kind#Object}, a word-sized integer or another pointer. The offset must be a word-sized
+ * integer.
+ */
+@NodeInfo(allowedUsageTypes = InputType.Association)
+public class OffsetAddressNode extends AddressNode implements Canonicalizable, PiPushable {
+    public static final NodeClass<OffsetAddressNode> TYPE = NodeClass.create(OffsetAddressNode.class);
+
+    @Input ValueNode base;
+    @Input ValueNode offset;
+
+    public OffsetAddressNode(ValueNode base, ValueNode offset) {
+        super(TYPE);
+        this.base = base;
+        this.offset = offset;
+    }
+
+    public ValueNode getBase() {
+        return base;
+    }
+
+    public void setBase(ValueNode base) {
+        updateUsages(this.base, base);
+        this.base = base;
+    }
+
+    public ValueNode getOffset() {
+        return offset;
+    }
+
+    public void setOffset(ValueNode offset) {
+        updateUsages(this.offset, offset);
+        this.offset = offset;
+    }
+
+    public Node canonical(CanonicalizerTool tool) {
+        if (base instanceof RawAddressNode) {
+            // The RawAddressNode is redundant, just directly use its input as base.
+            return new OffsetAddressNode(((RawAddressNode) base).getAddress(), offset);
+        } else if (base instanceof OffsetAddressNode) {
+            // Rewrite (&base[offset1])[offset2] to base[offset1 + offset2].
+            OffsetAddressNode b = (OffsetAddressNode) base;
+            return new OffsetAddressNode(b.getBase(), BinaryArithmeticNode.add(b.getOffset(), this.getOffset()));
+        } else {
+            return this;
+        }
+    }
+
+    @Override
+    public boolean push(PiNode parent) {
+        if (!(offset.isConstant() && parent.stamp() instanceof ObjectStamp && parent.object().stamp() instanceof ObjectStamp)) {
+            return false;
+        }
+
+        ObjectStamp piStamp = (ObjectStamp) parent.stamp();
+        ResolvedJavaType receiverType = piStamp.type();
+        if (receiverType == null) {
+            return false;
+        }
+        ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(offset.asJavaConstant().asLong(), Kind.Void);
+        if (field == null) {
+            // field was not declared by receiverType
+            return false;
+        }
+
+        ObjectStamp valueStamp = (ObjectStamp) parent.object().stamp();
+        ResolvedJavaType valueType = StampTool.typeOrNull(valueStamp);
+        if (valueType != null && field.getDeclaringClass().isAssignableFrom(valueType)) {
+            if (piStamp.nonNull() == valueStamp.nonNull() && piStamp.alwaysNull() == valueStamp.alwaysNull()) {
+                replaceFirstInput(parent, parent.object());
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @NodeIntrinsic
+    public static native Address address(Object base, long offset);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/address/RawAddressNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.memory.address;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Convert a word-sized integer to a raw address.
+ */
+@NodeInfo(allowedUsageTypes = InputType.Association)
+public class RawAddressNode extends AddressNode {
+    public static final NodeClass<RawAddressNode> TYPE = NodeClass.create(RawAddressNode.class);
+
+    @Input ValueNode address;
+
+    public RawAddressNode(ValueNode address) {
+        super(TYPE);
+        this.address = address;
+    }
+
+    public ValueNode getAddress() {
+        return address;
+    }
+
+    public void setAddress(ValueNode address) {
+        updateUsages(this.address, address);
+        this.address = address;
+    }
+
+    @NodeIntrinsic
+    public static native Address address(long address);
+
+    @NodeIntrinsic
+    public static native Address address(Object address);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringProvider.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringProvider.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.jvmci.meta.*;
 
 /**
@@ -36,14 +36,14 @@
     void lower(Node n, LoweringTool tool);
 
     /**
-     * Reconstructs the array index from a location node that was created as a lowering of an
+     * Reconstructs the array index from an address node that was created as a lowering of an
      * indexed access to an array.
      *
      * @param elementKind the {@link Kind} of the array elements
-     * @param location a location pointing to an element in an array
+     * @param address an {@link AddressNode} pointing to an element in an array
      * @return a node that gives the index of the element
      */
-    ValueNode reconstructArrayIndex(Kind elementKind, LocationNode location);
+    ValueNode reconstructArrayIndex(Kind elementKind, AddressNode address);
 
     /**
      * Gets the platform specific size of a type in bytes.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/AddressLoweringPhase.java	Mon Jun 08 18:47:58 2015 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.common;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.graal.phases.*;
+
+public class AddressLoweringPhase extends Phase {
+
+    public abstract static class AddressLowering {
+
+        public abstract AddressNode lower(ValueNode address);
+
+        public abstract AddressNode lower(ValueNode base, ValueNode offset);
+    }
+
+    private final AddressLowering lowering;
+
+    public AddressLoweringPhase(AddressLowering lowering) {
+        this.lowering = lowering;
+        assert lowering != null;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (Node node : graph.getNodes()) {
+            AddressNode lowered;
+            if (node instanceof RawAddressNode) {
+                RawAddressNode address = (RawAddressNode) node;
+                lowered = lowering.lower(address.getAddress());
+            } else if (node instanceof OffsetAddressNode) {
+                OffsetAddressNode address = (OffsetAddressNode) node;
+                lowered = lowering.lower(address.getBase(), address.getOffset());
+            } else {
+                continue;
+            }
+
+            node.replaceAndDelete(lowered);
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Jun 08 18:47:58 2015 +0200
@@ -328,7 +328,7 @@
 
         private static void processFloatable(FloatableAccessNode accessNode, MemoryMapImpl state) {
             StructuredGraph graph = accessNode.graph();
-            LocationIdentity locationIdentity = accessNode.location().getLocationIdentity();
+            LocationIdentity locationIdentity = accessNode.getLocationIdentity();
             if (accessNode.canFloat()) {
                 assert accessNode.getNullCheck() == false;
                 MemoryNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.phases.common;
 
-import com.oracle.jvmci.meta.JavaConstant;
-
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
@@ -35,8 +33,8 @@
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
@@ -44,6 +42,7 @@
 import com.oracle.graal.phases.schedule.SchedulePhase.SchedulingStrategy;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.jvmci.debug.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * This phase lowers {@link GuardNode GuardNodes} into corresponding control-flow structure and
@@ -82,16 +81,23 @@
             if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
                 nullGuarded.clear();
             } else {
-                Iterator<Entry<ValueNode, ValueNode>> it = nullGuarded.entrySet().iterator();
-                while (it.hasNext()) {
-                    Entry<ValueNode, ValueNode> entry = it.next();
-                    ValueNode guard = entry.getValue();
-                    if (guard.usages().contains(node)) {
-                        it.remove();
-                    } else if (guard instanceof PiNode && guard != node) {
-                        PiNode piNode = (PiNode) guard;
-                        if (piNode.getGuard().asNode().usages().contains(node)) {
+                /*
+                 * The OffsetAddressNode itself never forces materialization of a null check, even
+                 * if its input is a PiNode. The null check will be folded into the first usage of
+                 * the OffsetAddressNode, so we need to keep it in the nullGuarded map.
+                 */
+                if (!(node instanceof OffsetAddressNode)) {
+                    Iterator<Entry<ValueNode, ValueNode>> it = nullGuarded.entrySet().iterator();
+                    while (it.hasNext()) {
+                        Entry<ValueNode, ValueNode> entry = it.next();
+                        ValueNode guard = entry.getValue();
+                        if (guard.usages().contains(node)) {
                             it.remove();
+                        } else if (guard instanceof PiNode && guard != node) {
+                            PiNode piNode = (PiNode) guard;
+                            if (piNode.getGuard().asNode().usages().contains(node)) {
+                                it.remove();
+                            }
                         }
                     }
                 }
@@ -108,21 +114,21 @@
         }
 
         private void processAccess(Access access) {
-            if (access.canNullCheck()) {
-                ValueNode object = access.object();
-                check(access, object);
+            if (access.canNullCheck() && access.getAddress() instanceof OffsetAddressNode) {
+                OffsetAddressNode address = (OffsetAddressNode) access.getAddress();
+                check(access, address);
             }
         }
 
-        private void check(Access access, ValueNode object) {
-            ValueNode guard = nullGuarded.get(object);
-            if (guard != null && isImplicitNullCheck(access.accessLocation())) {
+        private void check(Access access, OffsetAddressNode address) {
+            ValueNode base = address.getBase();
+            ValueNode guard = nullGuarded.get(base);
+            if (guard != null && isImplicitNullCheck(address.getOffset())) {
                 if (guard instanceof PiNode) {
                     PiNode piNode = (PiNode) guard;
-                    assert guard == object;
+                    assert guard == address.getBase();
                     assert piNode.getGuard() instanceof GuardNode : piNode;
-                    assert access.object() == guard;
-                    access.asNode().replaceFirstInput(piNode, piNode.getOriginalNode());
+                    address.setBase(piNode.getOriginalNode());
                 } else {
                     assert guard instanceof GuardNode;
                 }
@@ -154,7 +160,7 @@
                 if (condition.hasNoUsages()) {
                     GraphUtil.killWithUnusedFloatingInputs(condition);
                 }
-                nullGuarded.remove(object);
+                nullGuarded.remove(base);
             }
         }
 
@@ -166,9 +172,10 @@
             }
         }
 
-        private boolean isImplicitNullCheck(LocationNode location) {
-            if (location instanceof ConstantLocationNode) {
-                return ((ConstantLocationNode) location).getDisplacement() < implicitNullCheckLimit;
+        private boolean isImplicitNullCheck(ValueNode offset) {
+            JavaConstant c = offset.asJavaConstant();
+            if (c != null) {
+                return c.asLong() < implicitNullCheckLimit;
             } else {
                 return false;
             }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Jun 08 18:47:58 2015 +0200
@@ -768,9 +768,9 @@
             }
         } else if (n instanceof FloatingReadNode) {
             FloatingReadNode frn = (FloatingReadNode) n;
-            buf.format(" // from %s", frn.location().getLocationIdentity());
+            buf.format(" // from %s", frn.getLocationIdentity());
             buf.format(", lastAccess: %s", frn.getLastLocationAccess());
-            buf.format(", object: %s", frn.object());
+            buf.format(", address: %s", frn.getAddress());
         } else if (n instanceof GuardNode) {
             buf.format(", anchor: %s", ((GuardNode) n).getAnchor());
         }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
 import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.replacements.*;
 
 public class AMD64GraphBuilderPlugins {
@@ -126,7 +127,8 @@
                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode delta) {
                         // Emits a null-check for the otherwise unused receiver
                         unsafe.get();
-                        b.addPush(kind, new AtomicReadAndAddNode(object, offset, delta, LocationIdentity.any()));
+                        AddressNode address = b.add(new OffsetAddressNode(object, offset));
+                        b.addPush(kind, new AtomicReadAndAddNode(address, delta, LocationIdentity.any()));
                         return true;
                     }
                 });
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
 import com.oracle.jvmci.code.*;
@@ -97,19 +98,18 @@
     private static void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) {
         JavaReadNode read = (JavaReadNode) graph.start().next();
         Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind());
-        Assert.assertEquals(graph.getParameter(0), read.object());
 
-        IndexedLocationNode location = (IndexedLocationNode) read.location();
-        Assert.assertEquals(locationIdentity, location.getLocationIdentity());
-        Assert.assertEquals(1, location.getIndexScaling());
+        OffsetAddressNode address = (OffsetAddressNode) read.getAddress();
+        Assert.assertEquals(graph.getParameter(0), address.getBase());
+        Assert.assertEquals(locationIdentity, read.getLocationIdentity());
 
         if (indexConvert) {
-            SignExtendNode convert = (SignExtendNode) location.getIndex();
+            SignExtendNode convert = (SignExtendNode) address.getOffset();
             Assert.assertEquals(convert.getInputBits(), 32);
             Assert.assertEquals(convert.getResultBits(), 64);
             Assert.assertEquals(graph.getParameter(1), convert.getValue());
         } else {
-            Assert.assertEquals(graph.getParameter(1), location.getIndex());
+            Assert.assertEquals(graph.getParameter(1), address.getOffset());
         }
 
         ReturnNode ret = (ReturnNode) read.next();
@@ -119,20 +119,20 @@
     private static void assertWrite(StructuredGraph graph, boolean indexConvert, LocationIdentity locationIdentity) {
         JavaWriteNode write = (JavaWriteNode) graph.start().next();
         Assert.assertEquals(graph.getParameter(2), write.value());
-        Assert.assertEquals(graph.getParameter(0), write.object());
+
+        OffsetAddressNode address = (OffsetAddressNode) write.getAddress();
+        Assert.assertEquals(graph.getParameter(0), address.getBase());
         Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci);
 
-        IndexedLocationNode location = (IndexedLocationNode) write.location();
-        Assert.assertEquals(locationIdentity, location.getLocationIdentity());
-        Assert.assertEquals(1, location.getIndexScaling());
+        Assert.assertEquals(locationIdentity, write.getLocationIdentity());
 
         if (indexConvert) {
-            SignExtendNode convert = (SignExtendNode) location.getIndex();
+            SignExtendNode convert = (SignExtendNode) address.getOffset();
             Assert.assertEquals(convert.getInputBits(), 32);
             Assert.assertEquals(convert.getResultBits(), 64);
             Assert.assertEquals(graph.getParameter(1), convert.getValue());
         } else {
-            Assert.assertEquals(graph.getParameter(1), location.getIndex());
+            Assert.assertEquals(graph.getParameter(1), address.getOffset());
         }
 
         ReturnNode ret = (ReturnNode) write.next();
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PEGraphDecoderTest.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PEGraphDecoderTest.java	Mon Jun 08 18:47:58 2015 +0200
@@ -30,9 +30,9 @@
 import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -99,8 +99,8 @@
         r.register2("readInt", Object.class, long.class, new InvocationPlugin() {
             @Override
             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode obj, ValueNode offset) {
-                LocationNode location = b.add(new ConstantLocationNode(LocationIdentity.any(), offset.asJavaConstant().asLong()));
-                ReadNode read = b.addPush(Kind.Int, new ReadNode(obj, location, StampFactory.forKind(Kind.Int), BarrierType.NONE));
+                AddressNode address = b.add(new OffsetAddressNode(obj, offset));
+                ReadNode read = b.addPush(Kind.Int, new ReadNode(address, LocationIdentity.any(), StampFactory.forKind(Kind.Int), BarrierType.NONE));
                 read.setGuard(AbstractBeginNode.prevBegin(read));
                 return true;
             }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -106,21 +107,20 @@
         JavaReadNode read = (JavaReadNode) cast.next();
         Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind());
 
-        Assert.assertEquals(cast, read.object());
+        OffsetAddressNode address = (OffsetAddressNode) read.getAddress();
+        Assert.assertEquals(cast, address.getBase());
         Assert.assertEquals(graph.getParameter(0), cast.getInput());
         Assert.assertEquals(target.wordKind, cast.stamp().getStackKind());
 
-        IndexedLocationNode location = (IndexedLocationNode) read.location();
-        Assert.assertEquals(locationIdentity, location.getLocationIdentity());
-        Assert.assertEquals(1, location.getIndexScaling());
+        Assert.assertEquals(locationIdentity, read.getLocationIdentity());
 
         if (indexConvert) {
-            SignExtendNode convert = (SignExtendNode) location.getIndex();
+            SignExtendNode convert = (SignExtendNode) address.getOffset();
             Assert.assertEquals(convert.getInputBits(), 32);
             Assert.assertEquals(convert.getResultBits(), 64);
             Assert.assertEquals(graph.getParameter(1), convert.getValue());
         } else {
-            Assert.assertEquals(graph.getParameter(1), location.getIndex());
+            Assert.assertEquals(graph.getParameter(1), address.getOffset());
         }
 
         ReturnNode ret = (ReturnNode) read.next();
@@ -134,21 +134,20 @@
         Assert.assertEquals(graph.getParameter(2), write.value());
         Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci);
 
-        Assert.assertEquals(cast, write.object());
+        OffsetAddressNode address = (OffsetAddressNode) write.getAddress();
+        Assert.assertEquals(cast, address.getBase());
         Assert.assertEquals(graph.getParameter(0), cast.getInput());
         Assert.assertEquals(target.wordKind, cast.stamp().getStackKind());
 
-        IndexedLocationNode location = (IndexedLocationNode) write.location();
-        Assert.assertEquals(locationIdentity, location.getLocationIdentity());
-        Assert.assertEquals(1, location.getIndexScaling());
+        Assert.assertEquals(locationIdentity, write.getLocationIdentity());
 
         if (indexConvert) {
-            SignExtendNode convert = (SignExtendNode) location.getIndex();
+            SignExtendNode convert = (SignExtendNode) address.getOffset();
             Assert.assertEquals(convert.getInputBits(), 32);
             Assert.assertEquals(convert.getResultBits(), 64);
             Assert.assertEquals(graph.getParameter(1), convert.getValue());
         } else {
-            Assert.assertEquals(graph.getParameter(1), location.getIndex());
+            Assert.assertEquals(graph.getParameter(1), address.getOffset());
         }
 
         ReturnNode ret = (ReturnNode) write.next();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Mon Jun 08 18:47:58 2015 +0200
@@ -31,7 +31,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.asm.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -41,6 +40,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
@@ -127,16 +127,31 @@
         GraphUtil.removeFixedWithUnusedInputs(n);
     }
 
+    protected static AddressNode createOffsetAddress(StructuredGraph graph, ValueNode object, long offset) {
+        ValueNode o = ConstantNode.forLong(offset, graph);
+        return graph.unique(new OffsetAddressNode(object, o));
+    }
+
+    protected AddressNode createFieldAddress(StructuredGraph graph, ValueNode object, ResolvedJavaField field) {
+        int offset = fieldOffset(field);
+        if (offset >= 0) {
+            return createOffsetAddress(graph, object, offset);
+        } else {
+            return null;
+        }
+    }
+
     protected void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) {
         assert loadField.getKind() != Kind.Illegal;
         StructuredGraph graph = loadField.graph();
         ResolvedJavaField field = loadField.field();
         ValueNode object = loadField.isStatic() ? staticFieldBase(graph, field) : loadField.object();
         Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind());
-        ConstantLocationNode location = createFieldLocation(graph, field, false);
-        assert location != null : "Field that is loaded must not be eliminated: " + field.getDeclaringClass().toJavaName(true) + "." + field.getName();
 
-        ReadNode memoryRead = graph.add(new ReadNode(object, location, loadStamp, fieldLoadBarrierType(field)));
+        AddressNode address = createFieldAddress(graph, object, field);
+        assert address != null : "Field that is loaded must not be eliminated: " + field.getDeclaringClass().toJavaName(true) + "." + field.getName();
+
+        ReadNode memoryRead = graph.add(new ReadNode(address, field.getLocationIdentity(), loadStamp, fieldLoadBarrierType(field)));
         ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead);
         loadField.replaceAtUsages(readValue);
         graph.replaceFixed(loadField, memoryRead);
@@ -156,10 +171,10 @@
         ResolvedJavaField field = storeField.field();
         ValueNode object = storeField.isStatic() ? staticFieldBase(graph, field) : storeField.object();
         ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value());
-        ConstantLocationNode location = createFieldLocation(graph, field, false);
-        assert location != null;
+        AddressNode address = createFieldAddress(graph, object, field);
+        assert address != null;
 
-        WriteNode memoryWrite = graph.add(new WriteNode(object, value, location, fieldStoreBarrierType(storeField.field())));
+        WriteNode memoryWrite = graph.add(new WriteNode(address, field.getLocationIdentity(), value, fieldStoreBarrierType(storeField.field())));
         memoryWrite.setStateAfter(storeField.stateAfter());
         graph.replaceFixedWithFixed(storeField, memoryWrite);
         memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool));
@@ -172,13 +187,25 @@
         }
     }
 
+    public AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, Kind elementKind, ValueNode index) {
+        ValueNode longIndex = graph.unique(new SignExtendNode(index, 64));
+
+        int shift = CodeUtil.log2(arrayScalingFactor(elementKind));
+        ValueNode scaledIndex = graph.unique(new LeftShiftNode(longIndex, ConstantNode.forInt(shift, graph)));
+
+        int base = arrayBaseOffset(elementKind);
+        ValueNode offset = graph.unique(new AddNode(scaledIndex, ConstantNode.forLong(base, graph)));
+
+        return graph.unique(new OffsetAddressNode(array, offset));
+    }
+
     protected void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) {
         StructuredGraph graph = loadIndexed.graph();
         Kind elementKind = loadIndexed.elementKind();
-        LocationNode location = createArrayLocation(graph, elementKind, loadIndexed.index(), false);
         Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind);
 
-        ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), location, loadStamp, BarrierType.NONE));
+        AddressNode address = createArrayAddress(graph, loadIndexed.array(), elementKind, loadIndexed.index());
+        ReadNode memoryRead = graph.add(new ReadNode(address, NamedLocationIdentity.getArrayLocation(elementKind), loadStamp, BarrierType.NONE));
         ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead);
 
         memoryRead.setGuard(createBoundsCheck(loadIndexed, tool));
@@ -191,7 +218,6 @@
         StructuredGraph graph = storeIndexed.graph();
         GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool);
         Kind elementKind = storeIndexed.elementKind();
-        LocationNode location = createArrayLocation(graph, elementKind, storeIndexed.index(), false);
 
         ValueNode value = storeIndexed.value();
         ValueNode array = storeIndexed.array();
@@ -215,7 +241,9 @@
             }
         }
 
-        WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), location, arrayStoreBarrierType(storeIndexed.elementKind())));
+        AddressNode address = createArrayAddress(graph, array, elementKind, storeIndexed.index());
+        WriteNode memoryWrite = graph.add(new WriteNode(address, NamedLocationIdentity.getArrayLocation(elementKind), implicitStoreConvert(graph, elementKind, value),
+                        arrayStoreBarrierType(storeIndexed.elementKind())));
         memoryWrite.setGuard(boundsCheck);
         memoryWrite.setStateAfter(storeIndexed.stateAfter());
         graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
@@ -229,9 +257,9 @@
     protected void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) {
         StructuredGraph graph = arrayLengthNode.graph();
         ValueNode array = arrayLengthNode.array();
-        ConstantLocationNode location = graph.unique(new ConstantLocationNode(ARRAY_LENGTH_LOCATION, arrayLengthOffset()));
 
-        ReadNode arrayLengthRead = graph.add(new ReadNode(array, location, StampFactory.positiveInt(), BarrierType.NONE));
+        AddressNode address = createOffsetAddress(graph, array, arrayLengthOffset());
+        ReadNode arrayLengthRead = graph.add(new ReadNode(address, ARRAY_LENGTH_LOCATION, StampFactory.positiveInt(), BarrierType.NONE));
         arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool));
         graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
     }
@@ -261,12 +289,12 @@
     protected void lowerCompareAndSwapNode(CompareAndSwapNode cas) {
         StructuredGraph graph = cas.graph();
         Kind valueKind = cas.getValueKind();
-        LocationNode location = createLocation(cas.offset(), cas.getLocationIdentity(), valueKind);
 
         ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected());
         ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue());
 
-        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, compareAndSwapBarrierType(cas)));
+        AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset()));
+        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(address, cas.getLocationIdentity(), expectedValue, newValue, compareAndSwapBarrierType(cas)));
         atomicNode.setStateAfter(cas.stateAfter());
         graph.replaceFixedWithFixed(cas, atomicNode);
     }
@@ -274,11 +302,11 @@
     protected void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) {
         StructuredGraph graph = n.graph();
         Kind valueKind = n.getValueKind();
-        LocationNode location = graph.unique(new IndexedLocationNode(n.getLocationIdentity(), 0, n.offset(), 1));
 
         ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
 
-        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, atomicReadAndWriteBarrierType(n)));
+        AddressNode address = graph.unique(new OffsetAddressNode(n.object(), n.offset()));
+        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getLocationIdentity(), newValue, atomicReadAndWriteBarrierType(n)));
         memoryRead.setStateAfter(n.stateAfter());
 
         ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead);
@@ -301,20 +329,20 @@
         }
     }
 
+    protected AddressNode createUnsafeAddress(StructuredGraph graph, ValueNode object, ValueNode offset) {
+        if (object.isConstant() && object.asConstant().isDefaultForKind()) {
+            return graph.unique(new RawAddressNode(offset));
+        } else {
+            return graph.unique(new OffsetAddressNode(object, offset));
+        }
+    }
+
     protected ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) {
         boolean compressible = load.accessKind() == Kind.Object;
         Kind readKind = load.accessKind();
-        ValueNode[] base = null;
-        ValueNode object = load.object();
-        if (object.isConstant() && object.asConstant().isDefaultForKind()) {
-            base = new ValueNode[1];
-        }
-        LocationNode location = createLocation(load, base);
-        if (base != null && base[0] != null) {
-            object = base[0];
-        }
         Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible);
-        ReadNode memoryRead = graph.add(new ReadNode(object, location, loadStamp, guard, BarrierType.NONE));
+        AddressNode address = createUnsafeAddress(graph, load.object(), load.offset());
+        ReadNode memoryRead = graph.add(new ReadNode(address, load.getLocationIdentity(), loadStamp, guard, BarrierType.NONE));
         if (guard == null) {
             // An unsafe read must not float otherwise it may float above
             // a test guaranteeing the read is safe.
@@ -327,19 +355,11 @@
 
     protected void lowerUnsafeStoreNode(UnsafeStoreNode store) {
         StructuredGraph graph = store.graph();
-        ValueNode object = store.object();
-        ValueNode[] base = null;
-        if (object.isConstant() && object.asConstant().isDefaultForKind()) {
-            base = new ValueNode[1];
-        }
-        LocationNode location = createLocation(store, base);
-        if (base != null && base[0] != null) {
-            object = base[0];
-        }
         boolean compressible = store.value().getKind() == Kind.Object;
         Kind valueKind = store.accessKind();
         ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible);
-        WriteNode write = graph.add(new WriteNode(object, value, location, unsafeStoreBarrierType(store)));
+        AddressNode address = createUnsafeAddress(graph, store.object(), store.offset());
+        WriteNode write = graph.add(new WriteNode(address, store.getLocationIdentity(), value, unsafeStoreBarrierType(store)));
         write.setStateAfter(store.stateAfter());
         graph.replaceFixedWithFixed(store, write);
     }
@@ -349,7 +369,7 @@
         Kind valueKind = read.getReadKind();
         Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible());
 
-        ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType()));
+        ReadNode memoryRead = graph.add(new ReadNode(read.getAddress(), read.getLocationIdentity(), loadStamp, read.getBarrierType()));
         GuardingNode guard = read.getGuard();
         ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible());
         if (guard == null) {
@@ -368,7 +388,7 @@
         Kind valueKind = write.getWriteKind();
         ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible());
 
-        WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), write.isInitialization()));
+        WriteNode memoryWrite = graph.add(new WriteNode(write.getAddress(), write.getLocationIdentity(), value, write.getBarrierType(), write.isInitialization()));
         memoryWrite.setStateAfter(write.stateAfter());
         graph.replaceFixedWithFixed(write, memoryWrite);
         memoryWrite.setGuard(write.getGuard());
@@ -409,21 +429,21 @@
                         // Truffle requires some leniency in terms of what can be put where:
                         assert valueKind.getStackKind() == entryKind.getStackKind() ||
                                         (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode));
-                        ConstantLocationNode location = null;
+                        AddressNode address = null;
                         BarrierType barrierType = null;
                         if (virtual instanceof VirtualInstanceNode) {
                             ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i);
                             long offset = fieldOffset(field);
                             if (offset >= 0) {
-                                location = graph.unique(new ConstantLocationNode(initLocationIdentity(), offset));
+                                address = createOffsetAddress(graph, newObject, offset);
                                 barrierType = fieldInitializationBarrier(entryKind);
                             }
                         } else {
-                            location = graph.unique(new ConstantLocationNode(initLocationIdentity(), arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind)));
+                            address = createOffsetAddress(graph, newObject, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind));
                             barrierType = arrayInitializationBarrier(entryKind);
                         }
-                        if (location != null) {
-                            WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType);
+                        if (address != null) {
+                            WriteNode write = new WriteNode(address, initLocationIdentity(), implicitStoreConvert(graph, entryKind, value), barrierType);
                             graph.addAfterFixed(newObject, graph.add(write));
                         }
                     }
@@ -444,18 +464,18 @@
                         ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)];
                         if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) {
                             assert virtual.entryKind(i) == Kind.Object && allocValue.getKind() == Kind.Object;
-                            LocationNode location;
+                            AddressNode address;
                             BarrierType barrierType;
                             if (virtual instanceof VirtualInstanceNode) {
                                 VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
-                                location = createFieldLocation(graph, virtualInstance.field(i), true);
+                                address = createFieldAddress(graph, newObject, virtualInstance.field(i));
                                 barrierType = BarrierType.IMPRECISE;
                             } else {
-                                location = createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), true);
+                                address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph));
                                 barrierType = BarrierType.PRECISE;
                             }
-                            if (location != null) {
-                                WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), location, barrierType);
+                            if (address != null) {
+                                WriteNode write = new WriteNode(address, initLocationIdentity(), implicitStoreConvert(graph, Kind.Object, allocValue), barrierType);
                                 graph.addBeforeFixed(commit, graph.add(write));
                             }
                         }
@@ -619,115 +639,14 @@
 
     protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor);
 
-    protected ConstantLocationNode createFieldLocation(StructuredGraph graph, ResolvedJavaField field, boolean initialization) {
-        int offset = fieldOffset(field);
-        if (offset >= 0) {
-            LocationIdentity loc = initialization ? initLocationIdentity() : field.getLocationIdentity();
-            return graph.unique(new ConstantLocationNode(loc, offset));
-        } else {
-            return null;
-        }
-    }
-
-    protected LocationNode createLocation(UnsafeAccessNode access, ValueNode[] base) {
-        return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind(), base);
-    }
-
-    protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) {
-        return createLocation(offsetNode, locationIdentity, accessKind, null);
-    }
-
-    /**
-     * Try to unpack the operations in offsetNode into a LocationNode, taking advantage of
-     * addressing modes if possible.
-     *
-     * @param offsetNode the computed offset into the base of the memory operation
-     * @param locationIdentity
-     * @param accessKind
-     * @param base if non-null try to find a value that can be used as the base of the memory
-     *            operation and return it as base[0]
-     * @return the newly created LocationNode
-     */
-    protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind, ValueNode[] base) {
-        ValueNode offset = offsetNode;
-        if (offset.isConstant()) {
-            long offsetValue = offset.asJavaConstant().asLong();
-            return offset.graph().unique(new ConstantLocationNode(locationIdentity, offsetValue));
-        }
-
-        long displacement = 0;
-        int indexScaling = 1;
-        boolean signExtend = false;
-        if (offset instanceof SignExtendNode) {
-            SignExtendNode extend = (SignExtendNode) offset;
-            if (extend.getResultBits() == 64) {
-                signExtend = true;
-                offset = extend.getValue();
-            }
-        }
-        if (offset instanceof AddNode) {
-            AddNode integerAddNode = (AddNode) offset;
-            if (integerAddNode.getY() instanceof ConstantNode) {
-                displacement = integerAddNode.getY().asJavaConstant().asLong();
-                offset = integerAddNode.getX();
-            }
-        }
-        if (base != null && signExtend == false && offset instanceof AddNode) {
-            /*
-             * Try to decompose the operation into base plus offset so the base can go into a new
-             * node. Prefer the unshifted side of an add as the base.
-             */
-            AddNode integerAddNode = (AddNode) offset;
-            if (integerAddNode.getY() instanceof LeftShiftNode) {
-                base[0] = integerAddNode.getX();
-                offset = integerAddNode.getY();
-            } else {
-                base[0] = integerAddNode.getY();
-                offset = integerAddNode.getX();
-            }
-            if (offset instanceof AddNode) {
-                integerAddNode = (AddNode) offset;
-                if (integerAddNode.getY() instanceof ConstantNode) {
-                    displacement = integerAddNode.getY().asJavaConstant().asLong();
-                    offset = integerAddNode.getX();
-                }
-            }
-        }
-        if (offset instanceof LeftShiftNode) {
-            LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
-            if (leftShiftNode.getY() instanceof ConstantNode) {
-                long shift = leftShiftNode.getY().asJavaConstant().asLong();
-                if (shift >= 1 && shift <= 3) {
-                    if (shift == 1) {
-                        indexScaling = 2;
-                    } else if (shift == 2) {
-                        indexScaling = 4;
-                    } else {
-                        indexScaling = 8;
-                    }
-                    offset = leftShiftNode.getX();
-                }
-            }
-        }
-        if (signExtend) {
-            // If we were using sign extended values before restore the sign extension.
-            offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64));
-        }
-        return offset.graph().unique(new IndexedLocationNode(locationIdentity, displacement, offset, indexScaling));
-    }
-
-    public IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) {
-        LocationIdentity loc = initialization ? initLocationIdentity() : NamedLocationIdentity.getArrayLocation(elementKind);
-        return graph.unique(new IndexedLocationNode(loc, arrayBaseOffset(elementKind), index, arrayScalingFactor(elementKind)));
-    }
-
     protected GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) {
         StructuredGraph graph = n.graph();
         ValueNode array = n.array();
         ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection());
         if (arrayLength == null) {
             Stamp stamp = StampFactory.positiveInt();
-            ReadNode readArrayLength = graph.add(new ReadNode(array, graph.unique(new ConstantLocationNode(ARRAY_LENGTH_LOCATION, arrayLengthOffset())), stamp, BarrierType.NONE));
+            AddressNode address = createOffsetAddress(graph, array, arrayLengthOffset());
+            ReadNode readArrayLength = graph.add(new ReadNode(address, ARRAY_LENGTH_LOCATION, stamp, BarrierType.NONE));
             graph.addBeforeFixed(n, readArrayLength);
             readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool));
             arrayLength = readArrayLength;
@@ -755,41 +674,16 @@
     }
 
     @Override
-    public ValueNode reconstructArrayIndex(Kind elementKind, LocationNode location) {
-        assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind));
-
-        long base;
-        ValueNode index;
-        int scale = arrayScalingFactor(elementKind);
+    public ValueNode reconstructArrayIndex(Kind elementKind, AddressNode address) {
+        StructuredGraph graph = address.graph();
+        ValueNode offset = ((OffsetAddressNode) address).getOffset();
 
-        if (location instanceof ConstantLocationNode) {
-            base = ((ConstantLocationNode) location).getDisplacement();
-            index = null;
-        } else if (location instanceof IndexedLocationNode) {
-            IndexedLocationNode indexedLocation = (IndexedLocationNode) location;
-            assert indexedLocation.getIndexScaling() == scale;
-            base = indexedLocation.getDisplacement();
-            index = indexedLocation.getIndex();
-        } else {
-            throw JVMCIError.shouldNotReachHere();
-        }
+        int base = arrayBaseOffset(elementKind);
+        ValueNode scaledIndex = graph.unique(new SubNode(offset, ConstantNode.forIntegerStamp(offset.stamp(), base, graph)));
 
-        base -= arrayBaseOffset(elementKind);
-        assert base >= 0 && base % scale == 0;
-
-        base /= scale;
-        assert NumUtil.isInt(base);
-
-        StructuredGraph graph = location.graph();
-        if (index == null) {
-            return ConstantNode.forInt((int) base, graph);
-        } else {
-            if (base == 0) {
-                return index;
-            } else {
-                return BinaryArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index);
-            }
-        }
+        int shift = CodeUtil.log2(arrayScalingFactor(elementKind));
+        ValueNode ret = graph.unique(new RightShiftNode(scaledIndex, ConstantNode.forInt(shift, graph)));
+        return IntegerConvertNode.convert(ret, StampFactory.forKind(Kind.Int), graph);
     }
 
     @Override
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java	Mon Jun 08 18:47:58 2015 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 import com.oracle.graal.word.Word.Opcode;
@@ -205,21 +206,23 @@
             case READ_BARRIERED: {
                 assert args.length == 2 || args.length == 3;
                 Kind readKind = wordTypes.asKind(wordMethod.getSignature().getReturnType(wordMethod.getDeclaringClass()));
-                LocationNode location;
+                AddressNode address = makeAddress(b, args[0], args[1]);
+                LocationIdentity location;
                 if (args.length == 2) {
-                    location = makeLocation(b, args[1], any());
+                    location = any();
                 } else {
-                    location = makeLocation(b, args[1], args[2]);
+                    assert args[2].isConstant();
+                    location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant());
                 }
-                b.push(returnKind, readOp(b, readKind, args[0], location, operation.opcode()));
+                b.push(returnKind, readOp(b, readKind, address, location, operation.opcode()));
                 break;
             }
             case READ_HEAP: {
                 assert args.length == 3;
                 Kind readKind = wordTypes.asKind(wordMethod.getSignature().getReturnType(wordMethod.getDeclaringClass()));
-                LocationNode location = makeLocation(b, args[1], any());
+                AddressNode address = makeAddress(b, args[0], args[1]);
                 BarrierType barrierType = snippetReflection.asObject(BarrierType.class, args[2].asJavaConstant());
-                b.push(returnKind, readOp(b, readKind, args[0], location, barrierType, true));
+                b.push(returnKind, readOp(b, readKind, address, any(), barrierType, true));
                 break;
             }
             case WRITE_POINTER:
@@ -228,13 +231,15 @@
             case INITIALIZE: {
                 assert args.length == 3 || args.length == 4;
                 Kind writeKind = wordTypes.asKind(wordMethod.getSignature().getParameterType(wordMethod.isStatic() ? 2 : 1, wordMethod.getDeclaringClass()));
-                LocationNode location;
+                AddressNode address = makeAddress(b, args[0], args[1]);
+                LocationIdentity location;
                 if (args.length == 3) {
-                    location = makeLocation(b, args[1], LocationIdentity.any());
+                    location = any();
                 } else {
-                    location = makeLocation(b, args[1], args[3]);
+                    assert args[3].isConstant();
+                    location = snippetReflection.asObject(LocationIdentity.class, args[3].asJavaConstant());
                 }
-                writeOp(b, writeKind, args[0], args[2], location, operation.opcode());
+                writeOp(b, writeKind, address, location, args[2], operation.opcode());
                 break;
             }
             case ZERO:
@@ -268,9 +273,10 @@
                 b.push(returnKind, objectToWord);
                 break;
 
-            case FROM_ARRAY:
-                assert args.length == 2;
-                b.addPush(returnKind, new ComputeAddressNode(args[0], args[1], StampFactory.forKind(wordKind)));
+            case FROM_ADDRESS:
+                assert args.length == 1;
+                WordCastNode addressToWord = b.add(WordCastNode.addressToWord(args[0], wordKind));
+                b.push(returnKind, addressToWord);
                 break;
 
             case TO_OBJECT:
@@ -328,41 +334,34 @@
         return materialize;
     }
 
-    protected ValueNode readOp(GraphBuilderContext b, Kind readKind, ValueNode base, LocationNode location, Opcode op) {
+    protected ValueNode readOp(GraphBuilderContext b, Kind readKind, AddressNode address, LocationIdentity location, Opcode op) {
         assert op == Opcode.READ_POINTER || op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED;
         final BarrierType barrier = (op == Opcode.READ_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE);
         final boolean compressible = (op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED);
 
-        return readOp(b, readKind, base, location, barrier, compressible);
+        return readOp(b, readKind, address, location, barrier, compressible);
     }
 
-    public static ValueNode readOp(GraphBuilderContext b, Kind readKind, ValueNode base, LocationNode location, BarrierType barrierType, boolean compressible) {
+    public static ValueNode readOp(GraphBuilderContext b, Kind readKind, AddressNode address, LocationIdentity location, BarrierType barrierType, boolean compressible) {
         /*
          * A JavaReadNode lowered to a ReadNode that will not float. This means it cannot float
          * above an explicit zero check on its base address or any other test that ensures the read
          * is safe.
          */
-        JavaReadNode read = b.add(new JavaReadNode(readKind, base, location, barrierType, compressible));
+        JavaReadNode read = b.add(new JavaReadNode(readKind, address, location, barrierType, compressible));
         return read;
     }
 
-    protected void writeOp(GraphBuilderContext b, Kind writeKind, ValueNode base, ValueNode value, LocationNode location, Opcode op) {
+    protected void writeOp(GraphBuilderContext b, Kind writeKind, AddressNode address, LocationIdentity location, ValueNode value, Opcode op) {
         assert op == Opcode.WRITE_POINTER || op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED || op == Opcode.INITIALIZE;
         final BarrierType barrier = (op == Opcode.WRITE_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE);
         final boolean compressible = (op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED);
         final boolean initialize = (op == Opcode.INITIALIZE);
-        b.add(new JavaWriteNode(writeKind, base, value, location, barrier, compressible, initialize));
+        b.add(new JavaWriteNode(writeKind, address, location, value, barrier, compressible, initialize));
     }
 
-    public LocationNode makeLocation(GraphBuilderContext b, ValueNode offset, LocationIdentity locationIdentity) {
-        return b.add(new IndexedLocationNode(locationIdentity, 0, fromSigned(b, offset), 1));
-    }
-
-    public LocationNode makeLocation(GraphBuilderContext b, ValueNode offset, ValueNode locationIdentity) {
-        if (locationIdentity.isConstant()) {
-            return makeLocation(b, offset, snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant()));
-        }
-        return b.add(new SnippetLocationNode(snippetReflection, locationIdentity, b.add(ConstantNode.forLong(0)), fromSigned(b, offset), b.add(ConstantNode.forInt(1))));
+    public AddressNode makeAddress(GraphBuilderContext b, ValueNode base, ValueNode offset) {
+        return b.add(new OffsetAddressNode(base, fromSigned(b, offset)));
     }
 
     public ValueNode fromUnsigned(GraphBuilderContext b, ValueNode value) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -26,8 +26,10 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.jvmci.meta.*;
 
@@ -66,8 +68,9 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        IndexedLocationNode location = graph().unique(new IndexedLocationNode(locationIdentity, displacement, offset, 1));
-        JavaWriteNode write = graph().add(new JavaWriteNode(storeKind, object, value, location, BarrierType.NONE, storeKind == Kind.Object, false));
+        ValueNode off = graph().unique(new AddNode(offset, ConstantNode.forIntegerStamp(offset.stamp(), displacement, graph())));
+        AddressNode address = graph().unique(new OffsetAddressNode(object, off));
+        JavaWriteNode write = graph().add(new JavaWriteNode(storeKind, address, locationIdentity, value, BarrierType.NONE, storeKind == Kind.Object, false));
         graph().replaceFixedWithFixed(this, write);
 
         tool.getLowerer().lower(write, tool);
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/NativeCallStubGraphBuilder.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/NativeCallStubGraphBuilder.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,13 +22,6 @@
  */
 package com.oracle.graal.truffle.hotspot.nfi;
 
-import com.oracle.jvmci.meta.ResolvedJavaType;
-import com.oracle.jvmci.meta.ResolvedJavaMethod;
-import com.oracle.jvmci.meta.ResolvedJavaField;
-import com.oracle.jvmci.meta.NamedLocationIdentity;
-import com.oracle.jvmci.meta.LocationIdentity;
-import com.oracle.jvmci.meta.Kind;
-import com.oracle.jvmci.meta.JavaConstant;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.util.*;
@@ -39,9 +32,12 @@
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.word.nodes.*;
 import com.oracle.jvmci.common.*;
 import com.oracle.jvmci.hotspot.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * Utility creating a graph for a stub used to call a native function.
@@ -122,15 +118,13 @@
             if (kind == Kind.Object) {
                 // array value
                 Kind arrayElementKind = getElementKind(type);
-                LocationIdentity locationIdentity = NamedLocationIdentity.getArrayLocation(arrayElementKind);
                 HotSpotJVMCIRuntimeProvider jvmciRuntime = runtime().getJVMCIRuntime();
                 int displacement = jvmciRuntime.getArrayBaseOffset(arrayElementKind);
-                ConstantNode index = ConstantNode.forInt(0, g);
-                int indexScaling = jvmciRuntime.getArrayIndexScale(arrayElementKind);
-                IndexedLocationNode locationNode = g.unique(new IndexedLocationNode(locationIdentity, displacement, index, indexScaling));
-                Stamp wordStamp = StampFactory.forKind(providers.getWordTypes().getWordKind());
-                ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, wordStamp));
-                args.add(arrayAddress);
+                AddressNode arrayAddress = g.unique(new OffsetAddressNode(boxedElement, ConstantNode.forLong(displacement, g)));
+                WordCastNode cast = g.add(WordCastNode.addressToWord(arrayAddress, providers.getWordTypes().getWordKind()));
+                last.setNext(cast);
+                last = cast;
+                args.add(cast);
             } else {
                 // boxed primitive value
                 try {
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java	Mon Jun 08 18:47:58 2015 +0200
@@ -126,7 +126,7 @@
         DominatorConditionalEliminationPhase conditionalElimination = new DominatorConditionalEliminationPhase(false);
         conditionalElimination.apply(graph);
 
-        floatingReads = graph.getNodes().filter(FloatingReadNode.class).filter(n -> ((FloatingReadNode) n).location().getLocationIdentity() instanceof ObjectLocationIdentity);
+        floatingReads = graph.getNodes().filter(FloatingReadNode.class).filter(n -> ((FloatingReadNode) n).getLocationIdentity() instanceof ObjectLocationIdentity);
         conditionAnchors = graph.getNodes().filter(ConditionAnchorNode.class);
         assertThat(floatingReads, hasCount(1));
         assertThat(conditionAnchors, isEmpty());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 
 public class ReadEliminationBlockState extends EffectsBlockState<ReadEliminationBlockState> {
 
@@ -111,20 +110,38 @@
         }
     }
 
-    static class ReadCacheEntry extends CacheEntry<LocationNode> {
+    static class ReadCacheEntry extends CacheEntry<ValueNode> {
+
+        private final LocationIdentity location;
 
-        public ReadCacheEntry(ValueNode object, LocationNode identity) {
-            super(object, identity);
+        public ReadCacheEntry(ValueNode object, ValueNode offset, LocationIdentity location) {
+            super(object, offset);
+            this.location = location;
         }
 
         @Override
-        public CacheEntry<LocationNode> duplicateWithObject(ValueNode newObject) {
-            return new ReadCacheEntry(newObject, identity);
+        public CacheEntry<ValueNode> duplicateWithObject(ValueNode newObject) {
+            return new ReadCacheEntry(newObject, identity, location);
         }
 
         @Override
         public boolean conflicts(LocationIdentity other) {
-            return identity.getLocationIdentity().equals(other);
+            return location.equals(other);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof ReadCacheEntry)) {
+                return false;
+            }
+
+            ReadCacheEntry other = (ReadCacheEntry) obj;
+            return this.location.equals(other.location) && super.equals(other);
+        }
+
+        @Override
+        public int hashCode() {
+            return location.hashCode() * 23 + super.hashCode();
         }
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Jun 08 18:47:58 2015 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
@@ -86,40 +87,41 @@
             }
         } else if (node instanceof ReadNode) {
             ReadNode read = (ReadNode) node;
-            if (read.location() instanceof ConstantLocationNode) {
-                ValueNode object = GraphUtil.unproxify(read.object());
-                ReadCacheEntry identifier = new ReadCacheEntry(object, read.location());
-                ValueNode cachedValue = state.getCacheEntry(identifier);
-                if (cachedValue != null && read.stamp().isCompatible(cachedValue.stamp())) {
-                    // Anchor guard if it is not fixed and different from cachedValue's guard
-                    if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
-                        if (!(cachedValue instanceof GuardedNode) || ((GuardedNode) cachedValue).getGuard() != read.getGuard()) {
-                            effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read);
+            if (read.getAddress() instanceof OffsetAddressNode) {
+                OffsetAddressNode address = (OffsetAddressNode) read.getAddress();
+                if (address.getOffset().isConstant()) {
+                    ValueNode object = GraphUtil.unproxify(address.getBase());
+                    ReadCacheEntry identifier = new ReadCacheEntry(object, address.getOffset(), read.getLocationIdentity());
+                    ValueNode cachedValue = state.getCacheEntry(identifier);
+                    if (cachedValue != null && read.stamp().isCompatible(cachedValue.stamp())) {
+                        // Anchor guard if it is not fixed and different from cachedValue's guard
+                        if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
+                            if (!(cachedValue instanceof GuardedNode) || ((GuardedNode) cachedValue).getGuard() != read.getGuard()) {
+                                effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read);
+                            }
                         }
                     }
-                    effects.replaceAtUsages(read, cachedValue);
-                    addScalarAlias(read, cachedValue);
-                    deleted = true;
-                } else {
-                    state.addCacheEntry(identifier, read);
                 }
             }
         } else if (node instanceof WriteNode) {
             WriteNode write = (WriteNode) node;
-            if (write.location() instanceof ConstantLocationNode) {
-                ValueNode object = GraphUtil.unproxify(write.object());
-                ReadCacheEntry identifier = new ReadCacheEntry(object, write.location());
-                ValueNode cachedValue = state.getCacheEntry(identifier);
+            if (write.getAddress() instanceof OffsetAddressNode) {
+                OffsetAddressNode address = (OffsetAddressNode) write.getAddress();
+                if (address.getOffset().isConstant()) {
+                    ValueNode object = GraphUtil.unproxify(address.getBase());
+                    ReadCacheEntry identifier = new ReadCacheEntry(object, address.getOffset(), write.getLocationIdentity());
+                    ValueNode cachedValue = state.getCacheEntry(identifier);
 
-                ValueNode value = getScalarAlias(write.value());
-                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                    effects.deleteNode(write);
-                    deleted = true;
+                    ValueNode value = getScalarAlias(write.value());
+                    if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
+                        effects.deleteNode(write);
+                        deleted = true;
+                    }
+                    processIdentity(state, write.getLocationIdentity());
+                    state.addCacheEntry(identifier, value);
+                } else {
+                    processIdentity(state, write.getLocationIdentity());
                 }
-                processIdentity(state, write.location().getLocationIdentity());
-                state.addCacheEntry(identifier, value);
-            } else {
-                processIdentity(state, write.location().getLocationIdentity());
             }
         } else if (node instanceof UnsafeAccessNode) {
             if (node instanceof UnsafeLoadNode) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/BarrieredAccess.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/BarrieredAccess.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,10 +22,9 @@
  */
 package com.oracle.graal.word;
 
-import com.oracle.jvmci.meta.LocationIdentity;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.word.Word.Opcode;
 import com.oracle.graal.word.Word.Operation;
+import com.oracle.jvmci.meta.*;
 
 /**
  * Medium-level memory access for Objects. Similarly to the readXxx and writeXxx methods defined for
@@ -44,7 +43,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -59,7 +58,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -74,7 +73,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -89,7 +88,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -104,7 +103,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -119,7 +118,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -134,7 +133,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -149,7 +148,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -164,7 +163,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -175,7 +174,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -186,7 +185,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -197,7 +196,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -208,7 +207,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -219,7 +218,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -230,7 +229,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -241,7 +240,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -252,7 +251,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -263,7 +262,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_BARRIERED)
@@ -278,7 +277,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -293,7 +292,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -308,7 +307,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -323,7 +322,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -338,7 +337,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -353,7 +352,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -368,7 +367,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -383,7 +382,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -398,7 +397,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -409,7 +408,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -420,7 +419,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -431,7 +430,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -442,7 +441,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -453,7 +452,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -464,7 +463,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -475,7 +474,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -486,7 +485,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
@@ -497,7 +496,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_BARRIERED)
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/ObjectAccess.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/ObjectAccess.java	Mon Jun 08 18:47:58 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,10 +22,9 @@
  */
 package com.oracle.graal.word;
 
-import com.oracle.jvmci.meta.LocationIdentity;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.word.Word.Opcode;
 import com.oracle.graal.word.Word.Operation;
+import com.oracle.jvmci.meta.*;
 
 /**
  * Low-level memory access for Objects. Similarly to the readXxx and writeXxx methods defined for
@@ -44,7 +43,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -59,7 +58,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -74,7 +73,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -89,7 +88,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -104,7 +103,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -119,7 +118,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -134,7 +133,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -149,7 +148,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -164,7 +163,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -175,7 +174,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -186,7 +185,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -197,7 +196,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -208,7 +207,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -219,7 +218,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -230,7 +229,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -241,7 +240,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -252,7 +251,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -263,7 +262,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     @Operation(opcode = Opcode.READ_OBJECT)
@@ -278,7 +277,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -293,7 +292,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -308,7 +307,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -323,7 +322,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -338,7 +337,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -353,7 +352,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -368,7 +367,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -383,7 +382,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -398,7 +397,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -409,7 +408,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -420,7 +419,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -431,7 +430,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -442,7 +441,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -453,7 +452,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -464,7 +463,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -475,7 +474,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -486,7 +485,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
@@ -497,7 +496,7 @@
      *
      * @param object the base object for the memory access
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     @Operation(opcode = Opcode.WRITE_OBJECT)
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,9 +22,8 @@
  */
 package com.oracle.graal.word;
 
-import com.oracle.jvmci.meta.LocationIdentity;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.jvmci.meta.*;
 
 /**
  * Lowest-level memory access of native C memory. These methods access the raw memory without any
@@ -55,7 +54,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     byte readByte(WordBase offset, LocationIdentity locationIdentity);
@@ -69,7 +68,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     char readChar(WordBase offset, LocationIdentity locationIdentity);
@@ -83,7 +82,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     short readShort(WordBase offset, LocationIdentity locationIdentity);
@@ -97,7 +96,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     int readInt(WordBase offset, LocationIdentity locationIdentity);
@@ -111,7 +110,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     long readLong(WordBase offset, LocationIdentity locationIdentity);
@@ -125,7 +124,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     float readFloat(WordBase offset, LocationIdentity locationIdentity);
@@ -139,7 +138,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     double readDouble(WordBase offset, LocationIdentity locationIdentity);
@@ -153,7 +152,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     Word readWord(WordBase offset, LocationIdentity locationIdentity);
@@ -167,7 +166,7 @@
      * 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})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     Object readObject(WordBase offset, LocationIdentity locationIdentity);
@@ -177,7 +176,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     byte readByte(int offset, LocationIdentity locationIdentity);
@@ -187,7 +186,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     char readChar(int offset, LocationIdentity locationIdentity);
@@ -197,7 +196,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     short readShort(int offset, LocationIdentity locationIdentity);
@@ -207,7 +206,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     int readInt(int offset, LocationIdentity locationIdentity);
@@ -217,7 +216,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     long readLong(int offset, LocationIdentity locationIdentity);
@@ -227,7 +226,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     float readFloat(int offset, LocationIdentity locationIdentity);
@@ -237,7 +236,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     double readDouble(int offset, LocationIdentity locationIdentity);
@@ -247,7 +246,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     Word readWord(int offset, LocationIdentity locationIdentity);
@@ -257,7 +256,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @param locationIdentity the identity of the read
      * @return the result of the memory access
      */
     Object readObject(int offset, LocationIdentity locationIdentity);
@@ -271,7 +270,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity);
@@ -285,7 +284,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeChar(WordBase offset, char val, LocationIdentity locationIdentity);
@@ -299,7 +298,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeShort(WordBase offset, short val, LocationIdentity locationIdentity);
@@ -313,7 +312,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeInt(WordBase offset, int val, LocationIdentity locationIdentity);
@@ -327,7 +326,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeLong(WordBase offset, long val, LocationIdentity locationIdentity);
@@ -341,7 +340,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity);
@@ -355,7 +354,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity);
@@ -369,7 +368,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
@@ -383,7 +382,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity);
@@ -397,7 +396,7 @@
      * 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 locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
@@ -407,7 +406,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeByte(int offset, byte val, LocationIdentity locationIdentity);
@@ -417,7 +416,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeChar(int offset, char val, LocationIdentity locationIdentity);
@@ -427,7 +426,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeShort(int offset, short val, LocationIdentity locationIdentity);
@@ -437,7 +436,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeInt(int offset, int val, LocationIdentity locationIdentity);
@@ -447,7 +446,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeLong(int offset, long val, LocationIdentity locationIdentity);
@@ -457,7 +456,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeFloat(int offset, float val, LocationIdentity locationIdentity);
@@ -467,7 +466,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeDouble(int offset, double val, LocationIdentity locationIdentity);
@@ -477,7 +476,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeWord(int offset, WordBase val, LocationIdentity locationIdentity);
@@ -487,7 +486,7 @@
      * are in bytes. The memory must be uninitialized or zero prior to this operation.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void initializeLong(int offset, long val, LocationIdentity locationIdentity);
@@ -497,7 +496,7 @@
      * bytes.
      *
      * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param locationIdentity the identity of the write
      * @param val the value to be written to memory
      */
     void writeObject(int offset, Object val, LocationIdentity locationIdentity);
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Mon Jun 08 18:47:58 2015 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.word;
 
-import com.oracle.jvmci.code.UnsignedMath;
-import com.oracle.jvmci.meta.LocationIdentity;
 import static com.oracle.jvmci.common.UnsafeAccess.*;
 
 import java.lang.annotation.*;
@@ -32,7 +30,10 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
+import com.oracle.graal.nodes.memory.address.AddressNode.Address;
+import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.common.*;
+import com.oracle.jvmci.meta.*;
 
 public abstract class Word implements Signed, Unsigned, Pointer {
 
@@ -73,7 +74,7 @@
          FROM_SIGNED,
          FROM_OBJECT,
          FROM_WORDBASE,
-         FROM_ARRAY,
+         FROM_ADDRESS,
          TO_OBJECT,
          TO_RAW_VALUE,
     }
@@ -177,8 +178,8 @@
     @Operation(opcode = Opcode.FROM_OBJECT)
     public static native Pointer fromObject(Object val);
 
-    @Operation(opcode = Opcode.FROM_ARRAY)
-    public static native Pointer fromArray(Object oop, Object location);
+    @Operation(opcode = Opcode.FROM_ADDRESS)
+    public static native Pointer fromAddress(Address address);
 
     @Override
     @Operation(opcode = Opcode.TO_OBJECT)
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.word.nodes;
-
-import com.oracle.jvmci.meta.Value;
-import com.oracle.jvmci.meta.LocationIdentity;
-import static com.oracle.jvmci.meta.LocationIdentity.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.lir.gen.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.jvmci.common.*;
-
-/**
- * Location node that can be used inside a snippet without having the elements (including the
- * location identity and kind) as a snippet constant. Can represent locations in the form of [base +
- * index * scale + disp]. When the location is created, all elements (base, index, scale, disp) are
- * nodes. Both scale and disp must eventually canonicalize to {@link ConstantNode constants} so that
- * this node can be canonicalized to a {@link IndexedLocationNode} or {@link ConstantLocationNode}.
- */
-@NodeInfo
-public final class SnippetLocationNode extends LocationNode implements Canonicalizable {
-    public static final NodeClass<SnippetLocationNode> TYPE = NodeClass.create(SnippetLocationNode.class);
-
-    protected final SnippetReflectionProvider snippetReflection;
-
-    @Input(InputType.Association) ValueNode locationIdentity;
-    @Input ValueNode displacement;
-    @Input ValueNode index;
-    @Input ValueNode indexScaling;
-
-    public SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode displacement) {
-        this(snippetReflection, locationIdentity, displacement, null, null);
-    }
-
-    public SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode displacement, ValueNode index, ValueNode indexScaling) {
-        super(TYPE, StampFactory.object());
-        this.snippetReflection = snippetReflection;
-        this.locationIdentity = locationIdentity;
-        this.displacement = displacement;
-        this.index = index;
-        this.indexScaling = indexScaling;
-    }
-
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        if (locationIdentity.isConstant()) {
-            LocationIdentity identity = snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant());
-            return identity;
-        }
-        // We do not know our actual location identity yet, so be conservative.
-        return any();
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (locationIdentity.isConstant() && displacement.isConstant() && (indexScaling == null || indexScaling.isConstant())) {
-            LocationIdentity constLocation = snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant());
-            long constDisplacement = displacement.asJavaConstant().asLong();
-            int constIndexScaling = indexScaling == null ? 0 : indexScaling.asJavaConstant().asInt();
-
-            if (index == null || constIndexScaling == 0) {
-                return graph().unique(new ConstantLocationNode(constLocation, constDisplacement));
-            } else if (index.isConstant()) {
-                return graph().unique(new ConstantLocationNode(constLocation, index.asJavaConstant().asLong() * constIndexScaling + constDisplacement));
-            } else {
-                return graph().unique(new IndexedLocationNode(constLocation, constDisplacement, index, constIndexScaling));
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
-        throw new JVMCIError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity);
-    }
-
-    @Override
-    public IntegerStamp getDisplacementStamp() {
-        throw JVMCIError.shouldNotReachHere();
-    }
-
-    @NodeIntrinsic
-    public static native Location constantLocation(LocationIdentity identity, long displacement);
-
-    @NodeIntrinsic
-    public static native Location indexedLocation(LocationIdentity identity, long displacement, int index, int indexScaling);
-}
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Mon Jun 08 15:57:52 2015 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Mon Jun 08 18:47:58 2015 +0200
@@ -56,6 +56,11 @@
         return new WordCastNode(StampFactory.forKind(wordKind), input);
     }
 
+    public static WordCastNode addressToWord(ValueNode input, Kind wordKind) {
+        assert input.stamp() instanceof AbstractPointerStamp;
+        return new WordCastNode(StampFactory.forKind(wordKind), input);
+    }
+
     public WordCastNode(Stamp stamp, ValueNode input) {
         super(TYPE, stamp);
         this.input = input;